No atendemos emergencias vitales: llama al 112.

+34 611 673 280

DesarrolladoresAPI v1

Guías

Límites de uso

Cuántas peticiones por minuto admite cada clave, las cabeceras X-RateLimit, qué pasa al superar el límite (429 y Retry-After) y cómo reintentar bien.

Última revisión: 1 de octubre de 2026

Límite por clave

Cada clave de API tiene un límite de peticiones por minuto. Por defecto son 60 peticiones por minuto, y se puede ajustar por clave según tu volumen: si lo necesitas, pídenos que lo subamos y dinos para qué.

  • El límite va por clave, no por IP ni por organización: si tienes dos claves, cada una tiene el suyo.
  • Se cuenta en ventanas de un minuto de reloj: el contador vuelve a cero al empezar cada minuto.
  • Cuentan todas las peticiones con una clave válida y el ámbito necesario, también las que acaban en error de validación. Las rechazadas con 401 o 403 no cuentan.
  • Los webhooks que te enviamos no cuentan: no son peticiones tuyas.

Cabeceras

Todas las respuestas autenticadas llevan:

CabeceraSignificado
X-RateLimit-LimitPeticiones por minuto que admite tu clave.
X-RateLimit-RemainingPeticiones que te quedan en el minuto en curso.
HTTP
HTTP/1.1 200 OK
X-Serad-Environment: production
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57

Al superar el límite

Si te pasas, la API responde 429 Too Many Requests con la cabecera Retry-After (segundos hasta que empieza el siguiente minuto) y un cuerpo RFC 9457:

HTTP
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0

{
  "type": "/errors/provider-api/rate-limited",
  "title": "Demasiadas peticiones",
  "status": 429,
  "detail": "Se ha superado el límite de la clave de API. Reintenta en 23 s",
  "instance": "/api/integrations/v1/visits",
  "timestamp": "2026-10-01T09:10:37.000Z"
}

La petición rechazada no se ha ejecutado: si era un alta, no se ha creado el aviso. Espera lo que dice Retry-After y repítela (con la misma Idempotency-Key).

Estrategia de reintento

No todos los errores se reintentan. La regla:

Respuesta¿Reintentar?Cómo
429SíEspera exactamente Retry-After segundos.
500, 502, 503, 504, error de red, tiempo agotadoSíEspera exponencial con variación aleatoria: 1 s, 2 s, 4 s, 8 s… hasta un máximo (por ejemplo, 5 intentos o 1 minuto).
409 idempotency-in-progressSíUnos segundos, con la misma Idempotency-Key.
400, 401, 403, 404, 409 (resto)NoEs un error de la petición: corrígelo. Reintentar daría lo mismo.

Y siempre:

  • Reintenta las altas con la misma Idempotency-Key (idempotencia), o podrías crear avisos duplicados.
  • Añade una variación aleatoria (jitter) a las esperas: si muchos procesos tuyos fallan a la vez, que no reintenten todos en el mismo segundo.
  • Pon un tope. Si después de los reintentos sigue fallando, registra el error, avisa a una persona y, si el aviso es urgente, que llame a la centralita (+34 611 673 280).
// Reintento con espera exponencial, jitter y respeto a Retry-After.
async function seradFetch(url: string, init: RequestInit, maxAttempts = 5): Promise<Response> {
  for (let attempt = 1; ; attempt++) {
    let response: Response | null = null;
    try {
      response = await fetch(url, { ...init, signal: AbortSignal.timeout(15_000) });
    } catch {
      // Error de red o tiempo agotado: se reintenta abajo.
    }

    const retryable = !response || response.status === 429 || response.status >= 500;
    if (!retryable || attempt >= maxAttempts) {
      if (!response) throw new Error('La API de Salud en Ruta no responde');
      return response;
    }

    const retryAfter = Number(response?.headers.get('Retry-After'));
    const backoff = Math.min(60_000, 1000 * 2 ** (attempt - 1));
    const waitMs = response?.status === 429 && retryAfter > 0 ? retryAfter * 1000 : backoff * (0.5 + Math.random());
    await new Promise((resolve) => setTimeout(resolve, waitMs));
  }
}

¿Falta algo o algo no cuadra con lo que ves? Escribe al equipo técnico: info@saludenruta.es.