Factuarea APIDevelopers

Límites de peticiones

Cuotas por clave, empresa y cartera gestionada según el tier. Cabeceras X-RateLimit-* y back-off recomendado.

La API pública evalúa tres ejes de cuota para garantizar la equidad entre tenants y proteger el backend frente a picos:

  1. API key — ventana deslizante por minuto y volumen mensual.
  2. Empresa — el agregado de todas las claves de la empresa.
  3. Cartera gestionada — la empresa gestora y todas sus hijas activas, solo cuando la credencial pertenece a una cartera.

Los límites dependen del tier de tu API key. El tier se deriva del plan de Factuarea de tu empresa: nunca se fija por clave ni por petición, no existe una compra de capacidad independiente y se actualiza automáticamente cuando cambia el plan. Solo las migraciones históricas grandfathered_addon pueden conservar un tier superior, y únicamente mientras la empresa mantenga un plan activo válido.

Niveles

TierClave/minClave/mesEmpresa/minEmpresa/mesIncluido con
Free1010010100El trial de 10 días.
Starter305.0009015.000El plan Emprendedor.
Pro30050.000900150.000El plan Empresario.
Scale1.2005.000.0003.60015.000.000El plan Enterprise.

Los límites por clave se aplican. Los agregados por empresa están presentes en el contrato y, en la versión entrante de la aplicación, funcionan en modo de observación (shadow): miden los rechazos que habrían ocurrido sin devolver 429. No trates ese modo como capacidad contratada; puede promocionarse a aplicación efectiva después de calibrarlo sin cambiar la forma de la petición ni de la respuesta.

Las claves fact_test_ siguen consumiendo su cuota por clave, pero los ejes agregados de empresa y cartera omiten las empresas sandbox para que el tráfico de prueba no consuma capacidad agregada de producción.

Ventana deslizante

El cubo por minuto no es una ventana fija de "60 segundos desde las 12:00". Es una ventana deslizante: en cualquier momento, la API cuenta cuántas peticiones aceptadas hay en los últimos 60 segundos para tu clave. Cuando el contador iguala al límite, las peticiones siguientes responden 429 hasta que pase suficiente tiempo para que las primeras peticiones "salgan" de la ventana.

Por qué: no hay un "minuto de gracia" cada 60 segundos en el que pudieras enviar el doble del límite. Más justo y más estable bajo tráfico real.

Techos de empresa y cartera

Cuando los ejes agregados están en aplicación efectiva, la API evalúa primero la clave, después la empresa y por último la cartera gestionada. Un rechazo de empresa usa company_rate_limit_exceeded o company_monthly_quota_exceeded: añadir claves no eleva esos techos porque se cuentan todas juntas.

Una cartera gestionada tiene un catálogo plano independiente por tier:

TierBanda común/minSuelo reservado por empresa activa/minCartera/mesClaves activas en cartera
Free10101001
Starter18020150.00015
Pro1.800301.500.000500
Scale7.2006050.000.0002.000

El suelo reservado por empresa se evalúa primero. Una hija por debajo de su suelo puede seguir aunque la banda común se haya agotado; la banda común no es, por tanto, un total absoluto de la cartera. La cuota mensual no tiene suelo y agrega toda la cartera. Estos valores también están actualmente en modo shadow, pendientes de calibración con tráfico real de cierre.

Los rechazos de cartera usan portfolio_rate_limit_exceeded y portfolio_monthly_quota_exceeded. Crear más empresas hijas o API keys no eleva un techo plano de cartera; reparte el trabajo en el tiempo o solicita una ampliación auditada para la empresa.

Cabeceras de respuesta

Toda respuesta (incluido 429) incluye:

CabeceraSignificado
X-RateLimit-LimitLímite por minuto de tu tier.
X-RateLimit-RemainingPeticiones restantes en la ventana actual.
X-RateLimit-ResetTimestamp UNIX en el que se libera un hueco (una petición sale de la ventana).
Retry-AfterSolo en 429. Segundos hasta que puedas reintentar.

