In this article
Explore the key concepts, practical considerations, and frequently asked questions related to whatsapp cloud api setup guide for developers (2026).
Key takeaways
- You can build and test the whole integration on Meta's test number before business verification is complete- verification only gates going live on your own number.
- Use a System User token for production. The App Dashboard's temporary token expires after about 24 hours and is a common cause of sudden 401 errors.
- Subscribing your app to the WABA with POST /{WABA_ID}/subscribed_apps is the most commonly missed step when webhooks verify but no events arrive.
This is a hands-on setup guide for developers integrating directly with Meta's WhatsApp Cloud API. It walks through every step from an empty Meta app to a delivered template message and a working webhook, with the exact API calls at each step.
Not a developer, or don't want to set this up yourself? This guide is for building the integration yourself. If you'd rather have it done for you, see our managed WhatsApp Business API service, or read the plain-English how to get WhatsApp Business API guide.
Before You Start
You will need:
- A Meta business portfolio (business.facebook.com) where you are an admin
- A Meta developer account (developers.facebook.com)
- A phone number that is not currently registered on WhatsApp or the WhatsApp Business app, and that can receive an SMS or voice call
- An HTTPS endpoint with a valid TLS certificate for your webhook. For local development, use a tunnel such as ngrok.
- For going live: documents for Meta business verification
Throughout this guide, set these environment variables. Find the current Graph API version in Meta's changelog and use it for API_VERSION:
export API_VERSION="vXX.0" # current Graph API version
export ACCESS_TOKEN="..." # System User token (Step 2)
export WABA_ID="..." # WhatsApp Business Account ID (Step 1)
export PHONE_NUMBER_ID="..." # Phone Number ID, not the phone number itself (Step 3)
export APP_SECRET="..." # App Dashboard > App settings > Basic
export VERIFY_TOKEN="..." # any random string you choose (Step 5)
How the Pieces Fit Together
| Component | What it is | ID you will use |
|---|---|---|
| Business portfolio | Owns your WABA, apps, and System Users | Business ID |
| Meta app | Your integration. It holds webhook settings and permissions | App ID, App Secret |
| WhatsApp Business Account (WABA) | Holds your phone numbers and templates | WABA_ID |
| Business phone number | The number customers see messages from | PHONE_NUMBER_ID |
| System User | Non-human account that owns your production token | ACCESS_TOKEN |
| Webhook | Your HTTPS endpoint that receives messages and status events | Callback URL + VERIFY_TOKEN |
Step 1- Create a Meta App and Connect a WABA
- In the Meta App Dashboard, create a new app of type Business and link it to your business portfolio.
- Add the WhatsApp product. Meta creates a test WABA and a test phone number, and shows a temporary access token.
- To use your own WABA, connect it in the WhatsApp section of the app. Note the WABA ID shown there.
At this point you can already send a test message from the test number to up to 5 recipient numbers you add to the allowed list. Use this to build Steps 5–7 while business verification runs in the background.
Step 2- Generate a System User Access Token
The temporary token in the App Dashboard expires after about 24 hours, so do not use it in production.
- Go to Business Settings > Users > System users and add a System User with the Admin role.
- Use Assign assets to give it your app and your WABA (full control).
- Click Generate new token, choose your app, set the expiry to Never, and select these permissions:
whatsapp_business_messaging- send and receive messageswhatsapp_business_management- manage templates, numbers, and WABA settings
- Store the token in a secrets manager or environment variable. Never commit it to code.
Check that the token works:
curl "https://graph.facebook.com/$API_VERSION/$WABA_ID/phone_numbers" \
-H "Authorization: Bearer $ACCESS_TOKEN"
The response lists each number on the WABA with its id. That id is your PHONE_NUMBER_ID.
Step 3- Add and Register Your Phone Number
- In WhatsApp Manager, add your phone number and display name, then verify it with the SMS or voice code.
- Register the number for Cloud API use. This also sets its two-step verification PIN, which you will need if you ever re-register it:
curl -X POST "https://graph.facebook.com/$API_VERSION/$PHONE_NUMBER_ID/register" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "messaging_product": "whatsapp", "pin": "123456" }'
A response of {"success": true} means the number is ready to send. Store the PIN securely.
Choose the number carefully. It becomes your business identity on WhatsApp, and while it is on the Cloud API it cannot be used in the WhatsApp or WhatsApp Business app.
Step 4- Subscribe Your App to the WABA
Your app only receives webhook events for a WABA after it subscribes to it. This step is easy to miss: the webhook verifies but no messages ever arrive.
curl -X POST "https://graph.facebook.com/$API_VERSION/$WABA_ID/subscribed_apps" \
-H "Authorization: Bearer $ACCESS_TOKEN"
To check it worked, call GET /$WABA_ID/subscribed_apps and confirm your app is listed.
Step 5- Build and Verify Your Webhook
Your endpoint has to handle two things:
- GET (verification): Meta sends
hub.mode,hub.verify_token, andhub.challenge. If the mode issubscribeand the token matches yours, reply with thehub.challengevalue as plain text and HTTP 200. - POST (events): Check the
X-Hub-Signature-256header against an HMAC-SHA256 of the raw request body, signed with your App Secret. Reply 200 quickly, then process the event asynchronously.
const express = require('express');
const crypto = require('crypto');
const app = express();
// Keep the raw body- signature checks must use the exact bytes Meta sent
app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; } }));
// GET: verification handshake
app.get('/webhook/whatsapp', (req, res) => {
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === process.env.VERIFY_TOKEN) {
return res.status(200).send(challenge);
}
return res.sendStatus(403);
});
// POST: inbound messages and status updates
app.post('/webhook/whatsapp', (req, res) => {
const signature = req.get('X-Hub-Signature-256') || '';
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.APP_SECRET)
.update(req.rawBody)
.digest('hex');
const valid = signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) return res.sendStatus(401);
res.sendStatus(200); // acknowledge first
for (const entry of req.body.entry || []) {
for (const change of entry.changes || []) {
const value = change.value || {};
for (const msg of value.messages || []) {
console.log('Inbound message', msg.from, msg.type);
}
for (const status of value.statuses || []) {
console.log('Status', status.id, status.status); // sent, delivered, read, failed
}
}
}
});
app.listen(3000);
Then, in the App Dashboard under WhatsApp > Configuration:
- Enter your Callback URL (for example
https://yourapp.com/webhook/whatsapp) and Verify token, then click Verify and save. - Under webhook fields, subscribe to
messages. This field carries both inbound messages and status updates.
If Meta can't deliver an event, it retries for some time, so your handler should cope with receiving the same event twice. Use the message or status id to remove duplicates.
Step 6- Create a Message Template
Messages that start a conversation outside the 24-hour customer service window must use an approved template. Create one in WhatsApp Manager > Message templates, or through the API:
curl -X POST "https://graph.facebook.com/$API_VERSION/$WABA_ID/message_templates" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "order_confirmation",
"language": "en",
"category": "UTILITY",
"components": [
{ "type": "BODY",
"text": "Hi {{1}}, your order {{2}} is confirmed.",
"example": { "body_text": [["Asha", "#10234"]] } }
]
}'
Choose the category carefully. Marketing is for promotions, Utility is for transactional updates, and Authentication is for OTPs. Meta can recategorise or reject a template whose content doesn't match its category, and the category also decides pricing. Check the status with GET /$WABA_ID/message_templates?name=order_confirmation, and wait for APPROVED before sending. For approval tips, see our WhatsApp template approval guide.
Step 7- Send a Test Message and Confirm Webhooks
curl -X POST "https://graph.facebook.com/$API_VERSION/$PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": {
"name": "order_confirmation",
"language": { "code": "en" },
"components": [
{ "type": "body",
"parameters": [
{ "type": "text", "text": "Asha" },
{ "type": "text", "text": "#10234" }
] }
]
}
}'
Write the recipient number in international format without + (for India, start with 91). A successful response returns a message id (wamid...). This means Meta accepted the message, not that it was delivered.
Go-live checklist:
- Your webhook receives
sent,delivered, andreadstatuses for thatwamid - Replying from the test phone triggers an inbound
messagesevent - Inside the 24-hour window, you can reply with a free-form
"type": "text"message - The business display name shows correctly on the recipient's phone
- Failed sends are logged with their error
code, and your retry logic follows our rate limits guide
Common Setup Errors and Fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Webhook "Verify and save" fails | Endpoint returns JSON or the wrong value, or the verify token doesn't match | Return the raw hub.challenge value as plain text with HTTP 200, and check that VERIFY_TOKEN matches exactly |
| Webhook verifies but no events arrive | App not subscribed to the WABA, or messages field not subscribed | Run Step 4 and check that the messages webhook field is subscribed |
| Every POST fails signature check | Signature computed on re-serialised JSON instead of the raw body, or wrong App Secret | Compute the HMAC on the raw request body using the App Secret from App settings > Basic |
| 401 / error code 190 | Temporary token expired, token revoked, or System User not assigned to the WABA | Use a System User token with no expiry and check its asset assignment and permissions |
| Error about permissions on send | Token missing whatsapp_business_messaging | Regenerate the token with both WhatsApp permissions |
| Number registration fails | Number still active on the WhatsApp or WhatsApp Business app | Delete the WhatsApp account on that number in the app, then add and register it again |
| Template send fails with template error | Template not yet APPROVED, wrong language code, or wrong number of parameters | Check the template status and send exactly the parameters it defines, in its exact language code |
| Sends fail after many succeed | Messaging limit or throughput reached | See WhatsApp API rate limits and error codes |
Frequently Asked Questions- WhatsApp Cloud API Setup
How long does WhatsApp Cloud API setup take? The technical setup- app, token, webhook, and test send- can be done in a day using Meta's test number. Going live on your own number usually takes 3 to 5 business days, because Meta business verification and template approval each take 1 to 3 days. These two can run in parallel.
Can I test the WhatsApp Cloud API before business verification? Yes. Meta's test number and temporary token let you send to a small allowed list of recipient numbers, which is enough to build your webhook and send logic.
What is a System User token and why do I need one? A System User is a non-human account used for server-to-server calls. Its token can be set to never expire, unlike the App Dashboard's temporary token, which expires after about 24 hours.
Is the On-Premises API still an option? No. Meta has sunset the On-Premises API. Build new integrations on the Cloud API only.
Do I have to do this setup myself? No. Get Click Media's managed WhatsApp Business API service handles verification, number registration, and templates for you.
Official References
- WhatsApp Cloud API- Get started (Meta for Developers)
- Webhooks for WhatsApp (Meta for Developers)
- WhatsApp Cloud API error codes (Meta for Developers)
- WhatsApp Business Platform changelog
Next Steps
Once your integration is live, see WhatsApp API integration for CRM and workflow patterns, the WhatsApp webhooks guide for event handling, and WhatsApp API rate limits before your first large send.
Article topics
Frequently Asked Questions
How long does WhatsApp Cloud API setup take?
The technical setup- app, token, webhook, and test send- can be done in a day using Meta's test number. Going live on your own number usually takes 3 to 5 business days, because Meta business verification and template approval each take 1 to 3 days. These two can run in parallel.
Can I test the WhatsApp Cloud API before business verification?
Yes. When you add the WhatsApp product to a Meta app, Meta gives you a test phone number and a temporary access token. You can send to a small number of recipient numbers you add to an allowed list, which is enough to build and test your webhook and send logic before your own number is live.
What is a System User token and why do I need one?
A System User is a non-human account in your business portfolio used for server-to-server API calls. You can generate its access token with no expiry date, unlike the temporary token in the App Dashboard, which expires after about 24 hours. Production integrations should always use a System User token with the whatsapp_business_messaging and whatsapp_business_management permissions.
Is the On-Premises API still an option?
No. Meta has sunset the On-Premises API, and the Cloud API is the supported way to integrate with the WhatsApp Business Platform. New integrations should be built on the Cloud API only.
Do I have to do this setup myself?
No. If you would rather not configure Meta's portals and APIs yourself, a Business Solution Provider can handle onboarding for you. Get Click Media's managed WhatsApp Business API service covers verification, number registration, and templates- see the WhatsApp Business API page for details.
About the author
Get Click Media creates practical resources for businesses using messaging, automation, analytics, and digital communication to improve customer engagement. This article was published on and was last reviewed on .

