08 — Política de reintentos
Calendario de reintentos
Un evento fallido se reintenta hasta 8 intentos en total, con espera creciente entre cada uno:
| Intento | Espera desde el intento anterior | Tiempo acumulado desde el fallo original |
|---|---|---|
| 1 | — (inmediato) | 0 s |
| 2 | 1 s | 1 s |
| 3 | 5 s | 6 s |
| 4 | 30 s | 36 s |
| 5 | ~4 min 24 s | 5 min |
| 6 | 30 min | 35 min |
| 7 | ~1 h 55 min | 2 h 30 min |
| 8 | ~9 h 30 min | 12 h |
Si el intento 8 también falla, la entrega pasa a ABANDONED y no se
reintenta más automáticamente — a partir de ahí, solo un reintento manual
la reactiva (ver abajo).
Qué se reenvía
Cada intento, automático o manual, reenvía el mismo evento: mismo id,
created_at y data, tal como quedaron al ocurrir. No se vuelve a armar con
el estado actual del cobro; si necesitas el estado de ahora, consulta
GET /v1/transactions/{id}. También se repiten X-Yallego-Event-Id y
X-Yallego-Delivery-Id. Solo cambian X-Yallego-Timestamp y la firma, que se
calcula en cada intento sobre el cuerpo enviado.
Entre un intento y el siguiente la entrega queda en PENDING, con
next_attempt_at y el resultado del intento anterior en last_status_code y
last_error (ver historial de entregas).
Las entregas creadas antes de que el sobre incluyera tenant_id y livemode
se reenvían con esos dos campos agregados; el resto del evento no cambia.
Qué cuenta como fallo
- Cualquier código de respuesta fuera del rango
2xx. - Timeout: tu endpoint tiene 10 segundos para responder antes de que Yallegó considere el intento fallido.
- Error de red (conexión rechazada, TLS, corte).
- Una redirección (
3xx): las entregas no siguen redirecciones — si tu endpoint responde con un301/302, cuenta como fallo. Configura la URL registrada para que apunte directo al destino final. - El dominio no resuelve: antes de cada intento Yallegó resuelve el dominio de
tu URL. Si la consulta falla (el dominio no existe, el DNS no responde o
tarda más de 5 segundos), el intento cuenta como fallido sin enviarse:
last_status_codequeda ennullylast_errordice «No se pudo resolver el dominio del webhook (CÓDIGO).», por ejemplo conENOTFOUNDoEAI_AGAIN. Un corte de DNS de tu lado retrasa las entregas, no las pierde.
Todos esos fallos siguen el calendario. Dos casos no lo siguen y abandonan la entrega en el acto, sin más reintentos:
410 Gone(abajo).- El dominio resuelve a una red interna: si alguna de las direcciones de tu
dominio es privada, de loopback o de otro rango reservado, la entrega pasa a
ABANDONEDsin enviarse y cuenta como un fallo consecutivo del endpoint. Es una protección de seguridad (SSRF), no un error pasajero.
La excepción: 410 Gone
Si tu endpoint responde explícitamente 410 Gone, Yallegó lo interpreta
como "este endpoint ya no existe, deja de intentar" — la entrega se marca
ABANDONED de inmediato (sin agotar los 8 intentos) y el endpoint se
deshabilita en el acto, sin esperar el umbral de fallos consecutivos
descrito abajo. Úsalo si estás retirando una integración permanentemente en
vez de dejar que expire por fallos.
Desactivación automática por fallos sostenidos
Si un endpoint acumula 5 entregas ABANDONED consecutivas (cada una ya
agotó sus 8 intentos, recibió un 410 o su dominio resolvió a una red interna),
Yallegó lo deshabilita
automáticamente (is_enabled: false) y notifica por correo a los usuarios
con rol OWNER o ADMIN del negocio. Un endpoint deshabilitado deja de recibir
nuevos eventos hasta que lo reactives explícitamente con
PATCH /v1/webhooks/{id} ({"is_enabled": true}).
Este umbral es una decisión operativa propia de Yallegó (no forma parte de un estándar externo) — su intención es detectar un endpoint roto en horas, no dejarlo fallando silenciosamente durante semanas mientras acumula entregas perdidas.
Cualquier entrega exitosa reinicia el contador de fallos consecutivos
(consecutive_failures) a cero. Las entregas que se abandonan porque el
endpoint ya estaba deshabilitado no suman.
Reintento manual
Para reactivar una entrega puntual sin esperar el calendario automático — por ejemplo, después de corregir un bug que causó el fallo original:
curl -X POST https://api.yallego.app/v1/webhooks/{id}/deliveries/{deliveryId}/retry \
-H "Authorization: Bearer yk_live_..."
Aplica a entregas ABANDONED y también a las PENDING (adelanta su próximo
intento); una DELIVERED responde 409 CONFLICT. El reintento manual no crea
una entrega nueva: reactiva la misma (mismo id, mismo
X-Yallego-Delivery-Id, mismo cuerpo) y hace un intento inmediato. En una
PENDING, ese intento es el que estaba agendado, adelantado: cuando llega la
hora original no se envía otro.
attemptssigue contando desde donde estaba, así que puede superarmax_attempts.- Si a la entrega le quedaban intentos del calendario (por ejemplo, se abandonó en el primero porque el endpoint estaba deshabilitado o su dominio resolvía a una red interna), un fallo sigue el calendario desde ahí.
- Si ya había agotado los 8, ese intento es el único: si falla, vuelve a
ABANDONEDy suma un fallo consecutivo al endpoint, como cualquier otra entrega abandonada. - Si el endpoint está deshabilitado, la entrega se abandona sin enviarse:
reactívalo antes con
PATCH /v1/webhooks/{id}({"is_enabled": true}).
Recomendaciones para tu endpoint
- Responde
2xxen cuanto valides la firma y encoles el procesamiento — no hagas trabajo pesado de forma síncrona dentro del handler, o corres riesgo de superar los 10 segundos de timeout. - Diseña tu handler para ser idempotente: un mismo evento puede llegarte
más de una vez si tu respuesta se perdió en tránsito aunque tu handler sí lo
haya procesado. Para descartar duplicados:
X-Yallego-Event-Id(=iddel cuerpo) es único por evento y se repite en todos los intentos. Guarda los que ya procesaste y descarta los repetidos.X-Yallego-Delivery-Idtambién se repite en todos los intentos de una entrega, automáticos y manuales: no es único por intento. Identifica la entrega de ese evento a ese endpoint y es elidque ves enGET /v1/webhooks/{id}/deliveries, así que sirve para cruzar tus registros con el historial.- Si el mismo comercio tiene varios endpoints suscritos al mismo tipo, el
evento llega una vez a cada uno, con el mismo
X-Yallego-Event-Idy unX-Yallego-Delivery-Iddistinto: deduplica porX-Yallego-Event-Idsi quieres procesarlo una sola vez, o porX-Yallego-Delivery-Idsi cada endpoint lo procesa por su cuenta. - El evento de prueba (
POST /v1/webhooks/{id}/test) tiene unidnuevo en cada llamada.
- Monitorea
GET /v1/webhooks/{id}/deliveries?status=ABANDONEDperiódicamente, o suscribe activamente a que tu propio sistema te alerte — no dependas solo del correo de desactivación automática como única señal.