Cada endpoint protegido lleva un contador por ventana de tiempo. Cuando el contador supera el límite configurado la API devuelve HTTP 429 con los encabezados de recuperación necesarios para reintentar correctamente.
Encabezados en una respuesta 429
Los encabezados de límite de tasa se emiten únicamente en 429 — de forma reactiva, junto con Retry-After. No se incluyen en respuestas 200 ni en ningún otro código de estado.
| Encabezado | Tipo | Descripción |
|---|---|---|
Retry-After | integer | Segundos a esperar antes de reintentar. Coincide con la ventana del bucket del endpoint. |
X-RateLimit-Limit | integer | Límite configurado para el bucket (p. ej. 5 solicitudes/hora). |
X-RateLimit-Remaining | integer | Solicitudes restantes — siempre 0 en el momento del 429. |
X-RateLimit-Reset | integer | Unix epoch absoluto (segundos) en que se reinicia la ventana. |
Ejemplo de respuesta
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1748649600
Content-Type: application/json
{
"errors": [{ "status": "429", "code": "rate_limit_exceeded", "detail": "Rate limit exceeded. Try again in 3600 seconds." }],
"meta": { "version": "1.50.8", "request_id": "f7a8b9c0d1e2" }
}Códigos de error por endpoint
El campo error.code identifica el bucket exacto que se excedió. Algunos endpoints tienen códigos específicos:
| Código | Endpoint / contexto |
|---|---|
rate_limit_exceeded | Genérico (fallback) |
rate_limited_login | POST /v1/auth/login |
rate_limited_twofa | POST /v1/auth/2fa/* |
rate_limited_billing_<family> | Endpoints de billing admin |
broadcast_rate_limited | POST /admin/notifications/broadcasts |
El campo code es el contrato estable — no cambia entre versiones, se puede usar para lógica condicional en el cliente.
Estrategia de reintento recomendada
- Detecta el 429.
- Lee
Retry-After(en segundos) o calcula el tiempo hastaX-RateLimit-Reset. - Espera ese tiempo antes de reintentar.
- Aplica jitter exponencial si el endpoint tiene varios clientes concurrentes.