Quick start
From docker run to a signed webhook and the user's answer. Every call below runs as written against a fresh container.
-
Run it
Tell it where your application listens for webhooks, and the secret to sign them with.
docker run --rm -p 3010:3010 \ -e WEBHOOK_URL=http://host.docker.internal:4000/webhooks/whatsapp \ -e WEBHOOK_SECRET=my-app-secret \ --add-host host.docker.internal:host-gateway \ ghcr.io/instituto-ama/whatsapp-mock:latestIt boots with a business, the WhatsApp Business Account
100000000000001and the number1234567890, registered and with calling on. The panel is at http://localhost:3010. -
Point your application at it
Same paths, same bodies, same answers, same error codes. Any bearer token is accepted, as long as there is one.
- WHATSAPP_GRAPH_URL=https://graph.facebook.com/v23.0 + WHATSAPP_GRAPH_URL=http://localhost:3010/v23.0 WHATSAPP_PHONE_NUMBER_ID=1234567890 WHATSAPP_TOKEN=test -
Create a template
It goes through a review, approved in 2 seconds by default, and the verdict arrives as the
message_template_status_updatewebhook.curl -X POST localhost:3010/v23.0/100000000000001/message_templates \ -H 'Authorization: Bearer test' -H 'Content-Type: application/json' \ -d '{"name":"appointment_reminder","language":"pt_BR","category":"UTILITY", "components":[{"type":"BODY","text":"Olá {{1}}, sua consulta é amanhã às {{2}}.", "example":{"body_text":[["Maria","14:30"]]}}, {"type":"BUTTONS","buttons":[{"type":"QUICK_REPLY","text":"Confirmar"}, {"type":"QUICK_REPLY","text":"Remarcar"}]}]}' # → {"id":"…","status":"PENDING","category":"UTILITY"} -
Send it
curl -X POST localhost:3010/v23.0/1234567890/messages \ -H 'Authorization: Bearer test' -H 'Content-Type: application/json' \ -d '{"messaging_product":"whatsapp","to":"5511987654321","type":"template", "template":{"name":"appointment_reminder","language":{"code":"pt_BR"}, "components":[{"type":"body","parameters":[ {"type":"text","text":"Maria"},{"type":"text","text":"14:30"}]}]}}' # → {"messages":[{"id":"wamid.…","message_status":"accepted"}]}, then sent, delivered, readOpen the panel: the conversation with
5511987654321shows the template as WhatsApp draws it, with its buttons. -
Answer as the user
Tap a button or type in the panel, or do it from a test with one header:
curl -X POST localhost:3010/v23.0/1234567890/messages \ -H 'Authorization: Bearer test' -H 'Content-Type: application/json' \ -H 'X-Mock-From: 5511987654321' -H 'X-Mock-Contact-Name: Maria Souza' \ -d '{"messaging_product":"whatsapp","type":"text","text":{"body":"Oi! Quero remarcar."}}' # → your endpoint receives the messages webhook, signed with x-hub-signature-256 -
In your compose
services: whatsapp: image: ghcr.io/instituto-ama/whatsapp-mock:latest ports: - '3010:3010' environment: WEBHOOK_URL: http://host.docker.internal:4000/webhooks/whatsapp WEBHOOK_SECRET: my-app-secret WEBHOOK_LOCALHOST_REWRITE: host.docker.internal extra_hosts: - 'host.docker.internal:host-gateway' # Linux volumes: - whatsapp-data:/app/data # conversations, templates, numbers, media volumes: whatsapp-data:Templates can also be seeded from files: every JSON in a mounted
templates/folder is imported at start and when it changes. -
In CI
Keep nothing between runs and take the waits out:
WHAP_DB=:memory: MOCK_WEBHOOK_RESPONSE_DELAY_MS=0 MOCK_TEMPLATE_REVIEW_DELAY_MS=0