Sending Carousel Messages
POST /api/external/messages/carousel
Auth: Authorization: Bearer ck_<api_key> (required)
Request parameters
| Field | Required | Type | Description |
|---|---|---|---|
phoneNumberId | Yes | string | WhatsApp phone number ID to send from. Alias: Phone_Number_Id. |
to | Yes | string | Recipient phone with country code |
templateName | Yes | string | Approved carousel template name |
templateId | No | number | Internal template ID. Must match templateName if provided. |
languageCode | No | string | Template language (default en_US) |
bodyParams | No | array | Template body variable values. Each item: { "type": "text", "text": "..." } |
cards | Yes | array | 2–10 card objects (see below) |
cards[] item fields
| Field | Required | Type | Description |
|---|---|---|---|
card_index | Yes | number | Zero-based sequential index (0, 1, …) |
headerMediaId | Yes* | string | Meta media ID for card header. *Omitted for catalog-auto-image cards. |
headerMediaType | No | string | image or video (default image) |
bodyParams | No | array | Per-card body variable values |
buttons | No | array | Up to 2 buttons per card (see below) |
cards[].buttons[] item fields
| Field | Required | Type | Description |
|---|---|---|---|
sub_type | Yes | string | quick_reply, url, or phone_number |
index | Yes | string | Button index matching the approved template |
parameters | No | array | Button parameters. Quick reply: { "type": "payload", "payload": "..." }. URL: { "type": "text", "text": "..." }. |
Response example
{
"success": true,
"messageId": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgSQjAwMDAwMDAwMDAwMDAwAA==",
"data": {
"metaMessageId": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgSQjAwMDAwMDAwMDAwMDAwAA==",
"dbMessageId": 9001,
"conversationId": 1001
}
}Error responses
Literal codes and messages returned by POST /messages/carousel:
| HTTP | code | error / errors |
|---|---|---|
| 403 | TEMPLATE_NOT_APPROVED | Template is not approved. Only APPROVED carousel templates can be sent. |
| 400 | VALIDATION_ERROR | errors array with validation messages |
| 404 | PHONE_NOT_FOUND | Phone number ID not found in this account. |
| 404 | TEMPLATE_NOT_FOUND | Template not found in this account. |
| 502 | META_ERROR | error — Meta API error message |
Code samples
curl -X POST https://chatyug.com/api/external/messages/carousel \
-H "Authorization: Bearer ck_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phoneNumberId": "100000000000001",
"to": "919876543210",
"templateName": "summer_sale_carousel",
"templateId": 501,
"languageCode": "en_US",
"bodyParams": [{ "type": "text", "text": "Rahul" }],
"cards": [
{
"card_index": 0,
"headerMediaId": "media_800000000000001",
"buttons": [
{
"sub_type": "quick_reply",
"index": "0",
"parameters": [{ "type": "payload", "payload": "yes" }]
}
]
},
{
"card_index": 1,
"headerMediaId": "media_800000000000002",
"buttons": [
{
"sub_type": "url",
"index": "0",
"parameters": [{ "type": "text", "text": "https://example.com/sale" }]
}
]
}
]
}'const axios = require('axios');
await axios.post('https://chatyug.com/api/external/messages/carousel', {
phoneNumberId: '100000000000001',
to: '919876543210',
templateName: 'summer_sale_carousel',
templateId: 501,
languageCode: 'en_US',
bodyParams: [{ type: 'text', text: 'Rahul' }],
cards: [
{
card_index: 0,
headerMediaId: 'media_800000000000001',
buttons: [{ sub_type: 'quick_reply', index: '0', parameters: [{ type: 'payload', payload: 'yes' }] }]
},
{
card_index: 1,
headerMediaId: 'media_800000000000002',
buttons: [{ sub_type: 'url', index: '0', parameters: [{ type: 'text', text: 'https://example.com/sale' }] }]
}
]
}, { headers: { Authorization: 'Bearer ck_your_api_key_here' } });import requests
requests.post('https://chatyug.com/api/external/messages/carousel', json={
'phoneNumberId': '100000000000001',
'to': '919876543210',
'templateName': 'summer_sale_carousel',
'templateId': 501,
'languageCode': 'en_US',
'bodyParams': [{'type': 'text', 'text': 'Rahul'}],
'cards': [
{
'card_index': 0,
'headerMediaId': 'media_800000000000001',
'buttons': [{'sub_type': 'quick_reply', 'index': '0', 'parameters': [{'type': 'payload', 'payload': 'yes'}]}]
},
{
'card_index': 1,
'headerMediaId': 'media_800000000000002',
'buttons': [{'sub_type': 'url', 'index': '0', 'parameters': [{'type': 'text', 'text': 'https://example.com/sale'}]}]
}
]
}, headers={'Authorization': 'Bearer ck_your_api_key_here'})$client = new GuzzleHttp\Client();
$client->post('https://chatyug.com/api/external/messages/carousel', [
'headers' => ['Authorization' => 'Bearer ck_your_api_key_here'],
'json' => [
'phoneNumberId' => '100000000000001',
'to' => '919876543210',
'templateName' => 'summer_sale_carousel',
'templateId' => 501,
'languageCode' => 'en_US',
'bodyParams' => [['type' => 'text', 'text' => 'Rahul']],
'cards' => [
[
'card_index' => 0,
'headerMediaId' => 'media_800000000000001',
'buttons' => [['sub_type' => 'quick_reply', 'index' => '0', 'parameters' => [['type' => 'payload', 'payload' => 'yes']]]]
],
[
'card_index' => 1,
'headerMediaId' => 'media_800000000000002',
'buttons' => [['sub_type' => 'url', 'index' => '0', 'parameters' => [['type' => 'text', 'text' => 'https://example.com/sale']]]]
]
]
]
]);
Related webhooks: Delivery updates for each card send are forwarded as
eventType: status. Commerce carousel Buy taps create orders with order_source: carousel_campaign; text inquiries use carousel_inquiry. Retrieve them via GET /orders.