# Reintentos y fallas

> Qué pasa si tu servidor no responde, cuántas veces reintentamos y cuándo se desactiva un webhook.

## Cuándo una entrega cuenta como fallida

Tu servidor tiene que responder con un código `2xx` (por ejemplo `200` o `204`) en menos de **8 segundos**. Cualquier otra cosa cuenta como falla:

- Un código `4xx` o `5xx`. Configura la URL final, sin redirecciones.
- Tardar más de 8 segundos.
- Un error de red: la URL no existe, el certificado HTTPS no es válido, el servidor está caído.

## Cuántas veces reintentamos

Si una entrega falla, la reintentamos con esperas cada vez más largas:

| Intento | Cuándo |
| --- | --- |
| 1 | Al momento del evento |
| 2 | 1 minuto después de la falla |
| 3 | 5 minutos después |
| 4 | 30 minutos después |
| 5 | 2 horas después |
| 6 | 6 horas después |
| 7 | 24 horas después |

Después del séptimo intento, la entrega queda como fallida (**Falló** en el historial) y no se reintenta más. En total, un aviso se intenta durante algo más de un día.

<Note>
  Los reintentos se revisan una vez por minuto, así que los tiempos pueden correrse unos segundos.
</Note>

## Cuándo se desactiva un webhook

Si un webhook falla **sin parar durante 3 días** (ninguna entrega sale bien en ese tiempo), lo desactivamos para no seguir mandando avisos a una URL que no responde. En **Ajustes › API y webhooks** lo vas a ver como **Desactivado**, con el último error.

Con que una sola entrega salga bien, el contador vuelve a cero.

Para reactivarlo, arregla tu servidor y toca **Activar**. Las entregas que hayan quedado pendientes se mandan en el siguiente minuto.

## El estado de un webhook en la app

| Lo que ves | Qué significa |
| --- | --- |
| **Activo** | Todo en orden. |
| **Fallando desde …** | Las últimas entregas fallaron. Seguimos reintentando. Al lado ves el último error (por ejemplo `HTTP 500`, o un error de red o de tiempo de espera). |
| **Desactivado** | Lo pausaste o falló durante 3 días. No se manda nada hasta que lo actives. |

## El historial de entregas

**Entregas** muestra los últimos 50 envíos a cada webhook: el evento, cuánto hace, cuántos intentos, el estado (**Entregado**, **Reintentando** o **Falló**) y el código que respondió tu servidor.

<Frame>
  <img src="/images/api/entregas.png" alt="Historial de entregas de un webhook" />
</Frame>

Guardamos el historial durante **30 días**.

## Pausar un webhook

**Pausar** deja de mandar avisos sin borrar la configuración ni el secreto. Útil mientras haces un mantenimiento. Los eventos que pasen mientras está en pausa quedan pendientes y se mandan cuando lo vuelves a activar (si no pasaron más de 30 días).

## Si cambias de plan

Si la cuenta pasa a un plan sin API, dejamos de mandar avisos. Los webhooks quedan guardados y vuelven a funcionar si regresas a Escala o Enterprise.

## Cómo manejar reintentos en tu servidor

<Steps>
  <Step title="Responde rápido">
    Responde `200` apenas verificas la firma y procesa en segundo plano (una cola, un job, un `setImmediate`). La mayoría de las fallas son timeouts de servidores que hacen todo antes de responder.
  </Step>
  <Step title="Evita duplicados">
    Un reintento trae el mismo `id` (y el mismo `X-Mindo-Delivery`). Guarda los ids que ya procesaste y, si llega uno repetido, responde `200` sin hacer nada.

    ```sql
    -- Una tabla simple alcanza
    create table mindo_webhooks_procesados (
      delivery_id uuid primary key,
      recibido_en timestamptz not null default now()
    );
    -- insert … on conflict do nothing: si no insertó nada, ya lo habías procesado
    ```
  </Step>
  <Step title="No respondas error por algo que no se va a arreglar">
    Si el evento no te interesa o tiene datos que no puedes usar, responde `200` igual. Un `4xx` solo provoca más reintentos.
  </Step>
</Steps>
