Send Message
POST /api/external/send-message
Auth: Authorization: Bearer ck_<api_key> (required)
Send WhatsApp messages of type text, template, image, video, audio, or document.
Important: Do not use
type: "text" with mediaUrl expecting a photo — that only delivers text. For photos/files use type: "image" (or video / audio / document) with mediaId or mediaUrl. Session media requires an open 24-hour customer window; outside that window use an approved template.
Request parameters
| Field | Required | Type | Description |
|---|---|---|---|
phoneNumberId | Yes | string | WhatsApp phone number ID to send from (must belong to your WABA) |
to | Yes | string | Recipient number with country code. Ten-digit Indian numbers are normalized to 91 prefix. |
type | Yes | string | text | template | image | video | audio | document |
text / message | If type=text | string | Message body. Either field name is accepted. For media types, may be used as caption if caption is omitted. |
templateName | If type=template | string | Approved template name in Meta |
templateLanguage | If type=template | string | Template language code (e.g. en, en_US) |
templateVariables | No | array | object | Body variable values in order (array) or keyed by index |
mediaId | For session media* | string | Meta media ID from Upload Media (preferred) |
mediaUrl | For session media* | string | Public HTTPS link for session media, or template media header URL |
caption | No | string | Caption for image / video / document (max 1024) |
filename | No | string | Filename for document type |
buttonParameters | No | array | Template button components. Each item: type (url, quick_reply, phone_number, otp/copy_code, catalog), index, value |
contextMessageId | No | string | Meta message ID to reply in thread |
* For image / video / audio / document, provide mediaId or mediaUrl.
Send image (session media)
Recommended: upload first, then send with mediaId.
curl -X POST https://chatyug.com/api/external/messages/upload-media \
-H "Authorization: Bearer ck_your_api_key_here" \
-F "mediaFile=@photo.jpg" \
-F "phoneNumberId=100000000000001" \
-F "mediaType=image"
curl -X POST https://chatyug.com/api/external/send-message \
-H "Authorization: Bearer ck_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phoneNumberId": "100000000000001",
"to": "919876543210",
"type": "image",
"mediaId": "900000000000099",
"caption": "Product photo"
}'Send via public HTTPS link
{
"phoneNumberId": "100000000000001",
"to": "919876543210",
"type": "image",
"mediaUrl": "https://example.com/images/product.jpg",
"caption": "Optional caption"
}Document example
{
"phoneNumberId": "100000000000001",
"to": "919876543210",
"type": "document",
"mediaId": "900000000000099",
"filename": "invoice.pdf",
"caption": "Your invoice"
}Response example
{
"success": true,
"message": "Message sent successfully",
"requestId": "req_1720856400000_abc123def",
"data": {
"messageId": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgSQjAwMDAwMDAwMDAwMDAwAA==",
"conversationId": 1001,
"status": "sent",
"to": "919876543210",
"type": "image",
"timestamp": "2026-07-13T07:00:00.000Z"
}
}If the message was delivered to Meta but database save failed, warning may be present and delivery tracking may be limited.
Inbound media
Customer photos are stored under /received_media/.... Use GET /api/external/messages/:messageId/media for a stable ChatYug URL. Do not cache Meta lookaside.fbsbx.com links — they expire in minutes.
Code samples (template)
curl -X POST https://chatyug.com/api/external/send-message \
-H "Authorization: Bearer ck_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phoneNumberId": "100000000000001",
"to": "919876543210",
"type": "template",
"templateName": "order_update",
"templateLanguage": "en",
"templateVariables": ["Rahul", "ORD-90001"]
}'const axios = require('axios');
await axios.post('https://chatyug.com/api/external/send-message', {
phoneNumberId: '100000000000001',
to: '919876543210',
type: 'template',
templateName: 'order_update',
templateLanguage: 'en',
templateVariables: ['Rahul', 'ORD-90001']
}, { headers: { Authorization: 'Bearer ck_your_api_key_here' } });import requests
requests.post('https://chatyug.com/api/external/send-message', json={
'phoneNumberId': '100000000000001',
'to': '919876543210',
'type': 'template',
'templateName': 'order_update',
'templateLanguage': 'en',
'templateVariables': ['Rahul', 'ORD-90001']
}, headers={'Authorization': 'Bearer ck_your_api_key_here'})$client = new GuzzleHttp\Client();
$client->post('https://chatyug.com/api/external/send-message', [
'headers' => ['Authorization' => 'Bearer ck_your_api_key_here'],
'json' => [
'phoneNumberId' => '100000000000001',
'to' => '919876543210',
'type' => 'template',
'templateName' => 'order_update',
'templateLanguage' => 'en',
'templateVariables' => ['Rahul', 'ORD-90001']
]
]);
Related webhook: After send, Meta pushes delivery updates to ChatYug, which forwards
eventType: status to your webhook URL (delivered, read, failed).