API para socios (B2B)
Errors & rate limits
Partner API error codes, per-key rate limits with X-RateLimit headers, and how to retry.
On this page
Error format#
Los cuerpos de error tienen la forma { statusCode, code, message }. message es texto legible en inglés y puede cambiar, así que basa siempre la lógica en code.
// Success
{ "success": true, "data": ..., "total": 128, "page": 1, "limit": 20 }
// Error
{ "statusCode": 401, "code": "INVALID_API_KEY", "message": "The API key is invalid." }Nota
Error codes#
| HTTP | code | Significado y solución |
|---|---|---|
| 401 | API_KEY_REQUIRED | No se envió ninguna clave: añade el encabezado X-API-Key |
| 401 | INVALID_API_KEY | Clave mal formada o desconocida: comprueba que no se haya copiado incompleta y que no sea una clave de la API pública |
| 401 | KEY_REVOKED | Clave revocada: genera una nueva |
| 401 | KEY_EXPIRED | Clave caducada (incluida una clave antigua tras el periodo de gracia de rotación): usa la nueva clave |
| 403 | PARTNER_SUSPENDED | La cuenta no está activa: contacta con esimoa |
| 403 | INSUFFICIENT_SCOPE | Solicitud fuera de los ámbitos de la clave |
| 403 | IP_NOT_ALLOWED | Llamada desde una IP fuera de la lista de permitidas: añade la IP de salida de tu servidor |
| 404 | PRODUCT_NOT_FOUND | Producto desconocido o descatalogado |
| 429 | RATE_LIMITED | Límite de solicitudes superado: reintenta tras los segundos indicados en Retry-After |
Rate limits#
Nota
Las solicitudes a la API B2B tienen un límite predeterminado de 20,000 por hora y clave.
La ventana de 3,600 segundos empieza con la primera solicitud; el límite por minuto también se aplica. Las cuotas cuentan llamadas, no MB transferidos. La configuración operativa puede cambiar la cuota.
X-RateLimit-Hour-Limit · X-RateLimit-Hour-Remaining · X-RateLimit-Hour-Reset
Estas cabeceras indican el límite por hora, las llamadas restantes y la hora de restablecimiento (segundos Unix). Al agotar el límite por hora se devuelve HTTP 429 y Retry-After en segundos. Las llamadas rechazadas por el límite por minuto no cuentan para la cuota por hora.
El valor predeterminado es de 300 solicitudes por minuto por clave (por ventana de 60 segundos, compartida entre todos los servidores). esimoa puede aumentarlo por cuenta según tu contrato. Cada respuesta autenticada incluye cabeceras de cuota.
X-RateLimit-Limit— solicitudes permitidas por minutoX-RateLimit-Remaining— solicitudes restantes en el intervalo actualX-RateLimit-Reset— cuándo se restablece el intervalo (segundos Unix)Retry-After— con 429, segundos que debes esperar antes de reintentar
HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1790000000
HTTP/1.1 429 Too Many Requests
Retry-After: 18
{ "statusCode": 429, "code": "RATE_LIMITED", "message": "Rate limit exceeded (300 requests per minute)." }Retrying#
- Si recibes un 429, espera los segundos indicados en Retry-After y vuelve a intentarlo.
- Reintenta los errores 5xx unas cuantas veces con retroceso exponencial.
- 400, 401, 403 y 404 no cambiarán al reintentar: corrige la causa.
- Si guardas el catálogo en caché unos minutos, te mantendrás muy por debajo del límite.
async function b2bFetch(url, attempt = 0) {
const res = await fetch(url, { headers: { 'X-API-Key': process.env.ESIMOA_PARTNER_KEY } });
if (res.status === 429 && attempt < 3) {
const wait = Number(res.headers.get('Retry-After') ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
return b2bFetch(url, attempt + 1);
}
const body = await res.json();
if (!res.ok) throw Object.assign(new Error(body.message), { code: body.code, status: res.status });
return body;
}