Límites y reintentos
La API la comparten todas las clínicas de Odontosys, así que tiene límites. Con un uso normal —un sitio de reservas, una central de citas— no se llega a ninguno. Están para frenar un error de programación (un bucle que no termina) antes de que afecte a los demás.
Los límites
| Límite | Valor | Alcance | Al pasarse |
|---|---|---|---|
| Pedidos por minuto | 60, con ráfagas de hasta 5 seguidos | Por clave | 429 limite_por_minuto |
| Pedidos a la vez | 3 lecturas y 1 escritura (un POST o un DELETE) |
Por clave | 429 demasiadas_solicitudes_en_curso |
| Altas por día | 100 citas creadas | Por clínica (todas sus claves juntas) | 429 cupo_diario_agotado |
| Bajas por día | 50 citas eliminadas | Por clínica | 429 cupo_diario_agotado |
| Lecturas por día | 5.000 | Por clínica | 429 cupo_diario_agotado |
| Claves equivocadas | 10 por minuto desde la misma IP | Por IP | 401 no_autenticado, aunque la clave sea buena, hasta que pase el minuto |
El día es el de la clínica: se reinicia a la medianoche de su zona horaria. GET /ping muestra los límites de tu clave y lo que la clínica lleva usado hoy.
Los "60 por minuto con ráfagas de 5" funcionan como un balde: entran 5 pedidos de golpe y después uno por segundo. Un integrador que manda de a uno, esperando cada respuesta, nunca lo toca.
La API también tiene un freno general para protegerse: si recibe más pedidos de los que puede atender, responde 503 no_disponible a cualquiera. Mandar ráfagas grandes te puede llevar a ese freno antes que a tu propio límite.
Las cabeceras
Toda respuesta a un pedido con una clave válida trae:
| Cabecera | Qué dice |
|---|---|
RateLimit-Limit |
Pedidos por minuto de la clave |
RateLimit-Remaining |
Cuántos podés mandar ya |
RateLimit-Reset |
En cuántos segundos se llena el balde |
Retry-After |
En los 429 y 503: cuántos segundos esperar antes de reintentar |
Cómo reintentar
- Respetá
Retry-After. Es el dato exacto: no reintentes antes. - No reintentes en bucle los errores que no son pasajeros (
400,401,403,404,409,410,422): el mismo pedido va a dar lo mismo, y cada rechazo cuenta. - Ante un
500o un corte de red, reintentá pocas veces y cada vez más espaciado (por ejemplo, a los 2, 4 y 8 segundos) y después rendite y registralo. - Un
POSTse reintenta con la mismareferenciaExterna: si la primera vez la cita llegó a crearse, la API devuelve esa misma en vez de duplicarla (ver Reintentar sin duplicar). - Una escritura por vez por clave. Si tu sistema procesa reservas en paralelo, encolalas.
async function conReintentos(pedido, intentos = 4) {
for (let i = 1; ; i++) {
const r = await pedido();
if (r.status !== 429 && r.status !== 503 && r.status < 500) return r;
if (i === intentos) return r;
const espera = Number(r.headers.get("Retry-After")) || 2 ** i;
await new Promise((listo) => setTimeout(listo, espera * 1000));
}
}
Ahorrar pedidos
- No consultes la disponibilidad en cada visita: guardala unos minutos. Y antes de volver a pedir las citas de una agenda, mirá si cambió su
ultimoCambioenGET /agendas. - Pedí rangos, no días sueltos: un pedido de
disponibilidadcubre hasta 31 días. - Paginá con
porPagina=200si necesitás muchas citas.
Si tu integración necesita más de lo que dan estos límites, escribinos: ver Soporte.