Webhook routing
Where to find each webhook URL, what each one does, and how to verify delivery end-to-end.
Sandbox tunnel
hookmyapp sandbox listen opens a secure tunnel from a HookMyApp-managed public hostname to http://localhost:3000/webhook by default. The tunnel URL is auto-provisioned. You don't configure it.
If you are using the starter kit, it serves per-channel routes. Select the route with --path:
View the current sandbox URL with hookmyapp sandbox status. It prints the public hostname, your pinned phone, the session expiry, and the activation code.
Tunnel to your own channel (local dev)
hookmyapp channels listen <channel> opens the same kind of tunnel for a connected WhatsApp number or Instagram account. Meta is pointed at the tunnel hostname while the CLI runs; on exit, the tunnel is reclaimed and Meta's webhook URL reverts to whatever was set before.
Use this to develop locally against your real WhatsApp number or Instagram account without standing up a public HTTPS endpoint first. Select the starter kit's per-channel route with --path:
If you set a webhook URL (next section) while a channels listen tunnel is active, the CLI exits with CHANNEL_TUNNEL_RECLAIMED. The two paths are mutually exclusive per channel.
Your own webhook URL (deployed)
When your receiver is deployed behind a stable public URL, set it with hookmyapp channels webhook set. HookMyApp writes it to Meta's override_callback_uri field via the Graph API. That override takes precedence over any URL you configure in the Meta App Dashboard's Webhooks card.
Verify delivery end-to-end
- Check the current override.
hookmyapp channels webhook show <channel>prints the URL and its verified status. If the status is notverified, your server failed the GET challenge. - Check channel health.
hookmyapp channels health <channel>shows phone status, webhook state, and quality rating. Anything nothealthymeans Meta cannot deliver. - Send yourself a test message. From another account, message your WhatsApp number or Instagram account. Watch your server logs for the inbound POST and a 200 response.
- If signature fails: refresh env. A signature-mismatch 401 means your local
VERIFY_TOKENis stale. Re-runhookmyapp sandbox env --write .env(sandbox) orhookmyapp channels env <channel>(your own channel) and restart your server.
When things break
- Webhook verify GET returns 404: your server is not handling
GET /webhook/whatsapp(or/webhook/instagram). Add the verification route that echoesVERIFY_TOKEN. - Signature mismatch on POST: your
.envis stale. Re-pull env values and restart. - No delivery at all: run
hookmyapp channels health <channel>. If it's unhealthy, delivery is blocked at Meta. Ifchannels disablewas run, Meta disabled your WhatsApp number and you need to re-enable. - Sandbox tunnel drops:
hookmyapp sandbox listenexited. Re-run it. - Tunnel reclaimed:
hookmyapp channels listenexited withCHANNEL_TUNNEL_RECLAIMED. Something else set a webhook URL on the channel (CLI elsewhere, dashboard, or the tunnel row was reaped). Re-runchannels listenif you still want the tunnel.
Next steps
- Receive Webhooks: Re-check the verify-and-acknowledge contract.
- Send Messages: Close the loop with a round-trip message test.