Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rail.cl/llms.txt

Use this file to discover all available pages before exploring further.

Límites por tipo de endpoint

Endpoint groupRate limitBurstNotas
Read (GET /v1/links, /v1/accounts, /v1/accounts/{id}/movements, etc)100 req/min por API key20Mismo bucket para todos los GETs
Sync write (POST /v1/refresh_intents)10 req/min por API key5Independiente del cooldown de 5min por link
Widget tokens (POST /v1/widget_tokens)30 req/min por API key10
Resources write (POST /v1/links/{id}/pause, DELETE /v1/links/{id}, etc)30 req/min por API key10
Webhook deliveries (read)60 req/min por API key20
Los límites son por API key, no por client. Si tenés sk_live + sk_test, cada una tiene su propio bucket. Las pk_* comparten bucket con su sk_* del mismo modo.

Headers en cada response

Todos los responses incluyen:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1717434120
HeaderSignifica
X-RateLimit-LimitTu límite efectivo para este bucket (req/min)
X-RateLimit-RemainingCuántos requests te quedan en la ventana actual
X-RateLimit-ResetUnix timestamp de cuándo se resetea el bucket

Cuando excedés — 429

HTTP/2 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1717434143

{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Excediste el límite de 100 req/min para esta API key. Reintentá en 23 segundos."
  }
}
El header Retry-After te dice cuántos segundos esperar antes de reintentar.

Manejo recomendado

async function railFetchWithBackoff(
  path: string,
  opts: RequestInit,
  maxRetries = 3,
): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const res = await fetch(`https://api.rail.cl${path}`, opts);
    if (res.status !== 429) return res;

    if (attempt === maxRetries) return res;

    const retryAfter = Number(res.headers.get('retry-after') ?? '5');
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
  }
  throw new Error('unreachable');
}

Patrones que disparan 429

Anti-patrónPor qué te bloquea
Polear /v1/refresh_intents/{id} cada 1sExcedés 100 req/min en pocos minutos. Polear cada 5-10s en su lugar (o usar webhooks).
Listar todos los movimientos sin paginar bienLoop sin condición de salida = burst inmediato.
Crear un refresh_intent por cada user en un cronHacelo escalonado o usá los syncs automáticos de Rail (cada 4h).

Pedir upgrade

Si tu use case legítimo requiere límites más altos, contactanos en soporte@rail.cl con:
  • Tu client_id (lo ves en el dashboard)
  • Caso de uso + volumen esperado
  • Endpoint/bucket específico
Subimos rate limits caso por caso para clientes con producción estable.