Documentação

Chamadas e webhooks no mesmo formato da WhatsApp Cloud API da Meta. Referência da Meta

Introdução

A API da dispara.dev segue a WhatsApp Cloud API da Meta. O caminho, o corpo da requisição, a resposta e os webhooks têm o mesmo formato da documentação oficial da Meta. Se você já tem código escrito para a Cloud API, troque a URL base e o token.

URL base: https://api.dispara.dev/v1. No lugar de {PHONE_NUMBER_ID} e {WABA_ID}, use os IDs que aparecem na visão geral de cada número no painel.

Os endpoints disponíveis hoje são envio de mensagens e gerenciamento de templates. Para o restante da Cloud API, a documentação da Meta continua sendo a referência dos campos.

Autenticação

Toda requisição leva a sua chave de API no header Authorization, no lugar do token de acesso da Meta. Cada chave pertence a um número: ela só envia mensagens por ele. Gere e revogue chaves em Chaves de API, dentro do número, no painel.

Sem chave válida a resposta é 401. Com a assinatura inativa a resposta é 402. Os erros usam o mesmo formato da Graph API: error.message, error.type e error.code.

Authorization
Authorization: Bearer dsp_live_8f2a...

# 401 Unauthorized
{
  "error": {
    "message": "Chave de API inválida",
    "type": "OAuthException",
    "code": 190
  }
}

Enviar mensagem de texto

POST /v1/{PHONE_NUMBER_ID}/messages. O texto livre só pode ser enviado dentro da janela de 24 horas depois da última mensagem do cliente. Fora dela, use um template.

POST /v1/106540352242922/messages
curl -X POST https://api.dispara.dev/v1/106540352242922/messages \
  -H "Authorization: Bearer dsp_live_8f2a..." \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "recipient_type": "individual",
    "to": "5511988887777",
    "type": "text",
    "text": {
      "preview_url": false,
      "body": "Seu pedido #4821 saiu para entrega."
    }
  }'

# 200 OK
{
  "messaging_product": "whatsapp",
  "contacts": [
    { "input": "5511988887777", "wa_id": "5511988887777" }
  ],
  "messages": [
    { "id": "wamid.HBgNNTUxMTk4ODg4Nzc3FQIAERgSQTBF..." }
  ]
}

Enviar template

Mesmo endpoint, com type template. Os parâmetros em components preenchem as variáveis {{1}}, {{2}} e seguintes do corpo do template aprovado.

POST /v1/106540352242922/messages
curl -X POST https://api.dispara.dev/v1/106540352242922/messages \
  -H "Authorization: Bearer dsp_live_8f2a..." \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "5511988887777",
    "type": "template",
    "template": {
      "name": "pedido_enviado",
      "language": { "code": "pt_BR" },
      "components": [
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Maria" },
            { "type": "text", "text": "#4821" },
            { "type": "text", "text": "terça-feira" }
          ]
        }
      ]
    }
  }'

# 200 OK
{
  "messaging_product": "whatsapp",
  "contacts": [
    { "input": "5511988887777", "wa_id": "5511988887777" }
  ],
  "messages": [
    { "id": "wamid.HBgNNTUxMTk4ODg4Nzc3FQIAERgSQTBF..." }
  ]
}

Enviar imagem, documento ou áudio

Envie o link público do arquivo em link, ou o id de uma mídia já enviada à Meta. Os tipos image, document, audio e video seguem o mesmo formato.

POST /v1/106540352242922/messages

curl -X POST https://api.dispara.dev/v1/106540352242922/messages \
  -H "Authorization: Bearer dsp_live_8f2a..." \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "5511988887777",
    "type": "image",
    "image": {
      "link": "https://seu-sistema.com/pedidos/4821.jpg",
      "caption": "Comprovante do pedido #4821"
    }
  }'

Enviar botões de resposta

Mensagens interativas com até três botões. Quando o cliente toca em um, você recebe um webhook com type interactive e o id do botão.

POST /v1/106540352242922/messages
curl -X POST https://api.dispara.dev/v1/106540352242922/messages \
  -H "Authorization: Bearer dsp_live_8f2a..." \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "5511988887777",
    "type": "interactive",
    "interactive": {
      "type": "button",
      "body": { "text": "Seu pedido saiu para entrega. Quer rastrear?" },
      "action": {
        "buttons": [
          { "type": "reply", "reply": { "id": "rastrear", "title": "Rastrear" } },
          { "type": "reply", "reply": { "id": "suporte", "title": "Falar com suporte" } }
        ]
      }
    }
  }'

Marcar como lida

Marca uma mensagem recebida como lida. A resposta é { "success": true }.

POST /v1/106540352242922/messages
curl -X POST https://api.dispara.dev/v1/106540352242922/messages \
  -H "Authorization: Bearer dsp_live_8f2a..." \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "status": "read",
    "message_id": "wamid.HBgNNTUxMTk4ODg4Nzc3FQIAERgSQTBF..."
  }'

Listar templates

GET /v1/{WABA_ID}/message_templates. Aceita os mesmos parâmetros da Meta, como limit, name e status, e devolve a mesma resposta, com paging.

GET /v1/102290129340398/message_templates
curl "https://api.dispara.dev/v1/102290129340398/message_templates?limit=10&status=APPROVED" \
  -H "Authorization: Bearer dsp_live_8f2a..."

