Límites de tasa (rate limits)

El límite es por API key, por minuto. Cada respuesta autenticada —incluidas las 4xx de scope o validación— te dice exactamente cuánto te queda y cuándo se reinicia, así que no tienes que adivinar.

Headers en cada respuesta

Mandamos dos formatos juntos para máxima compatibilidad: el trío clásico y el par del draft IETF, más el entorno.

HTTP/1.1 200 OK
RateLimit-Limit: 100
RateLimit-Remaining: 98
RateLimit-Reset: 42
RateLimit: "default";r=98;t=42
RateLimit-Policy: "default";q=100;w=60
AllSign-Environment: live
HeaderQué es
RateLimit-LimitTecho de peticiones en la ventana.
RateLimit-RemainingCuántas te quedan en la ventana actual.
RateLimit-ResetSegundos-delta hasta el reinicio (NO epoch). 42 = "en 42 s".
RateLimitHeader draft IETF combinado: r = remaining, t = segundos al reinicio. El techo viaja en RateLimit-Policy.
RateLimit-PolicyLa política: "default";q=100;w=60 = cuota 100 por ventana de 60 s.
AllSign-Environmentlive, test o dev.

El bucket es por principal (tu API key), no por IP: varias IPs con la misma key comparten el cupo. El contador es compartido entre todos los procesos que atienden la API, así que el número que ves es el que se aplica.

Cuánto te toca

El techo viene de tu plan de suscripción activo y aplica igual a las llaves dev, test y live del mismo tenant.

PlanLímite
Sin plan activo10 req/min
Freemium10 req/min
Esencial · Colabora · Conecta100 req/min
Business150 req/min

Si tu suscripción tiene un api_rpm_override acordado con nosotros, ese valor gana sobre el del plan.

Endpoints con límite propio

Tres endpoints tienen además un límite independiente del de tu plan, porque cada llamada cuesta bastante más que una petición normal. Se cuentan por separado: gastar el de uno no consume el presupuesto de otro ni el de tu plan.

EndpointLímitePor qué
POST /v2/documents/{id}/invite-bulk250 participantes/minSe cuentan participantes, no llamadas: cada uno es un envío.
POST /v3/constancias20/minCada llamada es una emisión facturada ante el PSC.
POST /v3/devassist/chat10/minCada turno dispara una llamada a un modelo de lenguaje.

Un 429 de este tipo trae X-RateLimit-Reason: endpoint. Distínguelo del de tu plan (per-tenant) antes de asumir que necesitas otro paquete: si el header dice endpoint, subir de plan no lo cambia.

El 429

Si te pasas del límite recibes 429 RATE_LIMITED (problem+json). Trae el header Retry-After y además el campo retryAfter en el cuerpo — ambos en segundos, y ambos iguales a RateLimit-Reset. No tienes que parsear headers si prefieres leer el body.

HTTP/1.1 429 Too Many Requests
Retry-After: 42
RateLimit-Reset: 42
Content-Type: application/problem+json

{
  "type": "https://developers.allsign.io/errors#RATE_LIMITED",
  "title": "Rate limited",
  "status": 429,
  "code": "RATE_LIMITED",
  "retryAfter": 42,
  "requestId": "req_..."
}

El 429 es seguro de reintentar (idempotency-safe): la petición no se procesó, así que reintentar no duplica nada. Aun así, para POST combina el reintento con tu Idempotency-Key como red de seguridad.

Reintentar con backoff

El patrón correcto: al ver 429, espera lo que diga Retry-After (equivale a RateLimit-Reset) y reintenta; si no viniera, cae a un backoff exponencial.

async function requestWithRetry(doRequest, { maxRetries = 5 } = {}) {
  for (let attempt = 0; ; attempt++) {
    const res = await doRequest();
    if (res.status !== 429 || attempt >= maxRetries) return res;
    // Confía en el servidor: espera lo que dice Retry-After (== RateLimit-Reset).
    const wait = Number(res.headers.get("Retry-After")) || 2 ** attempt;
    await new Promise((r) => setTimeout(r, wait * 1000));
  }
}
import time

def request_with_retry(do_request, max_retries=5):
    for attempt in range(max_retries + 1):
        resp = do_request()
        if resp.status_code != 429 or attempt == max_retries:
            return resp
        wait = int(resp.headers.get("Retry-After", 2 ** attempt))
        time.sleep(wait)

Diferencia con v2

Si vienes de v2, tres cosas cambiaron en los headers de rate limit:

v2v3
X-RateLimit-ResetRateLimit-Reset
Reset = epoch (timestamp Unix)Reset = segundos-delta (cuántos segundos faltan)
Prefijo X- en todosSe cae el prefijo X- (RFC 6648)

Si tu cliente v2 hacía reset - now() para calcular la espera, en v3 el valor ya es la espera en segundos — úsalo directo.

Los X-RateLimit-* siguen viajando en las respuestas v3, por compatibilidad, junto a los nuevos — y conservan su semántica v2: X-RateLimit-Reset es un epoch (timestamp Unix absoluto), no un delta. Si lo lees esperando segundos-para-el-reinicio vas a calcular esperas de décadas. En v3 lee solo los RateLimit-* sin prefijo.