Skip to main content
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:
hookmyapp sandbox listen --port 3000 --path /webhook/whatsapp
hookmyapp sandbox listen --port 3000 --path /webhook/instagram
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:
hookmyapp channels listen ch_xxxxxxxx --path /webhook/whatsapp
hookmyapp channels listen ch_xxxxxxxx --path /webhook/instagram
# or omit the channel arg for the interactive picker:
hookmyapp channels listen
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.
# Set your own webhook URL (use the route for the channel's type:
# /webhook/whatsapp for a WhatsApp channel, /webhook/instagram for Instagram)
hookmyapp channels webhook set ch_xxxxxxxx \
  --url https://api.acme.com/webhook/whatsapp \
  --verify-token $(openssl rand -hex 32)

# View the current override URL and verification state
hookmyapp channels webhook show ch_xxxxxxxx

# Remove the override URL (reverts to the CLI tunnel or dashboard config)
hookmyapp channels webhook clear ch_xxxxxxxx

Verify delivery end-to-end

  1. Check the current override. hookmyapp channels webhook show <channel> prints the URL and its verified status. If the status is not verified, your server failed the GET challenge.
  2. Check channel health. hookmyapp channels health <channel> shows phone status, webhook state, and quality rating. Anything not healthy means Meta cannot deliver.
  3. 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.
  4. If signature fails: refresh env. A signature-mismatch 401 means your local VERIFY_TOKEN is stale. Re-run hookmyapp sandbox env --write .env (sandbox) or hookmyapp 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 echoes VERIFY_TOKEN.
  • Signature mismatch on POST: your .env is 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. If channels disable was run, Meta disabled your WhatsApp number and you need to re-enable.
  • Sandbox tunnel drops: hookmyapp sandbox listen exited. Re-run it.
  • Tunnel reclaimed: hookmyapp channels listen exited with CHANNEL_TUNNEL_RECLAIMED. Something else set a webhook URL on the channel (CLI elsewhere, dashboard, or the tunnel row was reaped). Re-run channels listen if you still want the tunnel.

Next steps