Buenas prácticas
Integrar bien: reintentos, caché e idempotencia
Recomendaciones para que tu integración aguante los fallos y no gaste de más.
Reintentos con espera exponencial
No todos los errores se reintentan igual:
| Estado | ¿Reintentar? | Cómo |
|---|---|---|
| 429 | Sí | Espera los segundos de la cabecera Retry-After. |
| 502, 503 | Sí | Con espera exponencial y un tope de intentos. No se cobran. |
| 500 | Sí, con cuidado | Pocas veces y con espera exponencial. |
| 402 | No | Falta saldo: compra un paquete o espera. Reintentar no sirve. |
| 400, 401, 403, 404, 409, 422 | No | Corrige la petición, la clave o los datos. |
Un reintento con espera exponencial y variación aleatoria
curl
# En shell, con --retry: reintenta 429 y 5xx con espera creciente
curl --retry 4 --retry-all-errors "https://app.jurilia.com/v1/dev/ping" \
-H "Authorization: Bearer TU_CLAVE"Python
import random, time, requests
def llamar(url, intentos=5, **kw):
for n in range(intentos):
r = requests.get(url, headers={"Authorization": "Bearer TU_CLAVE"}, **kw)
if r.status_code not in (429, 500, 502, 503):
return r
espera = float(r.headers.get("Retry-After", 2 ** n)) + random.random()
time.sleep(espera)
return rJavaScript
async function llamar(url, intentos = 5) {
let r;
for (let n = 0; n < intentos; n++) {
r = await fetch(url, { headers: { Authorization: "Bearer TU_CLAVE" } });
if (![429, 500, 502, 503].includes(r.status)) return r;
const espera = Number(r.headers.get("Retry-After") ?? 2 ** n) + Math.random();
await new Promise((ok) => setTimeout(ok, espera * 1000));
}
return r;
}Idempotencia: qué se puede repetir sin riesgo
- Todos los GET son lecturas: repetirlos no cambia nada (aunque los de pago se cobran cada vez).
- Las calculadoras y
plazos/vencimientoson POST «puros»: no guardan nada y son gratis, así que repetirlos es seguro. - El asistente (POST) NO tiene clave de idempotencia: cada llamada es una consulta nueva y se cobra. Si pierdes la respuesta por un corte de red, no sabes si se cobró; vuelve a mirar
GET /v1/dev/saldoantes de reintentar. Los reintentos automáticos sólo son seguros tras un 502 o 503, que no se cobran.
Caché
- Cachea lo que repites: un artículo pedido con una fecha fija (
cita+fecha) es la misma consulta cada vez, y ahorra llamadas al límite por minuto. Vuelve a pedirlo cuando necesites estar al día. - El catálogo de normas (
/biblioteca/abreviaturas) admiteETag: envíaIf-None-Matchy recibirás 304 si no ha cambiado. - Los datos del BORME cambian cuando se publica un boletín: consulta
/v1/dev/estadopara saber cuál es el último día cargado y no repitas lo que no ha cambiado. - No caches respuestas del asistente como si fueran definitivas: nacen «propuesto» y dependen del estado de la biblioteca.
Respeta los límites
- Cada clave admite 120 llamadas por minuto. Toda respuesta lleva
X-RateLimit-Limit,X-RateLimit-RemainingyX-RateLimit-Reset(instante Unix en segundos): úsalas para repartir las llamadas en vez de provocar un 429. - Procesos masivos: reparte la carga en el tiempo, no la lances de golpe.
- El límite también cuenta en las APIs gratuitas.
Controla el gasto
- Lee
X-Jurilia-Coste-CentimosyX-Jurilia-Saldo-Centimosde cada consulta de pago y alerta cuando el saldo baje de un umbral tuyo. - Usa
maxCosteCentimosen el asistente si quieres un tope por pregunta. - Valida los datos antes de llamar: un 400 no se cobra, pero gasta una llamada de tu límite por minuto.
Nada de lo generado es definitivo
Las respuestas del asistente y los cálculos son propuestas con su fuente: muéstralas con su aviso y su cita, y deja que un abogado las valide antes de usarlas en un escrito.