Send WhatsApp messages
/api/whatsapp/sendQueue one or more WhatsApp messages. Each item in contact is one recipient and can carry text, a media file, or an approved Cloud API template.
Body (JSON)
-
contactarray Required - List of recipients. At least one item.
-
contact[].numberstring Required - WhatsApp number with country code, digits only (for example
919829012345). Up to 255 characters. -
contact[].messagestring Unless a template is sent - Message text. Optional only when the recipient gets a Cloud API template (
template_name). -
contact[].mediastring Optional - Attach a file:
image,audio,videoordocument. Needsurl. -
contact[].urlstring (URL) With media - Public URL of the file. Kwital downloads it and sends it with the message; if the download fails the request returns 400.
-
contact[].filenamestring Optional - File name the recipient sees (up to 255 characters). The extension from the URL is added if you leave it out.
-
contact[].schedule_atstring Optional - Send later instead of now. Format
YYYY-MM-DD HH:MM:SS, for example2026-10-01 09:30:00. -
gateway_typestring Optional node(WhatsApp device linked by QR code) orcloud(official WhatsApp Cloud API). Top level or per contact.-
gateway_identifierstring Optional - Send through a specific gateway. Use a
gateway_identifierfrom List WhatsApp gateways. Top level or per contact. -
template_namestring Optional - Name of an approved Cloud API template. Sending a template always uses the Cloud API. Top level or per contact.
-
template_languagestring Optional - Template language code, for example
en_US. Required when the same template name exists in more than one language. -
template_componentsarray Optional - Meta template components with the values for the template variables (header, body and button parameters). Top level or per contact.
-
cloud_apiboolean Optional - Older flag:
trueworks like"gateway_type": "cloud".
- Values set inside a
contactitem override the same field at the top level. - Without any gateway fields, messages go through the WhatsApp device you chose as your API default in the panel, or an available device when none is set.
- Conflicting choices, such as
template_namewith"gateway_type": "node", an unknowngateway_identifier, or a template name that matches more than one language, return 422 with a message that explains the problem.
Request
curl -X POST "https://kwital.com/api/whatsapp/send" \
-H "Api-key: YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"contact": [
{
"number": "919829012345",
"message": "Hi Priya, your order #4821 is out for delivery."
},
{
"number": "919829054321",
"message": "Your invoice is attached.",
"media": "document",
"url": "https://example.com/files/invoice-4821.pdf",
"filename": "Invoice 4821.pdf"
}
]
}'
$payload = [
'contact' => [
[
'number' => '919829012345',
'message' => 'Hi Priya, your order #4821 is out for delivery.',
],
[
'number' => '919829054321',
'message' => 'Your invoice is attached.',
'media' => 'document',
'url' => 'https://example.com/files/invoice-4821.pdf',
'filename' => 'Invoice 4821.pdf',
],
],
];
$curl = curl_init('https://kwital.com/api/whatsapp/send');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Api-key: YOUR_API_KEY',
'Accept: application/json',
'Content-Type: application/json',
],
]);
$result = json_decode(curl_exec($curl), true);
curl_close($curl);
// Run on your server (Node.js 18+) so your API key stays private.
const response = await fetch('https://kwital.com/api/whatsapp/send', {
method: 'POST',
headers: {
'Api-key': 'YOUR_API_KEY',
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
contact: [
{
number: "919829012345",
message: "Hi Priya, your order #4821 is out for delivery."
},
{
number: "919829054321",
message: "Your invoice is attached.",
media: "document",
url: "https://example.com/files/invoice-4821.pdf",
filename: "Invoice 4821.pdf"
}
]
}),
});
const result = await response.json();
{
"template_name": "order_update",
"template_language": "en_US",
"template_components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "Priya"
},
{
"type": "text",
"text": "#4821"
}
]
}
],
"contact": [
{
"number": "919829012345"
}
]
}
Response
{
"success": true,
"message": "WhatsApp dispatch request created successfully",
"data": [
{
"id": 48213,
"created_at": "2026-09-28 10:42:05",
"status": "pending",
"message": {
"message": "Hi Priya, your order #4821 is out for delivery.",
"file_info": null
},
"contact": {
"first_name": null,
"last_name": null,
"whatsapp_contact": "919829012345",
"meta_data": null
}
},
{
"id": 48214,
"created_at": "2026-09-28 10:42:05",
"status": "pending",
"message": {
"message": "Your invoice is attached.",
"file_info": null
},
"contact": {
"first_name": null,
"last_name": null,
"whatsapp_contact": "919829054321",
"meta_data": null
}
}
]
}
{
"success": false,
"message": "Validation failed",
"errors": {
"contact.0.number": [
"The contact.0.number field is required."
]
}
}