> ## Documentation Index
> Fetch the complete documentation index at: https://docs-hub-campaign.convertt.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Eventos de Webhook

> Formato e tipos de eventos enviados via webhook

## `message.status_updated`

Enviado toda vez que o status de uma mensagem muda. Cada transição de status gera um evento independente.

```json theme={null}
{
  "event": "message.status_updated",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "data": {
    "dispatchId": "uuid-do-message-delivery",
    "campaignId": "uuid-da-campanha",
    "campaignName": "Promoção Black Friday 2025",
    "uid": "user-001",
    "phone": "+5511999999999",
    "status": "delivered",
    "statusTimestamp": "2025-01-15T10:30:00.000Z",
    "channel": "rcs",
    "failureReason": null,
    "metadata": {}
  }
}
```

## Campos do Payload

| Campo                  | Tipo           | Descrição                                                            |
| ---------------------- | -------------- | -------------------------------------------------------------------- |
| `event`                | string         | Tipo do evento. Sempre `message.status_updated`                      |
| `timestamp`            | string         | ISO 8601 — momento em que o evento foi gerado                        |
| `data.dispatchId`      | string         | ID único do message delivery                                         |
| `data.campaignId`      | string         | ID da campanha (mesmo enviado no dispatch)                           |
| `data.campaignName`    | string         | Nome da campanha                                                     |
| `data.uid`             | string \| null | ID externo do destinatário (enviado no dispatch via `uid`)           |
| `data.phone`           | string         | Número do destinatário                                               |
| `data.status`          | string         | Status atual. Ver tabela abaixo                                      |
| `data.statusTimestamp` | string         | ISO 8601 — quando o status ocorreu no provedor                       |
| `data.channel`         | string         | Canal de entrega: `rcs` ou `sms`                                     |
| `data.failureReason`   | string \| null | Motivo da falha (somente quando `status = "failed"`)                 |
| `data.interaction`     | object \| null | Dados de interação do usuário (somente para `clicked` e `responded`) |
| `data.metadata`        | object         | Reservado para uso futuro                                            |

## Status Possíveis

| Status           | Canal          | Descrição                                             |
| ---------------- | -------------- | ----------------------------------------------------- |
| `sent`           | `rcs` ou `sms` | Mensagem enviada/confirmada pelo provedor             |
| `carrier-sended` | `sms`          | SMS aceito pela operadora para entrega                |
| `delivered`      | `rcs` ou `sms` | Mensagem entregue ao dispositivo                      |
| `read`           | `rcs`          | Mensagem lida pelo destinatário                       |
| `clicked`        | `rcs`          | Destinatário clicou em botão de ação (ACTION) ou URL  |
| `responded`      | `rcs`          | Destinatário respondeu com texto livre ou botão REPLY |
| `failed`         | `rcs` ou `sms` | Falha na entrega. Ver `failureReason`                 |

<Note>
  O campo `failureReason` é preenchido **apenas** quando `status = "failed"`. Em todos os outros eventos (delivered, read, clicked, etc.) o campo é `null`, independentemente de a mensagem ter falhado anteriormente.
</Note>

## Fluxos de Eventos por Cenário

### RCS — Bloqueado por duplicidade

Quando uma mensagem é bloqueada antes de ser enviada (ex: número já recebeu a mesma mensagem recentemente).

```json theme={null}
{
  "data": {
    "status": "failed",
    "channel": "rcs",
    "failureReason": "Bloqueado por duplicidade",
    "interaction": null
  }
}
```

### RCS — Entrega normal com leitura

```
sent → delivered → read
```

### RCS — Destinatário clica em botão de ação (openUrl, call)

```
sent → delivered → read → clicked
```

```json theme={null}
{
  "data": {
    "status": "clicked",
    "channel": "rcs",
    "failureReason": null,
    "interaction": {
      "type": "click",
      "text": "APROVEITE",
      "postbackData": "https://www.puravida.com.br/campanhas/health-monday"
    }
  }
}
```

### RCS — Destinatário responde com botão REPLY

```
sent → delivered → read → responded
```

```json theme={null}
{
  "data": {
    "status": "responded",
    "channel": "rcs",
    "failureReason": null,
    "interaction": {
      "type": "reply",
      "text": "Garanta já a sua.",
      "postbackData": "Eu quero a webcam"
    }
  }
}
```

