Límites de peticiones
Cada API key tiene un límite de peticiones por minuto. Si lo superas
recibes 429 rate_limited y debes esperar los segundos que indica
Retry-After.
Límites
- El administrador elige el límite de cada producto en el panel: 60, 300 (por defecto) o 1000 peticiones por minuto, por entorno.
- Se cuenta por API key en ventanas fijas de un minuto (alineadas al minuto del reloj). Todas las peticiones de una misma clave suman en el mismo contador, y cada petición se compara con el límite del producto al que pertenece.
- Si necesitas más capacidad para una carga inicial, usa la importación masiva (hasta 500 empleados por petición) o habla con soporte.
Cabeceras
Las peticiones autenticadas que llegan a la comprobación del límite incluyen:
| Cabecera | Significado |
|---|---|
X-RateLimit-Limit | Peticiones permitidas por minuto. |
X-RateLimit-Remaining | Peticiones que quedan en la ventana actual. |
X-RateLimit-Reset | Momento (epoch Unix, segundos) en que empieza la siguiente ventana. |
Retry-After | Solo en 429: segundos que hay que esperar. |
HTTP/1.1 429 Too Many Requests
Retry-After: 17
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1772463660
X-Request-Id: req_0c1d2e3f4a5b6c7d
{"error": {"code": "rate_limited", "message": "Rate limit exceeded. Retry after the indicated number of seconds."}}
Reintentar correctamente
Python
import random
import time
def request_with_retries(session, method, url, max_attempts=5, **kwargs):
for attempt in range(1, max_attempts + 1):
response = session.request(method, url, timeout=30, **kwargs)
if response.status_code == 429:
delay = int(response.headers.get("Retry-After", "1"))
elif response.status_code in (500, 502, 503):
delay = min(2 ** attempt, 30) + random.random()
else:
return response
if attempt == max_attempts:
return response
time.sleep(delay)
JavaScript
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function fetchWithRetries(url, options = {}, maxAttempts = 5) {
for (let attempt = 1; ; attempt++) {
const response = await fetch(url, options);
let delay;
if (response.status === 429) delay = Number(response.headers.get("Retry-After") || 1) * 1000;
else if ([500, 502, 503].includes(response.status)) delay = Math.min(2 ** attempt, 30) * 1000 + Math.random() * 1000;
else return response;
if (attempt === maxAttempts) return response;
await sleep(delay);
}
}
C#
static async Task<HttpResponseMessage> SendWithRetriesAsync(
HttpClient http, Func<HttpRequestMessage> build, int maxAttempts = 5)
{
for (var attempt = 1; ; attempt++)
{
var response = await http.SendAsync(build());
TimeSpan delay;
if ((int)response.StatusCode == 429)
delay = response.Headers.RetryAfter?.Delta ?? TimeSpan.FromSeconds(1);
else if ((int)response.StatusCode is 500 or 502 or 503)
delay = TimeSpan.FromSeconds(Math.Min(Math.Pow(2, attempt), 30) + Random.Shared.NextDouble());
else
return response;
if (attempt == maxAttempts) return response;
await Task.Delay(delay);
}
}
Con Polly (.NET) puedes expresar lo mismo con una política de reintentos
que lea Retry-After. No reintentes errores 4xx distintos de
429.
Además del límite por API key, POST /messages y Verify tienen topes propios
por remitente y teléfono (ver Mensajes y
Verify); también responden 429 rate_limited con
Retry-After. Si esos topes no se pueden comprobar, los envíos
(POST /messages, POST /verify/start) responden
503 limits_unavailable; POST /verify/check no se bloquea.