Enviando mensagens
Há duas formas de chamar /instance/.../send/*:
- Administrativa:
POST /instance/{id}/send/{text,poll,buttons,pix}, comAuthorization: Bearer(admin ou dono) — é o que o painel usa. - Self-service:
POST /instance/send/{text,poll,buttons,pix}, sem:id, com o headertokenda própria instância.
O corpo é o mesmo nos dois casos; só muda autenticação e se o :id vai na URL.
Dry-run por padrão — leia isto antes de integrar
Seção intitulada “Dry-run por padrão — leia isto antes de integrar”Toda chamada de envio é um preview, a não ser que você mande o campo
confirm com o valor exato da string "ENVIAR" (maiúsculas, em português).
Qualquer outra coisa — campo ausente, "confirm":"sim", "confirm":true — é
tratado como dry-run: nenhuma mensagem é enviada de verdade, cota e rate limit
não são verificados.
{ "to": "5583999999999", "text": "oi", "confirm": "ENVIAR" }Isso é deliberado: dá para integrar e testar a chamada inteira (incluindo erro de allowlist, rate limit, formato) sem nunca arriscar mandar mensagem de verdade, até o dia em que você está pronto para ativar.
to é um número com DDI (só dígitos, sem + nem espaços) — é resolvido para
JID do WhatsApp (IsOnWhatsApp) dentro do worker; você nunca monta o JID você
mesmo.
curl -X POST -H "Authorization: Bearer <ADMIN_TOKEN>" -H "Content-Type: application/json" \ -d '{"to":"5583999999999","text":"Olá!"}' \ https://sua-instancia.exemplo/instance/{id}/send/textPreview real (confirmado ao vivo, dry-run):
{ "dryRun": true, "preview": "{\"conversation\":\"Olá!\"}", "note": "Texto puro — confiabilidade alta."}preview é uma string contendo o protojson da mensagem que seria enviada —
não um objeto aninhado.
Enquete
Seção intitulada “Enquete”{ "to": "5583999999999", "question": "Gostou?", "options": ["Sim", "Não"], "selectableCount": 1}Caminho oficialmente suportado pela lib whatsmeow (BuildPollCreation) — o
mais confiável dos quatro tipos. Preview real confirmado:
{ "dryRun": true, "preview": "{\"messageContextInfo\":{\"messageSecret\":\"...\"}, \"pollCreationMessage\":{\"name\":\"Gostou?\",\"options\":[{\"optionName\":\"Sim\"},{\"optionName\":\"Não\"}],\"selectableOptionsCount\":1}}", "note": "Caminho oficialmente suportado pela lib (BuildPollCreation)."}Botões (quick_reply)
Seção intitulada “Botões (quick_reply)”{ "to": "5583999999999", "body": "Escolha uma opção", "options": ["Sim", "Não"]}Até 3 botões. Não existe builder oficial da lib para este tipo de mensagem
— o backend injeta manualmente o nó de protocolo <biz> necessário para o
WhatsApp renderizar os botões (ver ADR 0001 do zapgate-backend). Confirmado
funcional em teste real (entrega + leitura), mas é um formato não documentado
oficialmente pelo WhatsApp — pode parar de funcionar sem aviso se o protocolo
mudar.
Pix (cta_copy)
Seção intitulada “Pix (cta_copy)”{ "to": "5583999999999", "pixCode": "000201...", "displayText": "Pagar", "fallback": false}Mesmo mecanismo do nó <biz> manual dos botões. fallback: true manda um
texto simples em vez do botão interativo — útil se você perceber que o cliente
de destino não está renderizando o botão. Confirmado funcional em teste
real.
O que a documentação ainda não cobre
Seção intitulada “O que a documentação ainda não cobre”- Taxas de entrega/latência sob carga com várias instâncias enviando ao mesmo
tempo — não foi medido (ver
docs/adr/0003dozapgate-backend). - Suporte a mídia (imagem/áudio/documento) — confirmado que não existe:
só há rota de envio para
text,poll,buttonsepix(internal/httpapi/router.go).