API reference
Send WhatsApp templates and receive events.
Use the REST API to send approved WhatsApp templates from your website, CRM or backend, and use webhooks to receive incoming messages and delivery updates in real time.
1. Create an API campaign
- Create and get a template approved in Templates.
- Go to Campaigns → New campaign → API campaign, name it and choose the template.
- Set the campaign Live. Copy your key from Settings → API Keys.
2. Send a message
POST {API_URL}/api/v2/campaign/send
curl -X POST "$API_URL/api/v2/campaign/send" \
-H "Content-Type: application/json" \
-d '{
"apiKey": "YOUR_API_KEY",
"campaignName": "order_confirmation_api",
"destination": "+919876543210",
"userName": "Priya Sharma",
"source": "website-checkout",
"media": { "url": "https://example.com/invoice.pdf", "filename": "invoice.pdf" },
"templateParams": ["Priya", "#4821", "Thursday"],
"tags": ["customer", "cod"],
"attributes": { "city": "Pune", "order_value": "1249" }
}'Request fields
| Field | Type | Required | Description |
|---|---|---|---|
apiKey | string | Required | Your workspace API key from Settings → API Keys. |
campaignName | string | Required | Name of an API campaign whose status is Live. |
destination | string | Required | Recipient number with country code, e.g. +919876543210. Numbers without a code default to +91. |
userName | string | Required | Recipient name. Creates or updates the contact. |
source | string | Optional | Lead source, used for source-based segments. |
media | object | Optional | { url, filename } — required when the template has a media header. |
templateParams | string[] | Optional | Values for {{1}}, {{2}}… in order. |
tags | string[] | Optional | Tags to add to the contact. |
attributes | object | Optional | Key/value attributes to save on the contact. |
If the destination does not exist in your contacts, a new contact is created with the name, tags and attributes you send.
Success response
{
"success": true,
"messageId": "665f1c2a9b1e4a0012ab34cd",
"contactId": "665f1c2a9b1e4a0012ab34aa"
}Errors
{
"success": false,
"error": "Campaign not found or not live"
}| HTTP | Meaning |
|---|---|
400 | Missing or invalid field (e.g. destination not a valid number, wrong number of templateParams). |
401 | Invalid or revoked apiKey. |
402 | Insufficient wallet balance or plan does not include the template API. |
404 | Campaign not found or not Live. |
409 | Contact has opted out or is blocked. |
429 | Rate limit exceeded — retry with exponential backoff. |
502 | WhatsApp rejected the message; the response includes Meta’s error code. |
3. Receive events with webhooks
Add an endpoint in Settings → Webhooks (Premium and above) and choose events. We send message.received for inbound messages and message.status for sent / delivered / read / failed updates.
POST https://your-server.com/whatsapp-events
x-signature: sha256=5d1c0f... (HMAC-SHA256 of the raw body using your webhook secret)
Content-Type: application/json
{
"event": "message.received",
"workspaceId": "665f...",
"timestamp": "2026-10-27T10:21:09.000Z",
"data": {
"contact": { "id": "665f...", "phone": "919876543210", "name": "Priya" },
"message": { "id": "665f...", "type": "text", "text": "Is COD available?" }
}
}
{
"event": "message.status",
"data": { "messageId": "665f...", "wamid": "wamid.HBg...", "status": "delivered", "campaign": "order_confirmation_api" }
}Verify the signature
Every request carries an x-signature header: an HMAC-SHA256 of the raw request body using your webhook secret. Reject requests that do not match.
const crypto = require('crypto');
function isValid(rawBody, signatureHeader, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
}Retries
Respond with any 2xx within 10 seconds. Failed deliveries are retried with backoff; the endpoint is disabled after repeated failures and you are notified.