WhatsApp Business API
Wpbox API Reference
Integrate with WhatsApp Cloud API to send messages, manage contacts, run campaigns, and automate customer communication at scale.
WhatsApp API - LLM Context
LLM ReadyFeed complete WhatsApp Business API specs directly to your AI agent or coding assistant.
Overview
The Wpbox API provides programmatic access to WhatsApp Business features. Built on top of the Meta WhatsApp Cloud API, it enables you to send messages, manage contacts, create campaigns, and work with approved message templates.
Base URL
https://app.wacm.in/api/v1All endpoints require authentication via Bearer token or query parameter. The API supports standard RESTful conventions with JSON request and response bodies.
Pagination
List endpoints (contacts, campaigns, conversations) return paginated responses. Use ?page= and ?limit= query parameters:
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://app.wacm.in/api/v1/contacts?page=2&limit=20"{
"data": [...],
"links": {
"first": "...",
"last": "...",
"prev": "...",
"next": "..."
},
"meta": {
"current_page": 2,
"last_page": 5,
"per_page": 20,
"total": 100
},
"status": "success",
"message": "Contacts retrieved successfully"
}Use ?search= to filter contacts and conversations by name or phone. Contacts, templates and campaigns use the resource pagination format above. Groups, campaign messages and conversations return a paginator nested under data; message history uses before_id.
Authentication
Use your Personal Access Token from the WACM dashboard (Settings → API) to authenticate requests.
curl -X GET "https://app.wacm.in/api/v1/contacts" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"Webhook Setup
Configure your WhatsApp webhook URL in the Meta Developer Console to receive incoming messages and status updates.
https://app.wacm.in/webhook/wpbox/receive/{your_token}For manual connections, copy the callback URL and verify token from WACM WhatsApp setup. The callback accepts GET challenges and POST events. The verification token must match the token in the callback URL. Embedded Signup manages the connection through WACM onboarding.
Webhook Payload - Incoming Message
{
"entry": [{
"id": "WABA_ID",
"changes": [{
"value": {
"messaging_product": "whatsapp",
"messages": [{
"from": "919876543210",
"id": "wamid.XXX",
"timestamp": "1234567890",
"type": "text",
"text": { "body": "Hello" }
}],
"contacts": [{
"profile": { "name": "John Doe" },
"wa_id": "919876543210"
}]
}
}]
}]
}Webhook Payload - Status Update
{
"entry": [{
"changes": [{
"value": {
"messaging_product": "whatsapp",
"statuses": [{
"id": "wamid.XXX",
"status": "delivered",
"timestamp": "1234567890",
"recipient_id": "919876543210"
}]
}
}]
}]
}Profile
/meGet authenticated user profile and company context
{
"status": "success",
"message": "Profile retrieved successfully",
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"company_name": "Acme Corp"
}
}Contacts
/contactsList all contacts with pagination (page, limit, search, group_id, tag_id, filter_condition)
/contactsCreate or update a contact with groups, tags, and custom fields
/contacts/bulk-syncCreate or match contacts in bulk and optionally assign them to a group or tag
/contacts/{id}Get contact details with groups, tags, and fields
/contacts/{id}Update contact information
/contacts/{id}Delete contact
/contacts/{id}/groups-and-fieldsGet contact groups and custom fields
/contacts/{id}/notesGet contact notes
/contacts/check-phoneCheck single-phone reachability (live checks may send a probe; 202 means pending)
/contacts/check-phonesBulk phone reachability check (safe mode by default; optional live probe with limits)
Single-phone checks accept phone and optional refresh. A live check may send a probe message. Results include nullable is_valid and exists_on_whatsapp, check_status (confirmed, unreachable or pending), source, checked_at and error fields. HTTP 202 with null reachability means pending webhook confirmation. Group preflight uses local data and sends no messages.
Create Contact
curl -X POST "https://app.wacm.in/api/v1/contacts" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"phone": "+919876543210",
"email": "john@example.com",
"city": "Mumbai",
"company_name": "Acme Corp"
}'Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | WhatsApp phone number with country code |
| name | string | Optional | Contact full name |
| string | Optional | Contact email address | |
| city | string | Optional | City name |
| country_id | integer | Optional | Country ID reference |
| company_name | string | Optional | Company name |
| subscribed | boolean | Optional | Subscription / opt-in status (default: true) |
| enabled_ai_bot | boolean | Optional | Enable or disable AI chatbot for this contact |
| groups | array | Optional | Array of group IDs to assign |
| tags | array | Optional | Array of tag IDs to assign |
| fields | object | Optional | Key-value map of custom field values |
Response
{
"status": "success",
"message": "Contact created/updated successfully",
"data": {
"id": 123,
"name": "John Doe",
"phone": "+919876543210",
"email": "john@example.com",
"city": "Mumbai",
"country": "India",
"company": "Acme Corp",
"subscribed": true,
"is_on_whatsapp": true,
"enabled_ai_bot": true,
"groups": [
{ "id": 1, "name": "VIP Customers" }
],
"tags": [
{ "id": 1, "name": "Lead", "color": "#10B981" }
],
"custom": {},
"created_at": "2025-01-15T10:30:00.000000Z",
"updated_at": "2025-01-15T10:30:00.000000Z"
}
}Bulk Sync and Group Assignment
Submit one or more contacts and optionally provide a company-owned group_id or tag_id. Existing contacts are matched by normalized phone number, new contacts are created within plan limits, and assignments are additive and idempotent.
curl -X POST "https://app.wacm.in/api/v1/contacts/bulk-sync" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{"phone": "9876543210", "name": "Jane Doe"},
{"phone": "+919876543211", "name": "John Doe"}
],
"country_code": "91",
"group_id": 123
}'Bulk Sync Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| contacts | array | Required | Non-empty contact list; every item requires a phone containing at least one digit |
| contacts[].phone | string | Required | Phone number; normalized before matching |
| contacts[].name | string | Optional | Contact name |
| country_code | string | Optional | Country calling code applied to local numbers |
| group_id | integer | Optional | Group ID owned by the authenticated company |
| tag_id | integer | Optional | Tag ID owned by the authenticated company |
{
"status": "success",
"message": "Contacts synced successfully",
"data": {
"synced_count": 2,
"updated_count": 0,
"created_count": 2,
"skipped_limit_count": 0
}
}Messages
/messages/textSend a text, media, or quick-reply button message
/messages/textSend a text message (GET)
/messages/templateSend an approved template message with component parameters
/messages/templateSend template message (GET)
/messages/listSend an interactive list message
/messages/listSend list message (GET)
Send Text / Media Message
curl -X POST "https://app.wacm.in/api/v1/messages/text" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"message": "Hello! This is a test message from WACM API."
}'Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | Recipient WhatsApp number |
| message | string | Optional | Message text content |
| media_url | string (URL) | Optional | Direct URL to media attachment (image, document, audio, video) |
| image | file | Optional | Multipart file upload |
| buttons | array | Optional | Array of up to 3 quick-reply buttons with id and title |
| header | string | Optional | Optional header text |
| footer | string | Optional | Optional footer text |
| button_name | string | Optional | Call-to-action button label |
| button_url | string (URL) | Optional | Call-to-action button URL |
Send Template Message
Send an approved Meta WhatsApp template message to a recipient. Templates support dynamic body text placeholders ({{1}}, {{2}}), buttons, and rich media headers (Image, PDF / Document, or Video).
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "order_confirmation",
"template_language": "en",
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "John Doe" },
{ "type": "text", "text": "ORD-12345" }
]
}
]
}'Template Message Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | Recipient phone number with country code (e.g. +919876543210) |
| template_name | string | Required | Meta-approved WhatsApp template name |
| template_language | string | Optional | Language code (default: en). Alias: language |
| components | array | Optional | Standard WhatsApp Cloud API component array for header, body, and button parameters |
| image | string (URL) | Optional | Shorthand parameter: Direct public HTTPS URL for template image header |
| document | string (URL) | Optional | Shorthand parameter: Direct public HTTPS URL for template document / PDF header |
| video | string (URL) | Optional | Shorthand parameter: Direct public HTTPS URL for template video header |
| variables | array/object | Optional | Shorthand parameter: Body variable replacement list (e.g. ["John", "ORD-12345"]) |
| header_variables | array | Optional | Shorthand parameter: Text header variable replacement list |
| scheduled_at | string | Optional | Schedule message delivery for a future time (ISO timestamp or YYYY-MM-DD HH:MM:SS) |
| timezone | string | Optional | Timezone for scheduled delivery (e.g. Asia/Kolkata, UTC) |
Template Media Headers: Image, PDF & Video
When your approved WhatsApp template has a media header (IMAGE, DOCUMENT, or VIDEO), you provide the direct public URL for the media asset when dispatching the message. WACM supports both the Standard Meta WhatsApp Cloud API components format and Clean Shorthand parameters.
1. Sending an Image Header
For promotional banners, discount vouchers, product highlights, and event posters
To send an image header using Cloud API components, set the component type to header, the parameter type to image, and provide the direct HTTPS link in image: { link: "..." }.
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "seasonal_sale_banner",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "image",
"image": {
"link": "https://cdn.example.com/promotions/diwali_special_banner.jpg"
}
}
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Param" },
{ "type": "text", "text": "FESTIVE50" }
]
}
]
}'⚡ Shorthand Alternative
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "seasonal_sale_banner",
"template_language": "en",
"image": "https://cdn.example.com/promotions/diwali_special_banner.jpg",
"variables": ["Param", "FESTIVE50"]
}'2. Sending a PDF / Document Header
For GST tax invoices, monthly statements, e-tickets, lab reports, and policy documents
For document templates, specify the parameter type as document with its link. You can also specify an optional filename attribute so the recipient sees a neat, human-readable file name (e.g. Tax_Invoice_INV2026.pdf) in their WhatsApp chat interface.
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "invoice_notification",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "document",
"document": {
"link": "https://cdn.example.com/invoices/2026/INV-98231.pdf",
"filename": "Tax_Invoice_INV98231.pdf"
}
}
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Param Mehta" },
{ "type": "text", "text": "INV-98231" },
{ "type": "text", "text": "₹14,999" }
]
}
]
}'⚡ Shorthand Alternative
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "invoice_notification",
"template_language": "en",
"document": "https://cdn.example.com/invoices/2026/INV-98231.pdf",
"variables": ["Param Mehta", "INV-98231", "₹14,999"]
}'3. Sending a Video Header
For onboarding tutorials, product launch teasers, video greetings, and campaign demos
For video templates, specify the parameter type as video and supply the direct link to the .mp4 file encoded with H.264 video and AAC audio codecs.
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "product_onboarding_tour",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "video",
"video": {
"link": "https://cdn.example.com/videos/onboarding_quickstart.mp4"
}
}
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Alex" }
]
}
]
}'⚡ Shorthand Alternative
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "product_onboarding_tour",
"template_language": "en",
"video": "https://cdn.example.com/videos/onboarding_quickstart.mp4",
"variables": ["Alex"]
}'Code Examples in Popular Languages
Send a PDF Invoice template message programmatically using your preferred runtime.
// Send PDF Invoice Template with Node.js
const response = await fetch('https://app.wacm.in/api/v1/messages/template', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.WACM_API_TOKEN,
'Content-Type': 'application/json'
},
body: JSON.stringify({
phone: '+919876543210',
template_name: 'invoice_notification',
template_language: 'en',
components: [
{
type: 'header',
parameters: [
{
type: 'document',
document: {
link: 'https://cdn.example.com/invoices/2026/INV-98231.pdf',
filename: 'Tax_Invoice_INV98231.pdf'
}
}
]
},
{
type: 'body',
parameters: [
{ type: 'text', text: 'Param Mehta' },
{ type: 'text', text: 'INV-98231' },
{ type: 'text', text: '₹14,999' }
]
}
]
})
});
const data = await response.json();
console.log('Message WAMID:', data.data?.message_wamid);# Send Media Template with Python
import os
import requests
url = "https://app.wacm.in/api/v1/messages/template"
headers = {
"Authorization": f"Bearer {os.getenv('WACM_API_TOKEN')}",
"Content-Type": "application/json"
}
payload = {
"phone": "+919876543210",
"template_name": "seasonal_sale_banner",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "image",
"image": {
"link": "https://cdn.example.com/promotions/diwali_special_banner.jpg"
}
}
]
},
{
"type": "body",
"parameters": [
{"type": "text", "text": "Param"},
{"type": "text", "text": "FESTIVE50"}
]
}
]
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Important Media Header Rules & Guidelines
Direct HTTPS URLs Required
The media link must be a direct public URL accessible overhttps:// without requiring cookies, session tokens, or authentication. Do NOT use Google Drive preview links (e.g. drive.google.com/file/d/.../view) or Dropbox landing pages; provide direct asset URLs from AWS S3, Cloudflare R2, Google Cloud Storage, or your public web server.Template Header Type Must Match Meta Approval
When you submit a template for approval to Meta, you select the header format (IMAGE, DOCUMENT, or VIDEO). When sending via API, the media component type in your payload must strictly match the approved format, or Meta will return an error (#132000 Template param count mismatch).Document Filename Recommendation
When sending invoices or sensitive documents, always populate thefilename property inside document. This provides a clear, professional preview inside the recipient's WhatsApp conversation list and helps customers easily locate downloaded files in their device storage.Supported Media Sources: Public URLs, Firebase Storage, Base64 & Meta Media ID
Developers frequently ask how WhatsApp Cloud API handles different storage and backend architectures. Here is the definitive breakdown of how Official Meta WhatsApp Cloud API works versus how WACM makes media sending effortless.
- • No native Base64: Meta's official Cloud API does not accept raw Base64 data strings directly in template parameters or media payloads. Attempting to pass Base64 to Meta triggers
(#100) Invalid parameter: link is not a valid URL. - • Requires Public HTTPS URL (
link): Meta servers must download the file via standard HTTP/HTTPS GET without custom headers or cookies. - • Or Meta Media ID (
id): Assets pre-uploaded via Meta'sPOST /{phone-number-id}/mediaGraph API endpoint.
- • Firebase Storage URLs Supported: Standard Firebase download URLs (with public download token) work 100% natively as
link. - • Built-in Base64 Auto-Decoding: WACM automatically intercepts Data URIs (
data:image/...;base64,...ordata:application/pdf;base64,...), decodes the binary, persists it to your company storage, and supplies Meta with the required HTTPS link. - • Meta Media ID Pass-Through: If you already upload media via Meta Graph API, provide the numeric ID in
{ id: "123456789" }.
Method 1: Firebase Storage Public Download URLs
Standard LinkWhen using Firebase Storage, generate a download URL via the Firebase Client/Admin SDK (getDownloadURL()). The resulting URL contains a public query token (?alt=media&token=...) allowing Meta's crawler to fetch the media without needing Firebase Auth headers.
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "order_receipt_pdf",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "document",
"document": {
"link": "https://firebasestorage.googleapis.com/v0/b/my-app.appspot.com/o/invoices%2FINV-8941.pdf?alt=media&token=4a1c5d9e-8b2f-4e6a-912c-7b8a3e4f5d6c",
"filename": "Invoice_INV8941.pdf"
}
}
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Param" },
{ "type": "text", "text": "INV-8941" }
]
}
]
}'Method 2: Direct Base64 Data URI (Auto-Hosted by WACM)
WACM ExclusiveIdeal when generating invoices (PDFs) or dynamic vouchers (PNG/JPG) on the fly in backend memory (e.g. Puppeteer, jsPDF, PDFKit, DOMPDF). Pass standard Data URI format (data:<mime>;base64,<data>) directly in link or shorthand. WACM automatically saves the asset and supplies Meta with the required public URL.
// Node.js: Generating and sending Base64 PDF directly
import fs from 'fs';
// In-memory buffer or generated invoice
const pdfBuffer = fs.readFileSync('./generated-invoice.pdf');
const base64Pdf = `data:application/pdf;base64,${pdfBuffer.toString('base64')}`;
const response = await fetch('https://app.wacm.in/api/v1/messages/template', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.WACM_API_TOKEN,
'Content-Type': 'application/json'
},
body: JSON.stringify({
phone: '+919876543210',
template_name: 'monthly_statement_pdf',
template_language: 'en',
components: [
{
type: 'header',
parameters: [
{
type: 'document',
document: {
link: base64Pdf,
filename: 'Statement_March_2026.pdf'
}
}
]
},
{
type: 'body',
parameters: [
{ type: 'text', text: 'Param' },
{ type: 'text', text: 'March 2026' }
]
}
]
})
});
const data = await response.json();
console.log('Result:', data);⚡ Python Base64 Example
import base64
import requests
with open("invoice.pdf", "rb") as f:
b64_data = base64.b64encode(f.read()).decode("utf-8")
data_uri = f"data:application/pdf;base64,{b64_data}"
response = requests.post(
"https://app.wacm.in/api/v1/messages/template",
headers={"Authorization": "Bearer YOUR_API_TOKEN"},
json={
"phone": "+919876543210",
"template_name": "invoice_receipt",
"template_language": "en",
"document": data_uri,
"filename": "Invoice_9021.pdf",
"variables": ["Param", "₹4,999"]
}
)
print(response.json())Method 3: Meta Media ID (id)
Meta UploadIf your workflow uploads media assets directly to Meta's servers using the WhatsApp Resumable Upload API or POST /{phone-number-id}/media, you can supply the resulting numeric id instead of a URL.
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "product_brochure",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "image",
"image": {
"id": "184920491823910"
}
}
]
}
]
}'| Source Type | Meta Native? | WACM Support? | Best For | Parameter Format |
|---|---|---|---|---|
| Public HTTPS URL (S3, CDN) | Yes | Yes | Pre-hosted static assets, catalogs | { "link": "https://..." } |
| Firebase Storage URL | Yes (with token) | Yes | Mobile & Firebase web apps | { "link": "https://firebasestorage..." } |
| Base64 Data URI | No (rejected by Meta) | Yes (Auto-hosted) | In-memory generated invoices, receipts | { "link": "data:image/...;base64,..." } |
| Meta Media ID | Yes | Yes | Pre-uploaded Meta media workflows | { "id": "184920491823910" } |
Send Interactive List Message
curl -X POST "https://app.wacm.in/api/v1/messages/list" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"message": "Please select from the options below:",
"header": "Main Menu",
"footer": "Powered by WACM",
"action": {
"button": "View Options",
"sections": [
{
"title": "Menu Options",
"rows": [
{ "id": "opt1", "title": "Check Order Status", "description": "Track your recent order" },
{ "id": "opt2", "title": "Talk to Support", "description": "Connect with an agent" }
]
}
]
}
}'List Message Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | Recipient WhatsApp number |
| message | string | Required | Main body message |
| action | object | Required | Interactive action configuration containing button label and sections list |
| header | string | Optional | Optional text header |
| footer | string | Optional | Optional text footer |
Media Upload & Meta Cloud API
Upload documents (PDFs), images, videos, audio clips, and stickers directly to the official Meta WhatsApp Cloud API (POST /{phone-number-id}/media). WACM streams the file to Meta's infrastructure, saves a copy in your configured company storage, and returns the official numeric Meta Media ID (id) alongside a storage url. Use the returned id in template header components. Meta controls media availability and download URL expiry; re-upload media when needed.
/mediaUpload media file directly to Meta Cloud API and company storage (returns Meta media ID and URL)
/media/{id}Retrieve Meta media metadata and temporary download URL from Meta Graph API
/media/{id}Delete media asset from Meta WhatsApp Cloud API
Media Upload Parameters (multipart/form-data)
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | file | Required | Binary media file. Max sizes: Document (PDF) 100MB, Video 16MB, Audio 16MB, Image (JPG/PNG) 5MB, Sticker 100KB |
Upload Media File (cURL)
curl -X POST "https://app.wacm.in/api/v1/media" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-F "file=@/path/to/invoice_INV-9821.pdf" \
-F "type=document"Upload Response
{
"status": "success",
"message": "Media uploaded to Meta successfully",
"data": {
"id": "184920491823910",
"url": "https://app.wacm.in/storage/uploads/companies/1/media/2026/03/invoice_INV-9821.pdf",
"mime_type": "application/pdf",
"file_name": "invoice_INV-9821.pdf",
"file_size": 245100
}
}Instead of re-uploading or exposing private S3/GCS buckets, pass the returned numeric id directly into your template header or message payload. WhatsApp servers already hold the binary, avoiding another upload.
curl -X POST "https://app.wacm.in/api/v1/messages/template" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919876543210",
"template_name": "invoice_delivery",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "document",
"document": {
"id": "184920491823910",
"filename": "Invoice_March2026.pdf"
}
}
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Param Mehta" },
{ "type": "text", "text": "₹14,999" }
]
}
]
}'Retrieve Media Details (GET)
Fetch Meta metadata and temporary download URL using the Media ID:
curl -X GET "https://app.wacm.in/api/v1/media/184920491823910" \
-H "Authorization: Bearer YOUR_API_TOKEN"Delete Media (DELETE)
Delete a media file from Meta WhatsApp Cloud servers:
curl -X DELETE "https://app.wacm.in/api/v1/media/184920491823910" \
-H "Authorization: Bearer YOUR_API_TOKEN"Programmatic SDK Examples (Upload & Send Flow)
import fs from 'fs';
import FormData from 'form-data';
import fetch from 'node-fetch';
const TOKEN = process.env.WACM_API_TOKEN;
// 1. Upload to Meta via WACM
const form = new FormData();
form.append('file', fs.createReadStream('./invoice.pdf'));
form.append('type', 'document');
const uploadRes = await fetch('https://app.wacm.in/api/v1/media', {
method: 'POST',
headers: { 'Authorization': `Bearer ${TOKEN}`, ...form.getHeaders() },
body: form
});
const { data: media } = await uploadRes.json();
console.log('Meta Media ID:', media.id);
// 2. Dispatch Template with returned Meta Media ID
const msgRes = await fetch('https://app.wacm.in/api/v1/messages/template', {
method: 'POST',
headers: {
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
phone: '+919876543210',
template_name: 'invoice_ready',
template_language: 'en',
components: [
{
type: 'header',
parameters: [{ type: 'document', document: { id: media.id, filename: 'Invoice.pdf' } }]
},
{
type: 'body',
parameters: [{ type: 'text', text: 'Param' }]
}
]
})
});
console.log('Template dispatch:', await msgRes.json());import requests
TOKEN = "YOUR_API_TOKEN"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
# 1. Upload file to Meta Cloud API via WACM
with open("invoice.pdf", "rb") as f:
files = {"file": ("invoice.pdf", f, "application/pdf")}
data = {"type": "document"}
upload_res = requests.post("https://app.wacm.in/api/v1/media", headers=HEADERS, files=files, data=data)
media = upload_res.json()["data"]
print("Meta Media ID:", media["id"])
# 2. Send template using the Meta Media ID
template_payload = {
"phone": "+919876543210",
"template_name": "invoice_ready",
"template_language": "en",
"components": [
{
"type": "header",
"parameters": [
{
"type": "document",
"document": {
"id": media["id"],
"filename": "Invoice.pdf"
}
}
]
},
{
"type": "body",
"parameters": [{"type": "text", "text": "Param"}]
}
]
}
send_res = requests.post("https://app.wacm.in/api/v1/messages/template", headers=HEADERS, json=template_payload)
print("Template dispatch:", send_res.json())Templates
/templatesList templates in all statuses (supports ?name=, ?status=, ?category=, ?language= filters; check status before sending)
/templates/capabilitiesGet workspace template creation capabilities, AI availability, and opt-out settings
/templates/startersList quick-start WhatsApp template presets with opt-out buttons
/templates/librarySearch pre-built industry WhatsApp templates by category, industry, and language
/templatesCreate and submit a new WhatsApp template to Meta
/templates/{id}Get template details
/templates/{id}Edit and resubmit a rejected or paused WhatsApp template to Meta
/templates/validateValidate template structure and Meta compliance rules without submitting
/templates/ai/generateGenerate a compliant WhatsApp template draft from a natural-language prompt
/templates/ai/reviewAudit a template draft for Meta approval risk and policy compliance
/templates/syncSync all templates from WhatsApp Business Account
/templates/{id}/syncSync a single template status from Meta
/templates/{id}Delete template from WhatsApp and local database
Response
{
"data": [
{
"id": 1,
"name": "order_confirmation",
"language": "en",
"status": "APPROVED",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Hi {{1}}, your order {{2}} has been confirmed!"
}
],
"created_at": "2025-01-15T10:30:00.000000Z",
"updated_at": "2025-01-15T10:30:00.000000Z"
}
],
"status": "success",
"message": "Templates retrieved successfully"
}Groups
/groupsList contact groups with contacts_count
/groupsCreate a contact group
/groups/{id}Get contact group details and up to 50 sample contacts
/groups/{id}Rename a contact group
/groups/{id}Delete a contact group and detach its contacts
/groups/{id}/contactsBulk attach, detach, or sync contacts in a group (contact_ids, action: attach|detach|sync)
/groups/{id}/preflightLocal group readiness summary; no WhatsApp messages are sent
/groups/{id}/check-phonesDeprecated alias for local preflight; no background WhatsApp probing
{
"status": "success",
"message": "Groups retrieved successfully",
"data": {
"current_page": 1,
"data": [
{
"id": 1,
"name": "VIP Customers",
"contacts_count": 150,
"created_at": "2025-01-15T10:30:00.000000Z",
"updated_at": "2025-01-15T10:30:00.000000Z"
}
],
"total": 1
}
}Campaigns
/campaignsList all campaigns with pagination (page, limit, search, type)
/campaignsCreate and dispatch a new campaign
/campaigns/audience-previewPreview eligible opted-in contacts count before launching
/campaigns/{id}Get campaign statistics and details
/campaigns/{id}/messagesList campaign message delivery transactions with status filter
/campaigns/{id}Update campaign status (pause/resume with is_active)
/campaigns/{id}/retryReactivate campaign and requeue retryable failures; returns retried and skipped counts
/campaigns/{id}Delete a campaign
/campaigns/sendQueue a message from an existing campaign (phone and campaign_id required)
Audience Preview
curl -X POST "https://app.wacm.in/api/v1/campaigns/audience-preview" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"audience_type": "group",
"group_id": 1,
"template_id": 12,
"prevent_template_duplicates": true
}'{
"status": "success",
"message": "Campaign audience preview retrieved successfully",
"data": {
"audience_type": "group",
"eligible_contacts": 142
}
}Audience preview does not send messages. Creating a campaign queues delivery and returns HTTP 201; it is not a draft. Include an Idempotency-Key header (max 255 characters) when creating campaigns: an identical retry returns the existing campaign with HTTP 200, while different input with the same key returns 409.
Create Campaign
curl -X POST "https://app.wacm.in/api/v1/campaigns" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer Sale 2025",
"template_id": 1,
"audience_type": "all",
"send_now": true,
"paramvalues": {
"1": "Summer Sale",
"2": "50% OFF"
}
}'Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Campaign name |
| template_id | integer | Required | Approved WhatsApp template ID |
| audience_type | string | Optional | Explicitly set all, group, or contact. If omitted, inferred from group_id/contact_id, otherwise all. |
| group_id | integer | Optional | Required if audience_type is "group". Prohibited otherwise. |
| contact_id | integer | Optional | Required if audience_type is "contact". Prohibited otherwise. |
| send_now | boolean | Optional | Send immediately (true, default) or schedule later (false) |
| send_time | string | Optional | ISO date string to send if send_now is false |
| prevent_template_duplicates | boolean | Optional | Exclude contacts that already received this template |
| paramvalues | object | array | JSON string | Optional | Template variable mapping values |
| parammatch | object | array | JSON string | Optional | Template variable field mapping |
| file | Optional | Multipart form data for PDF attachments | |
| imageupload | file | Optional | Multipart form data for Image/Video attachments |
Send from an Existing Campaign
{
"phone": "+919876543210",
"campaign_id": 123
}Optional data supplies extra template values. This endpoint uses the existing campaign's template; use /messages/template to send by template name. Paused campaigns return 409; ineligible contacts return 422. A successful response contains message_id, nullable message_wamid, numeric status, and billing_status.
Conversations
/conversationsList all conversations with pagination (page, limit, search, lastmessagetime)
/conversations/{id}/messagesGet conversation messages with pagination (limit, before_id, search, lastmessagetime)
Conversation IDs are contact IDs. Workspace and agent permissions apply. Lists default to 50 results; message history uses before_id for older messages.
/conversation-agentsList eligible workspace agents
/conversations/{id}Get operational details; id is the contact ID
/conversations/{id}/customerRequired name, email, city; email/city nullable; phone changes prohibited
/conversations/{id}/ai-botRequired boolean enabled_ai_bot
/conversations/{id}/assignmentRequired user_id; null unassigns
/conversations/{id}/statusRequired status: open or resolved
/conversations/{id}/snoozeRequired hours: 1–168; null clears snooze
/conversations/{id}/notesList up to 50 internal notes
/conversations/{id}/notesRequired nonblank note, max 2000 characters; 201; no outbound message
/conversations/{id}/tagsRequired tag_ids array; up to 50 distinct workspace IDs; empty array clears tags
/conversations/{id}/readOptional last_read_message_id; marks read for current user
Get Conversation Messages
{
"data": [
{
"id": 1,
"fb_message_id": "wamid.HBgM...",
"contact_id": 123,
"value": "Hello! How can I help you?",
"status": 4,
"is_message_by_contact": 0,
"message_type": 1,
"created_at": "2025-01-15T10:30:00.000000Z",
"updated_at": "2025-01-15T10:30:00.000000Z"
}
],
"status": "success",
"message": "Messages retrieved successfully"
}Message Types Reference
| Type | Code | Description |
|---|---|---|
| TEXT | 1 | Plain text message |
| MEDIA | 2 | Image, video, document, or audio |
| LOCATION | 3 | Location share (Google Maps) |
| NFM_REPLY | 5 | Interactive flow reply |
Media Specifications & Constraints
Summary of supported file formats, MIME types, and file size limits for WhatsApp template media headers and direct media messages.
| Media Type | Supported MIME Types | Max Size | Recommended Specs & Notes |
|---|---|---|---|
| Image | image/jpeg, image/png | 5 MB | 800x800 or 1200x628 (1.91:1) recommended. RGB/RGBA. Animated GIFs or WebP are not supported in template headers. |
| Document / PDF | application/pdf | 100 MB | Standard PDF format. Pass filename attribute to control file name displayed in WhatsApp UI. |
| Video | video/mp4, video/3gpp | 16 MB | H.264 video codec and AAC audio codec. 720p or 1080p resolution recommended. Must contain an audio track. |
| Audio | audio/aac, audio/mp4, audio/mpeg | 16 MB | Mono or stereo audio. Used for voice notes and voice recordings. |
Message Status Codes
Error Responses
Error Response Format
{
"message": "The phone number is required.",
"errors": {
"phone": ["The phone field is required."]
}
}eCommerce Store API
Manage products, categories, and orders.