# Seguir la entrega de cada mensaje

> Guarda en tu sistema si cada mensaje se envió, se entregó, se leyó o falló, y reacciona a los que fallan.

Después de mandar un mensaje por la API quieres saber qué pasó con él: si llegó, si lo leyeron o si falló (por ejemplo, porque el número no tiene WhatsApp) para avisar por otro canal.

Hay dos formas. Puedes usar las dos juntas.

<CardGroup cols={2}>
  <Card title="Webhook message.status" icon="webhook">
    Te avisamos cada vez que cambia el estado. Es lo recomendado: inmediato y sin llamadas de más.
  </Card>
  <Card title="GET /messages/{id}" icon="search">
    Consultas cuando lo necesitas. Útil para revisar un mensaje puntual o como respaldo.
  </Card>
</CardGroup>

## Los estados

| `status` | Qué significa | ✓ en WhatsApp |
| --- | --- | --- |
| `pending` | Meta aceptó el mensaje y lo está procesando. | 🕓 |
| `sent` | Salió de los servidores de WhatsApp. | ✓ |
| `delivered` | Llegó al teléfono del cliente. | ✓✓ |
| `read` | El cliente lo abrió. | ✓✓ azules |
| `failed` | No se pudo entregar. `errorCode` dice por qué. | ⚠️ |

<Note>
  Si el cliente desactivó las confirmaciones de lectura en WhatsApp, el mensaje puede quedarse en `delivered` aunque lo haya leído.
</Note>

## Con el webhook

<Steps>
  <Step title="Guarda el wamid al enviar">
    `POST /messages` devuelve `id` y `wamid`. El webhook identifica el mensaje por su `wamid`, así que guárdalo junto a tu registro (el pedido, el turno, la factura…).

    ```javascript
    const mensaje = await (await fetch(`${MINDO}/messages`, { method: "POST", headers, body })).json()
    await db.pedidos.update(pedido.id, { whatsappWamid: mensaje.wamid, whatsappEstado: mensaje.status })
    ```
  </Step>
  <Step title="Suscríbete a message.status">
    En **Ajustes › API y webhooks**, crea un webhook con el evento **Estado de un mensaje enviado (entregado, leído, fallido)**.
  </Step>
  <Step title="Actualiza tu registro con cada aviso">
    ```javascript
    const ORDEN = { pending: 0, sent: 1, delivered: 2, read: 3, failed: 9 }

    if (evento.event === "message.status") {
      const { wamid, status, errorCode } = evento.data
      const pedido = await db.pedidos.findBy({ whatsappWamid: wamid })
      if (!pedido) return // mensajes de campañas o del chat: no son tuyos

      // Los avisos pueden llegar desordenados: nunca retrocedas
      if (ORDEN[status] <= ORDEN[pedido.whatsappEstado]) return
      await db.pedidos.update(pedido.id, { whatsappEstado: status, whatsappError: errorCode })

      if (status === "failed") await avisarPorEmail(pedido, errorCode)
    }
    ```
  </Step>
</Steps>

<Warning>
  `message.status` llega por **todos** los mensajes que mandas: los de la API, los del chat y los de las campañas. Si solo te interesan los tuyos, ignora los `wamid` que no conoces (como en el ejemplo). En campañas grandes pueden ser miles de avisos.
</Warning>

## Consultando

```bash
curl https://app.mindo.ar/api/v1/messages/01a0d472-c2f4-7c50-bd5f-957fd43ee8b8 \
  -H "Authorization: Bearer $MINDO_API_KEY"
```

```json Un mensaje que falló
{
  "id": "01a0d472-c2f4-7c50-bd5f-957fd43ee8b8",
  "wamid": "wamid.HBgNNTQ5MTE1NTU1MDAwMBUCABEYEjA5MEE2RURGNDlFOTRENDY5AA==",
  "direction": "out",
  "status": "failed",
  "type": "template",
  "body": "Hola Sofía, tu pedido ya está listo para retirar en Café Aurora. Te esperamos hasta las 20 h.",
  "errorCode": 131026,
  "errorTitle": "Message undeliverable",
  "createdAt": "2026-09-24T17:24:45.867Z",
  "sentAt": null,
  "deliveredAt": null,
  "readAt": null
}
```

Si consultas periódicamente, hazlo con calma: una vez por minuto durante los primeros minutos alcanza. La mayoría de los mensajes pasan a `delivered` en segundos.

## Qué hacer cuando falla

| `errorCode` | Qué pasó | Qué puedes hacer |
| --- | --- | --- |
| `131026` | El número no tiene WhatsApp o no recibe mensajes de empresas. | Avísale por email o SMS. Revisa que el teléfono esté bien escrito. |
| `131049` | Meta frenó el mensaje porque esa persona ya recibió muchos mensajes de marketing. | Prueba en otro momento; no reintentes enseguida. |
| `131050` | La persona dejó de aceptar mensajes de marketing de tu empresa. | No le mandes más marketing. Los mensajes de utilidad sí le pueden llegar. |
| `131042` | Hay un problema con el medio de pago de tu cuenta de Meta. | Revisa [el medio de pago](/guias/medio-de-pago). |

La lista completa de códigos está en la [documentación de Meta](https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes).

## Métricas propias

Con los estados guardados puedes calcular, por ejemplo, qué porcentaje de tus confirmaciones de pedido se leen y cuánto tardan. Para las campañas no hace falta: MINDO ya te muestra entregas, lecturas y respuestas en [Resultados de campañas](/guias/campanas/resultados), y `GET /campaigns` te da los totales.
