Step 1 — You need a public HTTPS URL
Your server must be reachable from the internet. During development, use ngrok to tunnel your localhost:/webhook: https://xxxx.ngrok-free.app/webhook
Step 2 — Register it in Meta Dashboard
Meta Dashboard → Your App → WhatsApp → Configuration → Webhook → Edit| Field | What to enter |
|---|---|
| Callback URL | https://xxxx.ngrok-free.app/webhook |
| Verify Token | Any secret word you choose (e.g. myrahulsecret123) |
Step 3 — The verification handshake
The moment you click Verify, Meta sends a GET to your URL:Frequently asked
What is the verify token?
What is the verify token?
A secret word you choose and set in two places: your
.env file and the Meta Dashboard
webhook form. Meta sends it in the handshake GET request so your server can confirm the
request is genuinely from Meta.Why does Meta say 'verification failed'?
Why does Meta say 'verification failed'?
Either your server wasn’t running when Meta sent the GET request, the verify token in your
.env doesn’t match what you entered in Meta Dashboard, or your URL isn’t publicly reachable
(e.g. ngrok isn’t running).Do I need ngrok?
Do I need ngrok?
During development yes — your localhost is not reachable from Meta’s servers. ngrok creates a
public tunnel. In production, deploy your server to a real host (Render, Railway, etc.) and
use that permanent URL instead.
Does the webhook URL change if I restart ngrok?
Does the webhook URL change if I restart ngrok?
Yes — free ngrok gives a new URL every restart. You’d need to update it in Meta Dashboard
each time. Paid ngrok gives a fixed domain.

