Quickstart: seu número

Para o negócio que quer ligar o próprio WhatsApp ao seu sistema: do teste no sandbox à primeira mensagem real, em cinco passos.

Este roteiro é para quem opera um negócio e integra o próprio número. Se você atende vários negócios, siga o quickstart de revenda. Se quer ligar um agente de IA, comece pelo MCP para agentes.

1. Teste no sandbox

Em Configurações › Desenvolvedores › Chaves de API, no painel, gere uma chave Sandbox (bz_sandbox_) com o escopo messages:send e exporte-a como BOTOZAP_KEY. Ela não chama a Meta nem consome quota, e o número mágico simula entrega e leitura. O passo a passo completo está em Primeiros passos.

Enviar uma mensagem de texto (sandbox)

Testa o envio ponta a ponta sem credenciais Meta e sem custo, usando o número mágico de happy path do sandbox.

curl https://botozap.com.br/api/v1/messages \
  -X POST \
  -H "X-API-Key: $BOTOZAP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "+5500000000001",
  "type": "text",
  "text": {
    "body": "Oi! 👋 Tudo bem?"
  }
}'

Resposta 201

{
  "id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
  "wamid": "wamid.HBgNNTU5MTk5OTk5OTk5FQIAERgSM0FCQzFEMkUzRjRBNUI2QzdEAA==",
  "to": "5500000000001",
  "sent_to": "5500000000001",
  "status": "sent",
  "sandbox": true
}

Chave sandbox (`bz_sandbox_`) nunca chama a Meta e não consome cota. A origem é sempre o número sintético da conta; o destino pode ser qualquer telefone, e a entrega é simulada. Os números mágicos escolhem o cenário.

`to` é o destinatário que você endereçou, só com dígitos; `sent_to` é o endereço usado no envio. No sandbox os dois são iguais.

O número mágico de happy path mantém a janela de 24h sempre aberta. Para outros destinos, texto fora da janela é 422 `outside_window`, como em produção.

Depois do 201, o BotoZap simula o ciclo de vida (delivered → read no happy path) e dispara seu webhook assinado, como em produção.

2. Conecte o seu número

No painel, abra Conectar meu WhatsApp (Configurações › Canais › Conectar), preencha os dados da empresa, aceite a Política de Mensagens da Meta, pedida uma vez por Conta (declarando que não vai usar o WhatsApp Business para os usos proibidos listados na tela) e conclua o cadastro oficial da Meta. Você pode usar o número só pela API ou em coexistência com o aplicativo do WhatsApp Business, se a Meta confirmar que o número é elegível. O token da WABA fica guardado no servidor e você nunca precisa manipulá-lo. Veja Embedded Signup em Conceitos.

3. Gere uma chave de produção

Gere uma chave Produção (bz_live_) só com os escopos que a integração usa. Para este roteiro, bastam numbers:read, webhooks:write e messages:send. Confira o número conectado:

Listar números conectados

Lista os números da conta, paginado por página (`page`/`per_page`).

curl https://botozap.com.br/api/v1/phone_numbers?page=1&per_page=2 \
  -H "X-API-Key: $BOTOZAP_KEY"

Resposta 200

{
  "data": [],
  "meta": {
    "page": 1,
    "per_page": 2,
    "total_pages": 1,
    "total_count": 1
  }
}

A chave sandbox continua valendo para testes. Ela recebe 403 sandbox_forbidden fora da allow-list de rotas; veja Sandbox vs. produção.

4. Receba eventos por webhook

Registre a URL que vai receber mensagens e status de entrega. O endpoint só passa a receber eventos reais depois de um teste assinado respondido com 2xx.

Registrar um endpoint de webhook

Cria o endpoint com `health_status=unverified`: mesmo com `active=true`, eventos reais só são admitidos depois de um teste assinado com resposta 2xx.

curl https://botozap.com.br/api/v1/webhooks \
  -X POST \
  -H "X-API-Key: $BOTOZAP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://exemplo-integracao.com.br/webhooks/botozap",
  "events": [
    "messages",
    "statuses"
  ],
  "customer_id": null
}'

Resposta 201

{
  "data": {
    "id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
    "customer_id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
    "url": "https://exemplo-integracao.com.br/webhooks/botozap",
    "events": [
      "messages",
      "statuses"
    ],
    "active": true,
    "has_authorization": false,
    "health_status": "unverified",
    "failure_streak": 0,
    "verified_at": null,
    "last_success_at": null,
    "last_failure_at": null,
    "last_response_code": null,
    "next_attempt_at": null,
    "paused_at": null,
    "secret": "whsec_...",
    "created_at": "2026-07-14T12:00:00.000Z",
    "updated_at": "2026-07-14T12:00:00.000Z"
  }
}

O `secret` (`whsec_...`) só aparece nesta resposta de criação — guarde-o agora, ele assina cada entrega (`X-Webhook-Signature`).

`active` expressa sua intenção manual; `health_status` começa como `unverified`. Execute `POST /api/v1/webhooks/{id}/test` e receba 2xx para verificar e ativar o endpoint.

`customer_id` é opcional: omitido ou `null`, o endpoint recebe eventos de todos os Clientes da Conta; informado, recebe apenas eventos daquele Cliente. O id precisa pertencer à Conta da chave.

A URL precisa usar https:// e resolver para um destino público (o BotoZap bloqueia loopback/redes privadas por segurança).

Testar e ativar um endpoint

Envia `webhook.test` assinado. Qualquer resposta HTTP 2xx verifica a configuração, zera o streak e ativa o endpoint para eventos reais.

curl https://botozap.com.br/api/v1/webhooks/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/test \
  -X POST \
  -H "X-API-Key: $BOTOZAP_KEY"

Resposta 200

{
  "data": {
    "success": true,
    "response_code": 204,
    "health_status": "healthy",
    "active": true
  }
}

Se o destino responder fora de 2xx, ou houver timeout/erro de rede, a API retorna 502 `test_delivery_failed`; a falha manual não incrementa `failure_streak` nem cruza alertas.

Depois de corrigir URL ou Authorization, use este mesmo endpoint para verificar e reativar; `PATCH { "active": true }` sozinho retorna `verification_required`.

Valide a assinatura X-Webhook-Signature e deduplique as entregas como explicado em Webhooks.

5. Envie pela API

Fora da janela de 24h, só template aprovado na WABA. Com um único número conectado, from é opcional. Ele passa a ser obrigatório quando a Conta tem mais de um número:

Enviar por um número específico (`from`)

Contas com mais de um número conectado precisam informar `from` (o `phone_number_id` Meta ou o UUID interno) para desambiguar por qual número enviar.

curl https://botozap.com.br/api/v1/messages \
  -X POST \
  -H "X-API-Key: $BOTOZAP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "+5511988887777",
  "type": "template",
  "template": {
    "name": "pedido_confirmado",
    "language": {
      "code": "pt_BR"
    }
  },
  "from": "112233445566778"
}'

Resposta 201

{
  "id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
  "wamid": "wamid.HBgNNTU5MTk5OTk5OTk5FQIAERgSM0FCQzFEMkUzRjRBNUI2QzdEAA==",
  "to": "5511988887777",
  "sent_to": "5511988887777",
  "status": "sent"
}

`from` é obrigatório quando a conta tem mais de um número conectado — sem ele a API responde 422 `ambiguous_phone`.

Use o `phone_number_id` Meta ou o UUID interno retornado por `GET /api/v1/phone_numbers`.

Próximos passos