Funcionamiento
Límites de uso
Peticiones y tiempo de consulta por minuto, qué pasa al superarlos, las cabeceras que lo cuentan y por qué conviene usar webhooks en vez de consultar en bucle.
Cada cliente tiene dos límites por minuto. Los dos existen para que una integración que consulta de más no quite capacidad a las alertas de nadie, la tuya incluida.
Los dos límites
| Límite | De serie |
|---|---|
| Peticiones por minuto | 600 |
| Tiempo de consulta por minuto | 30 segundos |
El segundo es menos habitual. Cada petición gasta el tiempo que tarda en resolverse, así que una lista larga cuenta más que una alerta suelta: pedir 500 alertas de un mes consume más de ese presupuesto que pedir una por su id. Si tu integración pide listas grandes a menudo, pagina con limit más bajos o, mejor, deja de consultar y usa webhooks.
Los dos se pueden ampliar por contrato.
El endpoint del token (POST /v1/oauth/token) tiene además su propio límite, por IP. Pide un token por hora y reutilízalo (ver Renovarlo).
Cabeceras
Las respuestas llevan cuánto margen te queda:
| Cabecera | Qué dice |
|---|---|
X-RateLimit-Limit | Tu límite. |
X-RateLimit-Remaining | Lo que te queda en la ventana actual. |
Al superarlos
La API responde 429 en application/problem+json, con la cabecera Retry-After: los segundos que tienes que esperar antes de volver a intentarlo.
async function pedir(url, opciones = {}, intentos = 3) {
const res = await fetch(url, opciones);
if (res.status === 429 && intentos > 0) {
const espera = Number(res.headers.get('Retry-After') ?? 1);
await new Promise((r) => setTimeout(r, espera * 1000));
return pedir(url, opciones, intentos - 1);
}
return res;
}import time
import requests
def pedir(metodo: str, url: str, intentos: int = 3, **kwargs) -> requests.Response:
res = requests.request(metodo, url, timeout=10, **kwargs)
if res.status_code == 429 and intentos > 0:
time.sleep(float(res.headers.get("Retry-After", "1")))
return pedir(metodo, url, intentos - 1, **kwargs)
return resasync Task<HttpResponseMessage> Pedir(Func<Task<HttpResponseMessage>> peticion, int intentos = 3)
{
var res = await peticion();
if ((int)res.StatusCode == 429 && intentos > 0)
{
var espera = res.Headers.RetryAfter?.Delta ?? TimeSpan.FromSeconds(1);
await Task.Delay(espera);
return await Pedir(peticion, intentos - 1);
}
return res;
}Respeta siempre Retry-After. Reintentar antes solo alarga la espera.
Webhooks en vez de consultar en bucle
La causa más común de un 429 es preguntar cada pocos segundos «¿hay alertas nuevas?». Es lo que los webhooks hacen mejor: te llega cada alerta en uno o dos segundos, sin gastar ni una petición.
- Para enterarte de lo que pasa: webhooks.
- Para ponerte al día tras un corte:
GET /v1/events. - Para cargar el estado al arrancar o buscar algo concreto: las listas, paginadas.