Message body
WhatsApp events arrive as nested JSON:entry, changes, value, then messages.
Messages sent from the WhatsApp Business app
If you connected a number you already use in the WhatsApp Business app, your team keeps replying from the app while your code sends through the API.Those app replies reach your webhook too, so your side of the conversation stays complete. They arrive under a different field name, with a different array inside.
field first, then the array that goes with it.
In an echo
from is your business number and to is the customer, the reverse of an inbound message.Messages your code sends through the API do not come back as echoes, you already have their ids from the send response.
Echoes do not count toward your usage.
Contacts and chat history from the WhatsApp Business app
When a number you use in the WhatsApp Business app connects for the first time, HookMyApp asks WhatsApp to share its contacts and up to 180 days of chat history.Both arrive at your webhook, under two more field names.
A contact:
action is add or remove.full_name and first_name are only there when the business saved a name for the contact.
A piece of chat history:
Messages look like regular messages plus
history_context.status.A message the business sent has a
to field, like an echo.Content WhatsApp can’t share arrives as
type: "errors", skip it.
If the business turned off chat history sharing, you get one history webhook with error code 2593109 and no threads.WhatsApp only allows the sync in the first 24 hours after a number connects for the first time.
Reconnecting the number later does not send its history again.
These webhooks do not count toward your usage.
Verification GET
When you set a deployed webhook URL, HookMyApp checks that your receiver can answer a verification request.Respond with
VERIFY_TOKEN and HTTP 200.Local listen commands skip this check because they send messages to your computer only while the command runs.
Signature verification
Every message delivery POST arrives withX-HookMyApp-Signature-256: sha256=<hex>.Compute HMAC-SHA256 over the raw request body using
WEBHOOK_HMAC_SECRET as the key.This is the HMAC signing secret from
hookmyapp channels env or hookmyapp sandbox env.It is not the
VERIFY_TOKEN.The
VERIFY_TOKEN is only echoed back on the ownership GET probe.Compare the computed value against the hex digest in the header. One POST is never signed: when you run
webhook set, HookMyApp sends an empty-body verification probe marked X-HookMyApp-Probe: webhook-verification (User-Agent HookMyApp-Webhook-Verifier).Answer it with any 2xx before checking signatures, or verification fails. For more detail, see Meta payload validation docs.
Acknowledge fast
Three ways to receive messages
- Listen in the sandbox:
hookmyapp sandbox listen --path /webhook/whatsapptells HookMyApp to send test WhatsApp messages to your local receiver.
Use this with the HookMyApp test number.
Keep the CLI running while you test. - Listen to your own number locally:
hookmyapp channels listen <channel>tells HookMyApp to send messages from your connected WhatsApp number to your local receiver.
Use this to test with your real WhatsApp number before you deploy.
Stop the CLI when you are done. - Your own number, your own URL:
hookmyapp channels webhook set <channel> --url <your-public-https-url>sends messages to your deployed receiver.
Use this after your receiver is live.
Next steps
- Webhook routing: Choose where incoming WhatsApp messages are delivered.
- Event subscriptions: Send events to extra URLs, next to this webhook.
- WhatsApp quickstart: Skip the boilerplate and clone the reference receiver.
- Connect your number: Connect a new number or the one you already use in the WhatsApp Business app.