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
429SíEspera los segundos de la cabecera Retry-After.
502, 503SíCon espera exponencial y un tope de intentos. No se cobran.
500Sí, con cuidadoPocas veces y con espera exponencial.
402NoFalta saldo: compra un paquete o espera. Reintentar no sirve.
400, 401, 403, 404, 409, 422NoCorrige 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 r

JavaScript

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/vencimiento son 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/saldo antes 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) admite ETag: envía If-None-Match y recibirás 304 si no ha cambiado.
  • Los datos del BORME cambian cuando se publica un boletín: consulta /v1/dev/estado para 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-Remaining y X-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-Centimos y X-Jurilia-Saldo-Centimos de cada consulta de pago y alerta cuando el saldo baje de un umbral tuyo.
  • Usa maxCosteCentimos en 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.