Docs
Sending messages
One endpoint sends every WhatsApp message type. Messages are queued, paced to WhatsApp's limits and tracked through webhooks.
/v1/messages— Send one message/v1/messages/bulk— Send up to 1,000 messages/v1/messages/{id}— Retrieve a message and its statusRequest body
tostringoptionalRecipient phone in E.164, with or without+. One ofto,recipientorcontact_idis required.recipientstringoptionalWhatsApp business-scoped user id (BSUID), for users who hide their number.contact_iduuidoptionalAn Engage contact id.phone_number_iduuidoptionalEngage id of the sending number. Defaults to your organization's default number.typeenumrequiredtext·template·image·video·audio·document·sticker·location·contacts·interactive·reaction{type}objectrequiredAn object named after the type with its content, e.g.text,image.reply_touuidoptionalEngage message id to quote as a reply.client_refstringoptionalYour own reference, echoed in status webhooks.
The response is 202 Accepted with { "id": "…", "status": "queued" }. Status then moves through sent → delivered → read, or ends in failed with an error object.
template requires an open 24-hour window — i.e. the customer messaged you in the last 24 hours.Text
Up to 4,096 characters. WhatsApp formatting is supported: *bold*, _italic_, ~strike~, ```mono```. Set preview_url to render a link preview.
{
"to": "+919812345678",
"type": "text",
"text": {
"body": "Hi Ananya! Your order *#48213* has shipped 🚚 Track it: https://acme.in/t/48213",
"preview_url": true
}
}Template
Templates can be sent at any time. Reference them by name + language or by Engage template_id. Fill parameters with the simple variables map — keys are the placeholder names (1, 2… for positional templates, or the parameter name for named ones), prefixed with the component when needed: header.1, button.0.
{
"to": "+919812345678",
"type": "template",
"template": {
"name": "order_shipped",
"language": "en",
"variables": {
"1": "Ananya",
"2": "#48213",
"header.1": "https://cdn.acme.in/orders/48213.jpg",
"button.0": "48213"
}
}
}Prefer full control? Pass Meta's components array instead of variables and Engage forwards it unchanged.
Media
Send image, video, audio, document or sticker with either an Engage media_id (from POST /v1/media) or a public HTTPS link.
{
"to": "+919812345678",
"type": "image",
"image": {
"link": "https://cdn.acme.in/sale.jpg",
"caption": "Festive sale — 30% off today only"
}
}Uploading media
curl https://api.engage.swastik.ai/v1/media \
-H "Authorization: Bearer $ENGAGE_API_KEY" \
-F "file=@./brochure.pdf"
# → { "id": "6a1f0c2e-…", "kind": "document", "mime": "application/pdf",
# "size_bytes": 482113, "filename": "brochure.pdf", "url": "…" }Location
{
"to": "+919812345678",
"type": "location",
"location": {
"latitude": 12.9716,
"longitude": 77.5946,
"name": "Acme Store — Indiranagar",
"address": "100 Feet Rd, Bengaluru 560038"
}
}Contacts
{
"to": "+919812345678",
"type": "contacts",
"contacts": [
{
"name": {
"formatted_name": "Acme Support",
"first_name": "Acme"
},
"phones": [
{
"phone": "+918045671234",
"type": "WORK"
}
],
"emails": [
{
"email": "support@acme.in",
"type": "WORK"
}
]
}
]
}The contacts array follows Meta's contact object schema.
Interactive
Pass Meta's interactive object as-is. Replies arrive as message.received webhooks with the chosen button or row id.
{
"to": "+919812345678",
"type": "interactive",
"interactive": {
"type": "button",
"body": {
"text": "Confirm your delivery slot for Saturday, 9–11 AM?"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "slot_confirm",
"title": "Confirm"
}
},
{
"type": "reply",
"reply": {
"id": "slot_change",
"title": "Change slot"
}
}
]
}
}
}Reaction
React to a message you received. Send an empty emoji to remove the reaction.
{
"to": "+919812345678",
"type": "reaction",
"reaction": {
"message_id": "8b2e3f1a-…",
"emoji": "👍"
}
}Replying to a message
Add reply_to with the Engage id of an inbound message to show it as a quoted reply.
{
"to": "+919812345678",
"type": "text",
"reply_to": "8b2e3f1a-…",
"text": {
"body": "Yes — the blue variant is back in stock!"
}
}Bulk send
Send up to 1,000 messages per request. Each item is validated independently; the response lists results in the same order.
{
"messages": [
{ "to": "+919812345678", "type": "template", "template": { "name": "order_shipped", "language": "en", "variables": { "1": "Ananya", "2": "#48213" } } },
{ "to": "+91000", "type": "text", "text": { "body": "Hi" } }
]
}
// → 200
{
"data": [
{ "id": "0f9b1c7e-…", "status": "queued" },
{ "error": { "code": "validation_failed", "message": "to must be a valid phone number" } }
]
}For large audiences, prefer campaigns — they handle audience expansion, opt-outs and reporting for you.