Factuarea API
Core concepts

Rate limits

Per-minute and monthly quotas per tier. X-RateLimit-* headers and recommended back-off.

The public API enforces two quota levels to guarantee fairness between tenants and protect the backend from bursts:

  1. Per-minute quota (sliding window).
  2. Monthly quota (natural calendar, resets on day 1 at 00:00 Europe/Madrid).

The limits depend on your API key tier. The default tier on key creation is controlled from Developers > API Keys > Settings > Default tier, and can be overridden per key from the dashboard.

Tiers

TierPer minutePer monthCost
Free10 rpm100 requestsIncluded in any plan.
Starter30 rpm5,000developer_api Starter add-on (€4.90/mo).
Pro300 rpm50,000developer_api Pro add-on (€19.90/mo).
ScaleCustomCustomContact sales.

Tiers are cumulative: once the monthly quota is exhausted you get 429 rate_limit_exceeded until day 1 of the next month. The per-minute quota resets on a sliding window.

Sliding window

The per-minute bucket is not a fixed window "60 seconds since 12:00". It's a sliding window: at any point, the API counts how many accepted requests there are in the last 60 seconds for your key. When the counter equals the limit, subsequent requests respond 429 until enough time has passed for the early requests to "drop off" the window.

Why: there's no "grace minute" every 60 seconds where you could send twice the limit. Fairer and more stable under real traffic.

Response headers

Every response (including 429) includes:

HeaderMeaning
X-RateLimit-LimitPer-minute limit of your tier.
X-RateLimit-RemainingRequests remaining in the current window.
X-RateLimit-ResetUNIX timestamp when a slot frees up (one slot exits the window).
Retry-AfterOnly on 429. Seconds until you can retry.

Example headers on a 200 response:

HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1747314060

And on a 429:

HTTP/1.1 429 Too Many Requests
Retry-After: 7
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1747314007

Error code

{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Has superado el límite de peticiones. Vuelve a intentarlo en unos segundos.",
    "request_id": "req_..."
  }
}

Exceeding the per-minute or monthly quota responds 429 with type: rate_limit_error and code: rate_limit_exceeded. The Retry-After header (and the message) tell you how long to wait. Repeated authentication failures are throttled separately with code: too_many_auth_failures.

Best practices

1. Respect Retry-After

import time, requests

def call_with_retry(url, **kwargs):
    while True:
        resp = requests.get(url, **kwargs)
        if resp.status_code != 429:
            return resp
        sleep = int(resp.headers.get('Retry-After', 1))
        time.sleep(sleep)

2. Exponential back-off with jitter

For 5xx, where there's no Retry-After:

import random, time

def backoff(attempt):
    return min(60, (2 ** attempt) * 0.1 + random.uniform(0, 0.5))

for attempt in range(5):
    resp = requests.get(url)
    if resp.status_code < 500:
        break
    time.sleep(backoff(attempt))

3. Monitor X-RateLimit-Remaining

If your integration consistently approaches 10% of the limit, consider:

  • Upgrading tier.
  • Batching: instead of N POSTs, aggregate and do 1 POST.
  • Caching frequent reads (products, taxes, series).
  • Subscribing to webhooks instead of polling.

4. Webhooks > polling

If you poll /v1/invoices?status=paid every minute to detect payments you consume 30 rpm just for that. Subscribe to the invoice.paid event and drop that to 0 requests.

5. Per-integration tier

If you have two integrations (an internal dashboard + an export cron), create two distinct keys with tiers sized for each one. That way a heavy cron doesn't exhaust the budget of an interactive dashboard.

Administrative quotas

Some endpoints have additional quotas independent of the main rate limit:

EndpointQuota
POST /v1/webhook_endpointsLimited number of endpoints per company.
POST /v1/invoices/{id}/sendRate-limited per invoice to avoid duplicate emails.
GET /v1/invoices/{id}/pdfRate-limited PDF generations per minute.

These limits respond 429 with type: rate_limit_error and a specific message.

Tier upgrade

Changing tier does not require rotating keys. After subscribing to a higher add-on:

  1. New quotas apply immediately.
  2. The monthly quota consumed at the previous tier does not reset: only the monthly cap grows.
  3. Existing keys keep their id and tier; manage tiers from the dashboard (Developers > API Keys).

On this page