Ejemplo de cabeceras en una respuesta 200:

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

Y en un 429:

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

Código de error

{
  "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_..."
  }
}

El code estable identifica qué eje aplicado se ha agotado:

EjePor minutoPor mes
API keyrate_limit_exceededrate_limit_exceeded
Empresacompany_rate_limit_exceededcompany_monthly_quota_exceeded
Cartera gestionadaportfolio_rate_limit_exceededportfolio_monthly_quota_exceeded

Todos usan type: rate_limit_error. Respeta Retry-After cuando aparezca; los errores de cartera también publican el instante o los segundos de reintento en error.details. Los fallos de autenticación repetidos se limitan por separado con code: too_many_auth_failures.

Buenas prácticas

1. Respeta 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. Back-off exponencial con jitter

Para 5xx, donde no hay 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. Monitoriza X-RateLimit-Remaining

Si tu integración se acerca de forma consistente al 10% del límite, considera:

  • Cambiar a un plan con un tier superior.
  • Agrupar en lotes: en lugar de N POSTs, agrega y haz 1 POST.
  • Cachear lecturas frecuentes (productos, impuestos, series).
  • Suscribirte a webhooks en lugar de hacer polling.

4. Webhooks > polling

Si haces polling de /v1/invoices?status=paid cada minuto para detectar pagos consumes 30 rpm solo para eso. Suscríbete al evento invoice.paid y reduce eso a 0 peticiones.

5. Claves por integración

Si tienes dos integraciones (un dashboard interno + un cron de exportación), crea dos claves distintas: cada clave tiene sus propios cubos por minuto y mensual, así un cron pesado no consume el cubo de la clave del dashboard.

Separar claves no aumenta la capacidad agregada. Los techos de empresa y cartera suman las claves que correspondan; usa más claves para aislamiento y atribución, no para esquivar la cuota.

Cuotas administrativas

Algunas cargas tienen presupuestos de protección independientes de la tasa de peticiones. No consumen los cubos de clave/empresa/cartera ni aparecen en X-RateLimit-*:

CargaCode estableQué se mide
Envíos de emailemail_recipient_budget_exceededDestinatarios distintos en la ventana, sumados entre credenciales.
Entrega de emailemail_delivery_circuit_openCorte temporal de seguridad del proveedor/empresa tras fallos de entrega; no es una cuota.
Cuentas nuevasaccount_probation_limit_exceededCapacidad reducida por antigüedad hasta que la cuenta madura, verifica su censo AEAT o activa una suscripción de pago.
Endpoints PDFpdf_generation_budget_exceededTrabajo de render horario, por empresa o documento (subcode).
Importaciones y subidasupload_in_flight_budget_exceededBytes temporales cruzando el disco a la vez, no almacenamiento ocupado.
Exportaciones empaquetadasexport_budget_exceededDocumentos empaquetados o artefactos generados por hora (subcode).

Estos codes responden 429 con type: rate_limit_error; usa Retry-After o error.details.retry_at cuando existan. Cambiar de credencial no evita un presupuesto de empresa. Un 402 storage_quota_exceeded distinto indica que el almacenamiento persistente agregado de la empresa está lleno y no se libera esperando. Los topes de cantidad de endpoints webhook son capacidad del plan, no un presupuesto 429; consulta Precios.

Subida de tier

Cambiar de tier no requiere rotar claves. Cuando tu plan cambia:

  1. Las nuevas cuotas aplican de inmediato.
  2. La cuota mensual consumida en el tier anterior no se reinicia: solo crece el tope mensual.
  3. Las claves existentes conservan su id; el nuevo tier se aplica a todas automáticamente.

Identidad para enviar documentos

El envío de documentos puede requerir identidad acreditada mediante una suscripción activa o una identificación censal aceptada. Las empresas gestionadas usan la identidad de la gestoría. 422 sender_identity_not_verified requiere corregir esa identidad; un 429 corresponde a un presupuesto de envío distinto. Consulta envío de documentos.

En esta página

¿Te echamos una mano?Contactar con soporte