> For the complete documentation index, see [llms.txt](https://docs.otima.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.otima.io/whatsapp/recursos-de-api/webhooks-callback.md).

# Webhooks (Callback)

A API da Meta integrada ao Ótima Provider envia callbacks (webhooks) em tempo real para a URL configurada em cada número.

Esses callbacks representam eventos que acontecem dentro do WhatsApp e permitem que sua aplicação reaja automaticamente.

<figure><img src="https://3723060873-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fech0v4OAuw7OeuwoISIc%2Fuploads%2F80uapXXZTPYyZC2uz9A3%2Fimage.png?alt=media&amp;token=e2a0f46e-d86a-4617-8e97-9996c7f581f2" alt=""><figcaption></figcaption></figure>

Os Webhooks seguem o padrão oficial da **Meta (WhatsApp Business Platform)** e permitem monitorar:

* Mensagens recebidas
* Status de mensagens enviadas
* Eventos de cobrança (pricing/conversation)
* Interações com mensagens interativas
* Atualizações de templates (HSM)
* Recebimento de arquivos/mídia (áudio, imagem, vídeo, documento, etc.)

***

### Estrutura Padrão do Webhook <a href="#estrutura-padrao-do-webhook" id="estrutura-padrao-do-webhook"></a>

Todos os webhooks seguem o padrão oficial da Meta:

```json
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "WABA_ID",
      "changes": [
        {
          "field": "messages",
          "value": {}
        }
      ]
    }
  ]
}
```

O conteúdo relevante do evento estará sempre em:

```json
entry[].changes[].value
```

***

### Mensagem Recebida (Inbound) <a href="#mensagem-recebida-inbound" id="mensagem-recebida-inbound"></a>

```json
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "WABA_ID",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "5511999999999",
              "phone_number_id": "PHONE_NUMBER_ID"
            },
            "contacts": [
              {
                "profile": {
                  "name": "João Silva"
                },
                "wa_id": "5511988887777"
              }
            ],
            "messages": [
              {
                "from": "5511999999999",
                "id": "wamid.ID_DA_MENSAGEM",
                "timestamp": "1700000000",
                "type": "text",
                "text": {
                  "body": "Olá!"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}
```

***

## Recebimento de Arquivos (Mídia)

Quando o usuário envia um arquivo, o webhook incluirá um objeto específico conforme o tipo da mídia.

### Importante sobre URLs de mídia

A Meta fornece uma URL temporária protegida:

```http
"url": "https://lookaside.fbsbx.com/..."
```

Essa URL:

* Expira após um período
* Requer autenticação

Ex:

```http
curl --location 'https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=19879042342750386&source=webhook&ext=1143812251&hash=ARlrSsMJHJKO4YYRDRyrwexwgRHHl5cJTqfmPZY8WR8WQFMg' \
--header 'Authorization: Bearer {SEU TOKEN}’
```

### Diferencial do Meta - Ótima Provider

Além da URL original da Meta, fornecemos:

```http
"s3_url": "https://s3.otima.io/..."
```

Essa URL:

* É pública
* Não expira
* Pode ser usada diretamente para download
* Ideal para armazenamento e processamento

***

## Tipos de Arquivos Suportados

### Áudio

```json
{
  "type": "audio",
  "audio": {
    "id": "MEDIA_ID",
    "mime_type": "audio/ogg; codecs=opus",
    "sha256": "HASH",
    "url": "URL_META",
    "s3_url": "URL_PUBLICA"
  }
}
```

***

### Imagem

```json
{
  "type": "image",
  "image": {
    "id": "MEDIA_ID",
    "mime_type": "image/jpeg",
    "sha256": "HASH",
    "caption": "Legenda opcional",
    "url": "URL_META",
    "s3_url": "URL_PUBLICA"
  }
}
```

***

### Vídeo

```json
{
  "type": "video",
  "video": {
    "id": "MEDIA_ID",
    "mime_type": "video/mp4",
    "sha256": "HASH",
    "caption": "Legenda opcional",
    "url": "URL_META",
    "s3_url": "URL_PUBLICA"
  }
}
```

***

### Documento

```json
{
  "type": "document",
  "document": {
    "id": "MEDIA_ID",
    "mime_type": "application/pdf",
    "filename": "arquivo.pdf",
    "sha256": "HASH",
    "url": "URL_META",
    "s3_url": "URL_PUBLICA"
  }
}
```

***

### Sticker

```json
{
  "type": "sticker",
  "sticker": {
    "id": "MEDIA_ID",
    "mime_type": "image/webp",
    "sha256": "HASH",
    "url": "URL_META",
    "s3_url": "URL_PUBLICA"
  }
}
```

***

## Exemplo Completo (Mensagem com Áudio)

O exemplo abaixo representa o **formato completo de um webhook oficial da Meta (WhatsApp Business Platform)** para o recebimento de mensagens.

Embora o exemplo utilize um **áudio**, essa mesma estrutura se aplica a **todos os tipos de mídia suportados**, como:

* `audio`
* `image`
* `video`
* `document`
* `sticker`

A única variação será o campo `type` e o objeto correspondente dentro de `messages[]`.

Além disso, o Meta - Ótima Provider adiciona o campo `s3_url`, que fornece uma URL pública já para download da mesma mídia.

```json
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "WABA_ID",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "contacts": [
              {
                "wa_id": "551199991111",
                "profile": {
                  "name": "Marcos"
                }
              }
            ],
            "messages": [
              {
                "id": "wamid.ID",
                "from": "556182897860",
                "timestamp": "1700000000",
                "type": "audio",
                "audio": {
                  "id": "MEDIA_ID",
                  "mime_type": "audio/ogg; codecs=opus",
                  "sha256": "HASH",
                  "url": "URL_META",
                  "s3_url": "URL_PUBLICA"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}
```

***

### Status de Mensagem <a href="#status-de-mensagem" id="status-de-mensagem"></a>

Status possíveis:

* `sent`
* `delivered`
* `read`
* `failed`

```json
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "WABA_ID",
      "changes": [
        {
          "field": "messages",
          "value": {
            "statuses": [
              {
                "id": "wamid.ID_DA_MENSAGEM",
                "status": "delivered",
                "timestamp": "1700000000",
                "recipient_id": "5511988887777",
                "conversation": {
                  "id": "CONVERSATION_ID",
                  "origin": {
                    "type": "marketing"
                  }
                },
                "pricing": {
                  "billable": true,
                  "pricing_model": "CBP",
                  "category": "marketing"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}
```

***

### Mensagem Interativa <a href="#mensagem-interativa" id="mensagem-interativa"></a>

```json
{
  "messages": [
    {
      "from": "5511988887777",
      "id": "wamid.ID",
      "timestamp": "1700000000",
      "type": "interactive",
      "interactive": {
        "type": "button_reply",
        "button_reply": {
          "id": "btn_1",
          "title": "Confirmar"
        }
      }
    }
  ]
}
```

***

### Atualização de Status de Template <a href="#atualizacao-de-status-de-template" id="atualizacao-de-status-de-template"></a>

Eventos possíveis:

* `APPROVED`
* `REJECTED`
* `PENDING`
* `DISABLED`

```json
{
  "field": "message_template_status_update",
  "value": {
    "message_template_id": "123456789",
    "message_template_name": "boas_vindas",
    "message_template_language": "pt_BR",
    "event": "APPROVED"
  }
}
```

***

{% hint style="success" %}

#### Boas práticas <a href="#boas-praticas" id="boas-praticas"></a>

* <mark style="color:$primary;">Responder com HTTP 200 OK</mark>
* <mark style="color:$primary;">Validar assinatura</mark> <mark style="color:$primary;"></mark><mark style="color:$primary;">`X-Hub-Signature-256`</mark>
* <mark style="color:$primary;">Processar eventos de forma assíncrona</mark>
  {% endhint %}