### RCS — Destinatário responde com texto livre

```json theme={null}
{
  "data": {
    "status": "responded",
    "channel": "rcs",
    "failureReason": null,
    "interaction": {
      "type": "text",
      "text": "Olá, quero mais informações"
    }
  }
}
```

<Note>
  `clicked` é acionado por botões do tipo `ACTION` (openUrl, call). `responded` é acionado por botões do tipo `REPLY` ou quando o destinatário digita texto livre. Para todos os demais status (`sent`, `delivered`, `read`, `failed`), o campo `interaction` é `null`.
</Note>

## Campo `interaction`

Presente somente nos eventos `clicked` e `responded`.

| Campo                      | Tipo                | Descrição                                                                   |
| -------------------------- | ------------------- | --------------------------------------------------------------------------- |
| `interaction.type`         | string              | `"click"` (botão ACTION), `"reply"` (botão REPLY) ou `"text"` (texto livre) |
| `interaction.text`         | string              | Texto do botão clicado ou mensagem digitada                                 |
| `interaction.postbackData` | string \| undefined | URL (click) ou valor de postback do botão REPLY                             |

### RCS → Fallback SMS — Dispositivo sem suporte RCS, SMS entregue

Quando o dispositivo não suporta RCS, o provedor automaticamente reenvia via SMS quando o template utilizado na campanha estiver com fallback ativo. O campo `channel` muda de `rcs` para `sms` a partir do evento de fallback.

```
[rcs] sent
[rcs] failed          ← "Aparelho não possui suporte ao RCS."
[sms] sent            ← SMS despachado pelo provedor
[sms] carrier-sended  ← SMS aceito pela operadora
[sms] delivered       ← SMS entregue ao dispositivo
```

```json theme={null}
{ "data": { "status": "failed",          "channel": "rcs", "failureReason": "Aparelho não possui suporte ao RCS." } }
{ "data": { "status": "sent",            "channel": "sms", "failureReason": null } }
{ "data": { "status": "carrier-sended",  "channel": "sms", "failureReason": null } }
{ "data": { "status": "delivered",       "channel": "sms", "failureReason": null } }
```

### RCS → Fallback SMS — SMS não entregue pela operadora

```
[rcs] sent
[rcs] failed          ← "Aparelho não possui suporte ao RCS."
[sms] sent            ← SMS despachado pelo provedor
[sms] carrier-sended  ← SMS aceito pela operadora
[sms] failed          ← Operadora não conseguiu entregar
```

```json theme={null}
{ "data": { "status": "failed",          "channel": "rcs", "failureReason": "Aparelho não possui suporte ao RCS." } }
{ "data": { "status": "sent",            "channel": "sms", "failureReason": null } }
{ "data": { "status": "carrier-sended",  "channel": "sms", "failureReason": null } }
{ "data": { "status": "failed",          "channel": "sms", "failureReason": null } }
```

## Diferença entre `sent` e `carrier-sended` (canal SMS)

| Status           | Momento                                                         |
| ---------------- | --------------------------------------------------------------- |
| `sent`           | Confirmação do provedor de que o SMS foi despachado             |
| `carrier-sended` | Confirmação da operadora de que o SMS foi recebido para entrega |
| `delivered`      | Confirmação de que o SMS chegou ao dispositivo                  |

<Note>
  Implemente seu handler de webhook de forma idempotente. Uma mesma mensagem pode gerar eventos de `sent` e `carrier-sended` em sequência rápida — ambos são válidos e distintos.
</Note>

## Eventos de Resposta do Destinatário

Além de atualizações de status de entrega, eventos `responded` e `clicked` indicam que o destinatário interagiu com a mensagem.

| Interação            | Status      | Descrição                                               |
| -------------------- | ----------- | ------------------------------------------------------- |
| Botão ACTION clicado | `clicked`   | O destinatário clicou em um link ou iniciou uma ligação |
| Botão REPLY clicado  | `responded` | O destinatário escolheu uma resposta rápida             |
| Texto digitado       | `responded` | O destinatário enviou uma mensagem de texto livre       |
