A complete developer reference for integrating with JaldiDM over the official WhatsApp Cloud API — send messages, manage media and templates, and receive events.
JaldiDM is a thin relay in front of the official Meta WhatsApp Cloud API. You call our endpoints with a simple bearer token; we forward your request to Meta on the WhatsApp number that token is bound to, and pass Meta's response back to you. Message payloads are forwarded 1:1 to Meta — the JSON body you send to JaldiDM is the same JSON body Meta receives, so any example in Meta's own documentation works here unchanged.
All requests are made over HTTPS to the following base URL:
https://app.jaldidm.com/api/v1
Every JaldiDM request is authenticated with a bearer token passed in the Authorization header. Generate a token in the dashboard under Settings → Numbers → API tokens. The token determines which WhatsApp number sends — you never pass a phone number id in the URL. Keep the token secret and never expose it in client-side code.
Authorization: Bearer <YOUR_API_TOKEN>
Requests with a missing, invalid, or paused token return 401 Unauthorized.
Every write endpoint uses the same shape: a POST to a path under the base URL, your token in the header, and a JSON body. This skeleton is the basis for all the examples below.
curl -X POST 'https://app.jaldidm.com/api/v1/messages' \
-H 'Authorization: Bearer <YOUR_API_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{ ... json body ... }'
Placeholders used throughout this reference: <YOUR_API_TOKEN> — your JaldiDM API token; {MEDIA_ID} — the id returned by the Upload media call; {WABA_ID} / {PHONE_ID} — your WhatsApp Business Account and phone number ids.
https://app.jaldidm.com/api/v1/me
Sanity-check a fresh token before wiring it into anything. Returns the WhatsApp number this token is bound to.
Response
{
"ok": true,
"token": { "id": "uuid", "name": "n8n booking flow" },
"business_phone_number_id": "1150287611490963",
"number": {
"phone_number_id": "1150287611490963",
"display_phone_number": "+91 90847 23091",
"verified_name": "Acme Support",
"nickname": "URoots"
}
}
https://app.jaldidm.com/api/v1/messages
Plain text reply. Only works inside the 24-hour customer-service window — outside that window, use a template instead.
Request
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "919876543210",
"type": "text",
"text": {
"preview_url": false,
"body": "Hi! How can we help?"
}
}
Response
{
"messaging_product": "whatsapp",
"contacts": [{ "input": "919876543210", "wa_id": "919876543210" }],
"messages": [{ "id": "wamid.HBgM..." }]
}
https://app.jaldidm.com/api/v1/messages
Send a pre-approved template by name. Use this when the 24h window is closed or you're starting a fresh conversation.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": {
"name": "hello_world",
"language": { "code": "en_US" }
}
}
Response
{
"messaging_product": "whatsapp",
"contacts": [{ "input": "919876543210", "wa_id": "919876543210" }],
"messages": [{ "id": "wamid.HBgM..." }]
}
https://app.jaldidm.com/api/v1/messages
Pass variables for {{1}}, {{2}}, ... placeholders in the template body.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": {
"name": "appointment_reminder",
"language": { "code": "en_US" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Mohd Khushnaseeb" },
{ "type": "text", "text": "Tuesday, 12 May at 4:00 PM" }
]
}
]
}
}
Response
{
"messages": [{ "id": "wamid.HBgM..." }]
}
https://app.jaldidm.com/api/v1/messages
Approved template that has an IMAGE in its header — useful for the magic_message style cards. Upload your image first to get a media_id.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": {
"name": "magic_message",
"language": { "code": "en_US" },
"components": [
{
"type": "header",
"parameters": [
{ "type": "image", "image": { "id": "{MEDIA_ID}" } }
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Mohd Khushnaseeb" }
]
}
]
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
PDF / DOCX in the template header. Pass media_id or a public link.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": {
"name": "invoice_template",
"language": { "code": "en_US" },
"components": [
{
"type": "header",
"parameters": [
{
"type": "document",
"document": {
"id": "{MEDIA_ID}",
"filename": "invoice-may.pdf"
}
}
]
}
]
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
MP4 video header for templates that were approved with a video header.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": {
"name": "promo_video",
"language": { "code": "en_US" },
"components": [
{
"type": "header",
"parameters": [
{ "type": "video", "video": { "id": "{MEDIA_ID}" } }
]
}
]
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Real-world template: body has {{1}} {{2}} placeholders AND a CTA URL button whose URL contains {{1}}. Send ALL component parameters in one call — missing any one of them returns Meta error 135000 'Generic user error'.
Request
{
"to": "919876543210",
"type": "template",
"template": {
"name": "order_confirmation_v6",
"language": { "code": "en_US" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "12893" },
{ "type": "text", "text": "5-7 working days" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [
{ "type": "text", "text": "12893" }
]
}
]
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Free-form image (inside 24h window). Pass a media_id you uploaded earlier or a public URL.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "image",
"image": {
"id": "{MEDIA_ID}",
"caption": "Sample photo from clinic"
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
MP4 video (inside 24h window). Optional caption.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "video",
"video": {
"id": "{MEDIA_ID}",
"caption": "Procedure walkthrough"
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
PDF / DOCX / XLSX. Always pass a filename the user will see.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "document",
"document": {
"id": "{MEDIA_ID}",
"filename": "treatment-plan.pdf",
"caption": "Your treatment plan"
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Audio file. WhatsApp shows it as a voice note.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "audio",
"audio": { "id": "{MEDIA_ID}" }
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
WebP sticker. Animated stickers also use this endpoint.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "sticker",
"sticker": { "id": "{MEDIA_ID}" }
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Quick-reply buttons. User taps one, you receive an inbound message of type interactive with the button id.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "interactive",
"interactive": {
"type": "button",
"body": { "text": "Are you ready to book your consultation?" },
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "yes_book", "title": "Yes, book" } },
{ "type": "reply", "reply": { "id": "later", "title": "Later" } },
{ "type": "reply", "reply": { "id": "no_thanks", "title": "No thanks" } }
]
}
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Drop-down list of options. Better than buttons when you have more than 3 choices.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "interactive",
"interactive": {
"type": "list",
"body": { "text": "Pick a clinic to book at:" },
"action": {
"button": "Choose clinic",
"sections": [
{
"title": "North India",
"rows": [
{ "id": "delhi", "title": "Delhi" },
{ "id": "haridwar", "title": "Haridwar" }
]
},
{
"title": "South India",
"rows": [
{ "id": "hyderabad", "title": "Hyderabad" }
]
}
]
}
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Add an emoji reaction to a message you previously received.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "reaction",
"reaction": {
"message_id": "wamid.HBgMOTE5MDg0NzIzMDkxFQIAEhggMTIzNDU2Nzg5MA==",
"emoji": "❤️"
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Static lat/long with a label.
Request
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "location",
"location": {
"latitude": 28.6139,
"longitude": 77.2090,
"name": "QHT Delhi Clinic",
"address": "Connaught Place, New Delhi"
}
}
Response
{ "messages": [{ "id": "wamid.HBgM..." }] }
https://app.jaldidm.com/api/v1/messages
Tell Meta the user's message has been seen. Optionally include typing_indicator to show 'typing…' on the user's screen.
Request
{
"messaging_product": "whatsapp",
"status": "read",
"message_id": "wamid.HBgMOTE5MDg0NzIzMDkxFQIAEhggMTIzNDU2Nzg5MA==",
"typing_indicator": { "type": "text" }
}
Response
{ "success": true }
https://app.jaldidm.com/api/v1/media
Upload a file and get back a media_id you can pass to any send-message call. Multipart form, not JSON. Same Bearer token as /messages.
Request
# Multipart form fields:
type = image/jpeg (or image/png, video/mp4, audio/ogg, application/pdf, image/webp …)
file = @/path/to/file.jpg
curl -X POST 'https://app.jaldidm.com/api/v1/media' \
-H 'Authorization: Bearer <YOUR_API_TOKEN>' \
-F 'type=image/jpeg' \
-F 'file=@/path/to/file.jpg'
Response
{ "id": "1234567890" }
https://app.jaldidm.com/api/v1/media/<id>
Given a media_id (from an inbound webhook), download the raw file bytes. The relay resolves Meta's private download URL server-side and streams the file back to you.
Response
# Binary — the raw file bytes, Content-Type from Meta
# (image/jpeg, video/mp4, application/pdf, …)
Bearer <YOUR_API_TOKEN>.https://app.jaldidm.com/api/v1/media/<id>
Optional cleanup of a media_id you uploaded.
Response
{ "success": true }
Bearer <YOUR_API_TOKEN>.https://app.jaldidm.com/api/v1/templates?limit=200
Read every template attached to your WhatsApp Business Account.
Response
{
"data": [
{
"name": "magic_message",
"language": "en_US",
"status": "APPROVED",
"category": "UTILITY",
"components": [ /* header, body, footer, buttons */ ]
}
],
"paging": { "cursors": { "before": "...", "after": "..." } }
}
Bearer <YOUR_API_TOKEN>.https://app.jaldidm.com/api/v1/templates
Submit a template for Meta's approval. They typically review within minutes.
Request
{
"name": "appointment_reminder",
"language": "en_US",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Hi {{1}}, your appointment is on {{2}}.",
"example": {
"body_text": [["Mohd", "Tue 12 May, 4 PM"]]
}
}
]
}
Response
{
"id": "1234567890",
"status": "PENDING",
"category": "UTILITY"
}
Bearer <YOUR_API_TOKEN>.https://app.jaldidm.com/api/v1/templates?name=appointment_reminder
Remove a template by name.
Response
{ "success": true }
Bearer <YOUR_API_TOKEN>.https://your-app.example.com/api/webhook?hub.mode=subscribe&hub.verify_token=...&hub.challenge=...
First call from Meta when you save a webhook URL. Echo the challenge back to confirm you own the endpoint.
Response
# Plain-text response, not JSON:
<the value of hub.challenge>
https://your-app.example.com/api/webhook
What Meta POSTs when a user messages your number. This is what Meta sends TO your endpoint (not what you send to Meta). Respond with 200 OK quickly and process async.
Response
{
"object": "whatsapp_business_account",
"entry": [{
"id": "{WABA_ID}",
"changes": [{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "+91 90847 23091",
"phone_number_id": "{PHONE_ID}"
},
"contacts": [{
"profile": { "name": "Mohd" },
"wa_id": "919876543210"
}],
"messages": [{
"from": "919876543210",
"id": "wamid.HBgM...",
"timestamp": "1762668222",
"type": "text",
"text": { "body": "hi" }
}]
}
}]
}]
}
https://your-app.example.com/api/webhook
Sent / delivered / read / failed events for messages you previously sent.
Response
{
"entry": [{
"changes": [{
"value": {
"metadata": { "phone_number_id": "{PHONE_ID}" },
"statuses": [{
"id": "wamid.HBgMOTE5MDg0NzIzMDkxFQIAEhggMTIzNDU2Nzg5MA==",
"status": "delivered",
"timestamp": "1762668255",
"recipient_id": "919876543210"
}]
}
}]
}]
}
Different from Meta's webhooks above. These are events JaldiDM fires to URLs you registered under Settings → Numbers → Webhooks. Use them in n8n, Make, or any HTTP server.
X-QHT-Event, X-QHT-Signature: sha256=<hex>message.inbound, message.status, call.event.Verify the signature (Node.js)
import crypto from "crypto";
function ok(rawBody, headers, secret) {
const got = headers["x-qht-signature"];
const exp = "sha256=" + crypto
.createHmac("sha256", secret).update(rawBody).digest("hex");
return got && got.length === exp.length &&
crypto.timingSafeEqual(Buffer.from(got), Buffer.from(exp));
}
Customer messaged your number.
Payload
{
"type": "message.inbound",
"business_phone_number_id": "{PHONE_ID}",
"occurred_at": "2026-05-09T10:03:42Z",
"data": {
"wa_id": "919876543210",
"wa_message_id": "wamid.HBgM...",
"type": "text",
"profile_name": "Mohd",
"raw": { /* original Meta inbound */ }
}
}
Sent / delivered / read / failed for a message you previously sent.
Payload
{
"type": "message.status",
"business_phone_number_id": "{PHONE_ID}",
"occurred_at": "2026-05-09T10:04:15Z",
"data": {
"wa_message_id": "wamid.HBgM...",
"status": "delivered",
"error": null,
"raw": { /* original Meta status */ }
}
}
WhatsApp Cloud Calling state change.
Payload
{
"type": "call.event",
"business_phone_number_id": "{PHONE_ID}",
"occurred_at": "2026-05-09T10:05:00Z",
"data": {
"wa_call_id": "wacid....",
"event": "accept", // connect | accept | reject | terminate
"status": "accepted", // ringing | accepted | rejected | terminated | missed
"direction": "inbound",
"from": "919876543210",
"to": null,
"raw": { /* original Meta call */ }
}
}
Requests are subject to Meta's messaging limits. Respect the messaging limit and quality tier tied to your WhatsApp Business Account — these determine how many unique customers you can message in a rolling window. Sending within your tier and maintaining a high quality rating keeps your account in good standing; a drop in quality can lower your tier automatically.
The API uses standard HTTP status codes to indicate the outcome of a request:
Error responses include a JSON body describing what went wrong so you can log and handle it appropriately.
Need API access or the full reference? Email support@jaldidm.com.