# 200 OK
{
  "data": [
    {
      "id": "1234567890123456",
      "name": "pedido_enviado",
      "language": "pt_BR",
      "status": "APPROVED",
      "category": "UTILITY",
      "components": [
        {
          "type": "BODY",
          "text": "Olá, {{1}}! Seu pedido {{2}} chega na {{3}}."
        }
      ]
    }
  ],
  "paging": { "cursors": { "before": "MAZDZD", "after": "MjQZD" } }
}

Criar template

POST /v1/{WABA_ID}/message_templates. O template passa pela aprovação da Meta e o status muda de PENDING para APPROVED ou REJECTED. Para apagar, use DELETE no mesmo caminho com ?name=.

POST /v1/102290129340398/message_templates
curl -X POST https://api.dispara.dev/v1/102290129340398/message_templates \
  -H "Authorization: Bearer dsp_live_8f2a..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "pedido_enviado",
    "language": "pt_BR",
    "category": "UTILITY",
    "components": [
      {
        "type": "BODY",
        "text": "Olá, {{1}}! Seu pedido {{2}} chega na {{3}}.",
        "example": { "body_text": [["Maria", "#4821", "terça-feira"]] }
      }
    ]
  }'

# 200 OK
{ "id": "1234567890123456", "status": "PENDING", "category": "UTILITY" }

Erros

Quando a Meta recusa uma requisição, devolvemos o status e o corpo de erro dela sem alterações. Os erros da própria dispara.dev usam o mesmo formato.

400 Bad Request
{
  "error": {
    "message": "(#131030) Recipient phone number not in allowed list",
    "type": "OAuthException",
    "code": 131030,
    "fbtrace_id": "AhXmFzM4H36Arbx3WDsC6RJ"
  }
}

Configurar webhooks

Cadastre a URL em Webhooks, dentro do número, no painel. Cada número tem a própria URL. A cada mensagem recebida ou mudança de status, enviamos um POST com o mesmo JSON que a Meta enviaria (object, entry, changes, value), contendo apenas os eventos daquele número.

Responda com qualquer 2xx para confirmar o recebimento.

Se o seu servidor responder com erro ou não responder em 10 segundos, tentamos de novo com intervalos crescentes, até 8 vezes. Cada tentativa aparece no painel. Não fazemos o desafio hub.challenge no seu endpoint.

Mensagem de texto recebida

Quando um cliente envia uma mensagem de texto para o seu número.

POST https://seu-sistema.com/webhooks/whatsapp
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
          "display_phone_number": "5511999990000",
          "phone_number_id": "106540352242922"
        },
            "contacts": [
              {
                "profile": { "name": "Maria Souza" },
                "wa_id": "5511988887777"
              }
            ],
            "messages": [
              {
                "from": "5511988887777",
                "id": "wamid.HBgNNTUxMTk4ODg4Nzc3FQIAERgSQTBF...",
                "timestamp": "1761488000",
                "type": "text",
                "text": { "body": "Oi, queria saber do meu pedido #4821" }
              }
            ]
          }
        }
      ]
    }
  ]
}

Imagem recebida

A mensagem traz o id da mídia. Baixe o arquivo pela Graph API da Meta, em GET /{MEDIA_ID}, e depois na URL devolvida.

POST https://seu-sistema.com/webhooks/whatsapp
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "5511999990000",
              "phone_number_id": "106540352242922"
            },
            "contacts": [
              { "profile": { "name": "Maria Souza" }, "wa_id": "5511988887777" }
            ],
            "messages": [
              {
                "from": "5511988887777",
                "id": "wamid.HBgNNTUxMTk4ODg4Nzc3FQIAERgSQTBF...",
                "timestamp": "1761488100",
                "type": "image",
                "image": {
                  "caption": "Essa é a caixa que chegou",
                  "mime_type": "image/jpeg",
                  "sha256": "Ki8bZ3JvYmF...",
                  "id": "1138264548317301"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}

Resposta de botão

Quando o cliente toca em um botão de mensagem interativa, o evento vem com type interactive. Botões de template chegam com type button.

POST https://seu-sistema.com/webhooks/whatsapp

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "5511999990000",
              "phone_number_id": "106540352242922"
            },
            "contacts": [
              { "profile": { "name": "Maria Souza" }, "wa_id": "5511988887777" }
            ],
            "messages": [
              {
                "from": "5511988887777",
                "id": "wamid.HBgNNTUxMTk4ODg4Nzc3FQIAERgSQTBF...",
                "timestamp": "1761488200",
                "type": "interactive",
                "interactive": {
                  "type": "button_reply",
                  "button_reply": { "id": "rastrear", "title": "Rastrear" }
                }
              }
            ]
          }
        }
      ]
    }
  ]
}

Status de entrega

Cada mensagem enviada passa por sent, delivered e read. Se falhar, o status é failed e vem com errors.

POST https://seu-sistema.com/webhooks/whatsapp

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
          "display_phone_number": "5511999990000",
          "phone_number_id": "106540352242922"
        },
            "statuses": [
              {
                "id": "wamid.HBgNNTUxMTk4ODg4Nzc3FQIAERgSQTBF...",
                "status": "delivered",
                "timestamp": "1761488004",
                "recipient_id": "5511988887777"
              }
            ]
          }
        }
      ]
    }
  ]
}

Ainda não tem uma chave? Crie sua conta.