Lógica de Reintentos
Comprenda cómo Mail.Land reintenta las entregas de webhook fallidas
Cuando una entrega de webhook falla, MailLand reintenta automáticamente con retrasos crecientes. Esta página cubre el calendario de reintentos, los estados de entrega, el manejo de errores y cómo monitorear y reintentar entregas manualmente.
Calendario de Reintentos
Esta sección cubre todos los eventos que entrega el durable dispatcher: message.*, suppression.*,
account.* e inbound.received. Lo específico de los eventos de entrada está en
Entregas Entrantes más abajo.
MailLand reintenta una entrega fallida hasta 6 veces en total, con un retraso creciente antes de cada reintento:
| Intento | Retraso antes de este intento | Tiempo Total Transcurrido |
|---|---|---|
| 1 | : (intento inicial) | 0 |
| 2 | Inmediato | ~0 |
| 3 | 1 minuto | ~1 minuto |
| 4 | 5 minutos | ~6 minutos |
| 5 | 15 minutos | ~21 minutos |
| 6 | 1 hora | ~1 hora 21 minutos |
Si el 6.º intento falla, la entrega se marca como fallida permanentemente: no hay más espera ni un 7.º intento.
Reintentable vs No Reintentable
Respuestas reintentables
Estos códigos de estado activan reintentos automáticos:
408Request Timeout429Too Many Requests500Internal Server Error502Bad Gateway503Service Unavailable504Gateway Timeout- Errores de red (tiempos de espera, errores de socket, fallos de DNS)
Respuestas no reintentables
Estos códigos de estado se tratan como fallos permanentes, sin reintento:
400Bad Request401Unauthorized403Forbidden404Not Found- Todos los demás errores
4xx(excepto 408 y 429) - Una respuesta de redirección que falla la validación (consulta Redirecciones) o supera el límite de saltos
Si tu endpoint devuelve un encabezado Retry-After en una respuesta reintentable, MailLand usa ese
valor como retraso antes del siguiente intento en lugar del calendario anterior: para cualquier
estado reintentable, no solo 429. No hay un límite superior ni jitter aplicado: respeta esto
también de tu lado si lo envías, ya que un valor muy grande se respeta exactamente como se indica.
Redirecciones
MailLand no trata tu endpoint como lo haría un navegador. Las redirecciones se siguen manualmente, con un máximo de 3 saltos, y cada salto se revalida antes de enviar nada a él:
- el destino debe ser
https://: una redirección ahttp://se rechaza, no se degrada; - el destino debe resolver a una dirección pública: una redirección a una dirección privada, loopback o link-local se rechaza, y la solicitud nunca se emite;
- superar 3 saltos hace fallar la entrega.
Una redirección rechazada se reporta como un fallo de entrega sin código de estado. Si tu endpoint se movió, apunta el webhook a la nueva URL en lugar de depender de una redirección.
Configuración de Entrega
| Configuración | Predeterminado | Descripción |
|---|---|---|
| Tiempo de espera HTTP | 15 segundos | Tiempo de espera máximo por intento de entrega |
| Reintentos máximos | 6 intentos | Total de intentos de entrega incluyendo el inicial |
| Umbral de pausa automática | 10 fallos consecutivos | El webhook se pausa después de este número de fallos seguidos: usa el pauseThreshold propio del webhook cuando está configurado en un valor mayor que 0, y este valor por defecto en caso contrario |
| Deduplicación | Mientras exista el registro de entrega | Los duplicados del mismo evento se suprimen mediante la restricción (WebhookId, EventId) mientras la fila exista: al menos 30 días para las entregas exitosas |
Entregas Entrantes
inbound.received se entrega con el mismo durable dispatcher que cualquier otro evento, con el mismo
calendario de reintentos, el mismo tratamiento de Retry-After, el mismo historial de entregas y la misma
pausa automática descritos arriba.
- Deduplique con
event_id(igual aX-MLND-Event-Id), como en cualquier otro evento. Es estable por mensaje de entrada y webhook, así que cada intento para el mismo correo lleva el mismo id. - Un reenvío manual es un evento nuevo: un
event_idnuevo, con el original endata.replay_of.data.idempotency_keyno cambia. - La
download_urlde cada adjunto se firma en cada intento y vale 15 minutos desde ese momento; eliddel adjunto es el mismo en cada intento. Consulte Webhooks de entrada.
Ver Historial de Entregas
Consulte las entregas anteriores para un webhook:
GET https://api.mail.land/v1/webhooks/{id}/deliveriescurl -X GET "https://api.mail.land/v1/webhooks/wh_abc123/deliveries?limit=20" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Parámetros de Consulta
| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
cursor | string | - | Cursor opaco del nextCursor de la página anterior. Omitir para la primera página. |
limit | int | 20 | Elementos por página |
status | string | - | Filtro: success o failed |
eventType | string | - | Filtrar por tipo de evento (ej. message.delivered) |
from | datetime | - | Fecha de inicio |
to | datetime | - | Fecha de fin |
{
"items": [
{
"publicId": "p8r2kx7m9wq4rtz",
"eventType": "message.delivered",
"messageId": "t_a1b2c3d4e5f6",
"statusCode": 200,
"responseTimeMs": 145,
"success": true,
"errorMessage": null,
"createdAt": "2026-02-17T12:34:58.000Z",
"attemptNumber": 1
},
{
"publicId": "p8r2kx7m3nq1abc",
"eventType": "message.bounced",
"messageId": "t_d4e5f6a1b2c3",
"statusCode": 503,
"responseTimeMs": 15000,
"success": false,
"errorMessage": "Service Unavailable",
"createdAt": "2026-02-17T12:30:00.000Z",
"attemptNumber": 3
}
],
"nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
"hasMore": true
}Reintentar una Entrega Fallida
Reintente manualmente una entrega fallida específica:
POST https://api.mail.land/v1/webhooks/{id}/deliveries/{publicId}/retrycurl -X POST https://api.mail.land/v1/webhooks/wh_abc123/deliveries/p8r2kx7m3nq1abc/retry \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Devuelve 202 Accepted en caso de éxito. El reintento se pone en cola y usa la carga útil del evento original.
| Estado | Código | Descripción |
|---|---|---|
202 | - | Reintento en cola exitosamente |
202 | - | La entrega ya está en cola para reintento, no-op, no es un error |
400 | ALREADY_SUCCEEDED | No se puede reintentar una entrega que ya tuvo éxito |
400 | INVALID_REQUEST | La entrega es anterior al seguimiento duradero de reintentos, o está actualmente en curso |
404 | WEBHOOK_NOT_FOUND | El webhook no existe |
404 | DELIVERY_NOT_FOUND | El ID de entrega no existe |
Pausa Automática por Fallos
Cuando un webhook acumula suficientes intentos de entrega fallidos consecutivos, MailLand lo pausa
automáticamente. El umbral es el pauseThreshold propio del webhook cuando está configurado en un
valor mayor que 0, y en caso contrario el valor por defecto de 10 intentos de entrega fallidos
consecutivos:
- El
isActivedel webhook se establece enfalse, y se rellenanpausedAtypausedReason:pausedReasonindica cuántos fallos hubo y cuál fue el último - Se crea una notificación en la aplicación
- No se entregan más eventos hasta que se reanude el webhook
El contador es de intentos, no de eventos: un solo evento que agota toda su escalera de reintentos contribuye con varios fallos.
No hay una notificación de advertencia previa antes de alcanzar el umbral: revisa
consecutiveFailures de forma proactiva (ver Buenas Prácticas más abajo) en lugar de esperar a que
te avisen.
Reanudar un Webhook en Pausa
POST https://api.mail.land/v1/webhooks/{id}/resumecurl -X POST https://api.mail.land/v1/webhooks/wh_abc123/resume \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Esto reactiva el webhook: borra el estado de pausa, restablece el contador de fallos consecutivos a cero y lo vuelve a marcar como activo. El siguiente intento de entrega de eventos se realizará normalmente.
Cualquier entrega exitosa restablece automáticamente el contador de fallos consecutivos a cero. Un solo éxito después de 9 fallos evita que el webhook se pause.
Buenas Prácticas
- Devuelva 200 rápidamente: procese las cargas útiles de webhook de forma asíncrona. Ponga el evento en cola y devuelva
200inmediatamente. Los controladores de larga duración corren riesgo de tiempo de espera. - Use el ID de evento para el consumo idempotente: el encabezado
X-MLND-Event-Id(y el campoevent_idcorrespondiente en la carga útil) es estable a través de reintentos y reenvíos: el mismo evento subyacente siempre llega con el mismo ID, sin importar cuántas veces se reenvíe. Almacene los IDs procesados y omita los que ya manejó, de modo que una entrega duplicada sea un no-op de su lado. - Monitoree los fallos consecutivos: revise el campo
consecutiveFailuresal listar webhooks. Investigue antes de alcanzar el umbral de pausa automática. - Maneje correctamente el 429: si su punto de conexión está sobrecargado, devuelva
429con un encabezadoRetry-After. MailLand lo respetará.
Próximos Pasos
- Verificación de firma: verificar la autenticidad del webhook
- Eventos: referencia completa de tipos de eventos
- Descripción general de webhooks: cree y administre webhooks
Verificación de Firma
Verifique las firmas de webhook para garantizar la autenticidad de las cargas útiles de webhook entrantes
Versionado y compatibilidad
Cómo se versionan los payloads de webhook, qué significa cada identificador y cada marca de tiempo, y cómo se anuncian los cambios y las obsolescencias