Build WhatsApp into your own product
A clean, well-documented REST API on the official WhatsApp Business Platform. Send messages and templates, manage contacts and receive real-time events — straight from your backend, with a single API key.
Bearer API keys Predictable JSON errors Rate-limited & idempotent
curl -X POST https://api.wazappy.com/api/v1/messages/send \
-H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "+919555592220",
"type": "text",
"message": "Hi Priya! Your order #1042 has shipped 🚚"
}'What you can build
One API for every WhatsApp workflow
The same engine that powers WaZappy flows and campaigns, exposed as a simple REST API for your own code.
Notify from your own app
Fire order confirmations, shipping updates, OTPs and reminders straight from your backend when events happen.
Wire WhatsApp into your stack
Trigger messages from your CRM, ERP, e-commerce or internal tools — no dashboard needed.
Send approved templates at scale
Deliver any approved template — with dynamic header, body variables, buttons, carousels and offers.
Keep contacts in sync
Upsert customers with tags, status and marketing opt-in as they sign up or transact in your system.
Build custom AI agents
Pair the API with your own logic (or the MCP server) to run bespoke WhatsApp assistants.
Log & reconcile
Every API send is recorded for reports, so programmatic traffic shows up alongside the rest.
Quickstart
Send your first message in 3 steps
- 1
Get an API key
On a plan that includes API access (Pro and above), open the dashboard → Developers / API Keys → Create key. You can scope a key to one WhatsApp number. The full key is shown once — copy it (you can also reveal it again later).
- 2
Set your base URL & auth
Point requests at https://api.wazappy.com/api/v1 and send your key as an Authorization: Bearer header (or x-api-key).
- 3
Call /messages/send
Post a JSON body with the recipient and message. You get back a messageId you can track in Message Reports.
const res = await fetch("https://api.wazappy.com/api/v1/messages/send", {
method: "POST",
headers: {
"Authorization": "Bearer wz_live_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "+919555592220",
type: "text",
message: "Hi Priya! Your order #1042 has shipped",
}),
});
const data = await res.json();
// { success: true, messageId: "wamid.HBg...", to: "919555592220", type: "text" }
console.log(data);import requests
res = requests.post(
"https://api.wazappy.com/api/v1/messages/send",
headers={"Authorization": "Bearer wz_live_xxxxxxxxxxxxxxxx"},
json={
"to": "+919555592220",
"type": "text",
"message": "Hi Priya! Your order #1042 has shipped",
},
)
print(res.json())Authentication
API keys & base URL
Every request is authenticated with a secret API key that starts with wz_live_. Send it as a Bearer token, or as an x-api-key header.
- Keys are tied to your account and (optionally) a specific WhatsApp number.
- Treat keys like passwords — use them server-side only, never in a browser or mobile app.
- Revoke or rotate a key anytime from the dashboard; requests with it stop immediately.
Base URL
https://api.wazappy.com/api/v1
Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
# or, equivalently:
x-api-key: wz_live_xxxxxxxxxxxxxxxxcurl https://api.wazappy.com/api/v1/status \
-H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx"Reference
Endpoints
All paths are relative to https://api.wazappy.com/api/v1. All requests and responses are JSON.
/messages/sendSend a text, image, video, document or audio message to a number.
/messages/templateSend any approved template — dynamic header, body variables, buttons, carousel & limited-time offer.
/contactsCreate or update a contact (idempotent upsert) with name, email, tags, status and opt-in.
/templatesList your APPROVED templates, normalised into a render-ready spec so you know exactly which inputs to send.
/statusHealth snapshot — plan, API access, connected number, quality rating and key usage.
POST /messages/send
Send a text or media message. Fields: to (required), type (text, image, video, document, audio), and either message (for text) or mediaUrl/mediaId with an optional caption.
curl -X POST https://api.wazappy.com/api/v1/messages/send \
-H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "+919555592220",
"type": "text",
"message": "Hi Priya! Your order #1042 has shipped 🚚"
}'curl -X POST https://api.wazappy.com/api/v1/messages/send \
-H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "+919555592220",
"type": "image",
"mediaUrl": "https://example.com/invoice-1042.jpg",
"caption": "Your invoice for order #1042"
}'Media accepts either a public mediaUrl or a Meta media mediaId from your gallery. Documents may include a filename.
POST /messages/template
Send any approved template. Supports positional bodyVariables or named bodyParams, a dynamic header (text / image / video / document / location), buttons (url, copy_code, quick_reply, flow), a limited-time offer and multi-card carousels.
curl -X POST https://api.wazappy.com/api/v1/messages/template \
-H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "+919555592220",
"templateName": "order_update",
"languageCode": "en",
"bodyVariables": ["#1042", "shipped"],
"buttons": [
{ "index": 0, "subType": "url", "value": "1042" }
]
}'POST /contacts
Idempotent upsert keyed on the phone number. Set name, email, tags, status, source and marketing optin.
curl -X POST https://api.wazappy.com/api/v1/contacts \
-H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919555592220",
"name": "Priya Nair",
"email": "priya@example.com",
"tags": ["vip", "d2c"],
"optin": true
}'Templates
GET /templates
Returns your APPROVED templates normalised into a render-ready spec — header type, body placeholders (positional or named), footer, buttons and carousel cards — so your client knows exactly which inputs to collect without hardcoding a single template. Results are cached for ~10 minutes.
- Discover placeholders before you send
- Build dynamic forms from the spec
- Reuse the same code for every template
Status
GET /status
A quick health snapshot for your integration — plan, API access, the connected number and its quality rating, and this key’s usage.
{
"success": true,
"account": { "plan": "pro", "apiAccess": true },
"number": {
"phoneId": "1029384756",
"phoneNumber": "+91 95555 92220",
"status": "active",
"qualityRating": "GREEN"
},
"key": {
"name": "Production key",
"prefix": "wz_live_ab12cd",
"lastUsedAt": "2026-08-05T09:12:44.000Z",
"requestCount": 18422
}
}Webhooks
Get events in real time
Register a webhook URL in your dashboard to receive delivery status updates (sent → delivered → read → failed) and inbound customer messages as they happen. You can also POST to any endpoint mid-flow with the HTTP request node, so your systems stay in sync without polling.
- Delivery & read receipts for every send
- Inbound message events
- Flow-triggered callbacks to any URL
{
"event": "message.status",
"messageId": "wamid.HBg...",
"to": "919555592220",
"status": "delivered",
"timestamp": "2026-08-05T09:13:02.000Z"
}Fair use
Rate limits & idempotency
60
requests / minute
Per API key. A 429 with RATE_LIMITED is returned when you exceed it.
5,000
requests / day
Per API key. Need more? Talk to us about higher limits.
30s
duplicate guard
Identical content to the same number inside the window returns 409 DUPLICATE_MESSAGE — safe retries, no double-sends.
Note: WhatsApp’s own per-number throughput and quality tier apply on top of these limits. Message usage is billed by Meta directly.
Errors
Predictable error codes
Failures return the right HTTP status and a stable JSON body: { success: false, code, message }. Branch on code, not the message text.
| HTTP | Code | When it happens |
|---|---|---|
| 401 | NO_API_KEY | No key supplied in the Authorization / x-api-key header. |
| 401 | INVALID_API_KEY | Key is unknown or has been revoked. |
| 401 | API_KEY_INACTIVE | The key was disabled from the dashboard. |
| 402 | PLAN_INACTIVE | Subscription expired — renew to continue. |
| 403 | API_NOT_IN_PLAN | Your plan does not include API access — upgrade to Pro or higher. |
| 400 | NO_WHATSAPP_NUMBER | No WhatsApp number is connected to the account. |
| 400 | NUMBER_NOT_ACTIVE | The connected number is not activated or is disabled. |
| 403 | META_ACCOUNT_RESTRICTED | Meta has restricted the WhatsApp Business account (check Account Quality). |
| 402 | META_BILLING_ISSUE | A billing issue exists on your Meta WhatsApp account. |
| 429 | RATE_LIMITED | Too many requests — see the rate limits below. |
| 409 | DUPLICATE_MESSAGE | Identical content sent to the same number within the dedupe window. |
| 400 | BAD_REQUEST | Missing required fields or invalid values. |
| 502 | SEND_FAILED | WhatsApp rejected the message — details are included in the response. |
| 500 | SERVER_ERROR | Something went wrong on our side — retry shortly. |
Ready to build?
Create an account, generate an API key, and send your first message in minutes. Questions? Our team is a message away.
Ready to put WhatsApp to work?
Start on the free plan, connect your number, and send your first automated reply today. No setup fee, no card.
Free plan · No setup fee · Messages billed by Meta at cost