Send a WhatsApp message
Send a WhatsApp message
/api/v1/whatsapp/messagesBefore you start
Connect your business and number in Portal → WhatsApp → Numbers & accounts first. Use an account-owner Production API key. Create templates in the Portal.
Result
Send from a number connected and activated in the Portal. Provide number_id, recipient and text, an approved template or ready media. One request calculates the current fee and queues the message; quote_id is optional for a previously quoted exact payload. max_platform_fee is an optional EUR decimal string limiting only the IllyVoIP fee, not Meta charges or temporary wallet hold rounding.
Meta bills separately. Idempotency-Key is required: retry with the identical key and body; never create a replacement for an unknown result. 202 means queued, not delivered. IllyVoIP reserves its fee before dispatch and charges delivered outbound messages only.
Unknown outcomes retain their hold. Consent, service-window, ownership, account and balance checks still apply.
Charges and safe retries
Inspect uncertain operations before retrying. A queued message is not delivered. IllyVoIP reserves its fee at queue admission and charges only delivered outbound messages; incoming messages are free.
Authentication
Send your account API key in the X-Api-Key header. Keep it on your server; never embed it in browser code.
Request examples
Replace the example values with your own inputs. Examples do not run on this page. Production requests can change your account or incur charges.
cURL
curl -X POST "https://app.illyvoip.com/api/v1/whatsapp/messages" \
-H "X-Api-Key: ${ILLYVOIP_API_KEY:?Set ILLYVOIP_API_KEY}" \
-H "Idempotency-Key: YOUR_UNIQUE_IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d '{
"number_id": "YOUR_NUMBER_ID",
"to": "YOUR_TO",
"type": "text",
"text": "YOUR_MESSAGE_TEXT"
}'Node.js
const response = await fetch("https://app.illyvoip.com/api/v1/whatsapp/messages", {
method: "POST",
headers: {
"X-Api-Key": process.env.ILLYVOIP_API_KEY,
"Idempotency-Key": "YOUR_UNIQUE_IDEMPOTENCY_KEY",
'Content-Type': 'application/json'
},
body: JSON.stringify({
"number_id": "YOUR_NUMBER_ID",
"to": "YOUR_TO",
"type": "text",
"text": "YOUR_MESSAGE_TEXT"
})
});
const data = await response.json();
console.log(response.status, data);PHP
<?php
$ch = curl_init('https://app.illyvoip.com/api/v1/whatsapp/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-Api-Key: ' . getenv('ILLYVOIP_API_KEY'),
'Idempotency-Key: YOUR_UNIQUE_IDEMPOTENCY_KEY',
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => '{
"number_id": "YOUR_NUMBER_ID",
"to": "YOUR_TO",
"type": "text",
"text": "YOUR_MESSAGE_TEXT"
}',
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status . PHP_EOL;
echo $response;Python
import os
import json
import requests
response = requests.request(
"POST",
"https://app.illyvoip.com/api/v1/whatsapp/messages",
headers={
"X-Api-Key": os.environ["ILLYVOIP_API_KEY"],
"Idempotency-Key": "YOUR_UNIQUE_IDEMPOTENCY_KEY",
'Content-Type': 'application/json'
},
json=json.loads("{\n \"number_id\": \"YOUR_NUMBER_ID\",\n \"to\": \"YOUR_TO\",\n \"type\": \"text\",\n \"text\": \"YOUR_MESSAGE_TEXT\"\n}"),
)
print(response.status_code)
print(response.json())Node.js examples run on the server (Node.js 22.17+). Python examples require requests; PHP examples require cURL. Set the environment variables referenced in each example.
Request parameters
Header parameters
Idempotency-KeystringrequiredRequest body
application/json
Body required.
oneOf schema alternatives
number_idintegerrequiredtostringrequiredtypestringrequiredtextstringrequiredquote_idstringoptionalmax_platform_feestringoptionalMaximum IllyVoIP platform fee in EUR. Meta charges are separate.
Additional properties: not allowed.
number_idintegerrequiredtostringrequiredtypestringrequiredtemplate_idintegerrequiredparametersarray<string>requiredView nested fields
Array items
Type: string
{
"maxLength": 4096
}named_parametersobjectoptionalheader_parametersarray<string>optionalView nested fields
Array items
Type: string
{
"maxLength": 4096
}named_header_parametersobjectoptionalquote_idstringoptionalmax_platform_feestringoptionalMaximum IllyVoIP platform fee in EUR. Meta charges are separate.
Additional properties: not allowed.
number_idintegerrequiredtostringrequiredtypestringrequiredmedia_idstringrequiredcaptionstringoptionalquote_idstringoptionalmax_platform_feestringoptionalMaximum IllyVoIP platform fee in EUR. Meta charges are separate.
Additional properties: not allowed.
number_idintegerrequiredtostringrequiredtypestringrequiredmedia_idstringrequiredquote_idstringoptionalmax_platform_feestringoptionalMaximum IllyVoIP platform fee in EUR. Meta charges are separate.
Additional properties: not allowed.
number_idintegerrequiredtostringrequiredtypestringrequiredmedia_idstringrequiredcaptionstringoptionalquote_idstringoptionalmax_platform_feestringoptionalMaximum IllyVoIP platform fee in EUR. Meta charges are separate.
Additional properties: not allowed.
number_idintegerrequiredtostringrequiredtypestringrequiredmedia_idstringrequiredcaptionstringoptionalquote_idstringoptionalmax_platform_feestringoptionalMaximum IllyVoIP platform fee in EUR. Meta charges are separate.
Additional properties: not allowed.
Full schema
{
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"number_id",
"to",
"type",
"text"
],
"properties": {
"number_id": {
"type": "integer",
"minimum": 1
},
"to": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{7,14}$"
},
"type": {
"type": "string",
"enum": [
"text"
]
},
"text": {
"type": "string",
"minLength": 1,
"maxLength": 4096
},
"quote_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"max_platform_fee": {
"type": "string",
"pattern": "^(0|[1-9][0-9]{0,5})(\\.[0-9]{1,8})?$",
"description": "Maximum IllyVoIP platform fee in EUR. Meta charges are separate."
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"number_id",
"to",
"type",
"template_id",
"parameters"
],
"properties": {
"number_id": {
"type": "integer",
"minimum": 1
},
"to": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{7,14}$"
},
"type": {
"type": "string",
"enum": [
"template"
]
},
"template_id": {
"type": "integer",
"minimum": 1
},
"parameters": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"maxLength": 4096
}
},
"named_parameters": {
"type": "object",
"maxProperties": 100,
"additionalProperties": {
"type": "string",
"minLength": 1,
"maxLength": 4096
}
},
"header_parameters": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string",
"maxLength": 4096
}
},
"named_header_parameters": {
"type": "object",
"maxProperties": 100,
"additionalProperties": {
"type": "string",
"minLength": 1,
"maxLength": 4096
}
},
"quote_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"max_platform_fee": {
"type": "string",
"pattern": "^(0|[1-9][0-9]{0,5})(\\.[0-9]{1,8})?$",
"description": "Maximum IllyVoIP platform fee in EUR. Meta charges are separate."
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"number_id",
"to",
"type",
"media_id"
],
"properties": {
"number_id": {
"type": "integer",
"minimum": 1
},
"to": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{7,14}$"
},
"type": {
"type": "string",
"enum": [
"image"
]
},
"media_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"caption": {
"type": "string",
"maxLength": 1024
},
"quote_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"max_platform_fee": {
"type": "string",
"pattern": "^(0|[1-9][0-9]{0,5})(\\.[0-9]{1,8})?$",
"description": "Maximum IllyVoIP platform fee in EUR. Meta charges are separate."
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"number_id",
"to",
"type",
"media_id"
],
"properties": {
"number_id": {
"type": "integer",
"minimum": 1
},
"to": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{7,14}$"
},
"type": {
"type": "string",
"enum": [
"audio"
]
},
"media_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"quote_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"max_platform_fee": {
"type": "string",
"pattern": "^(0|[1-9][0-9]{0,5})(\\.[0-9]{1,8})?$",
"description": "Maximum IllyVoIP platform fee in EUR. Meta charges are separate."
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"number_id",
"to",
"type",
"media_id"
],
"properties": {
"number_id": {
"type": "integer",
"minimum": 1
},
"to": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{7,14}$"
},
"type": {
"type": "string",
"enum": [
"video"
]
},
"media_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"caption": {
"type": "string",
"maxLength": 1024
},
"quote_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"max_platform_fee": {
"type": "string",
"pattern": "^(0|[1-9][0-9]{0,5})(\\.[0-9]{1,8})?$",
"description": "Maximum IllyVoIP platform fee in EUR. Meta charges are separate."
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"number_id",
"to",
"type",
"media_id"
],
"properties": {
"number_id": {
"type": "integer",
"minimum": 1
},
"to": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{7,14}$"
},
"type": {
"type": "string",
"enum": [
"document"
]
},
"media_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"caption": {
"type": "string",
"maxLength": 1024
},
"quote_id": {
"type": "string",
"pattern": "^[a-f0-9]{48}$"
},
"max_platform_fee": {
"type": "string",
"pattern": "^(0|[1-9][0-9]{0,5})(\\.[0-9]{1,8})?$",
"description": "Maximum IllyVoIP platform fee in EUR. Meta charges are separate."
}
}
}
]
}Request behavior
Send from a number connected and activated in the Portal. Provide number_id, recipient and text, an approved template or ready media. One request calculates the current fee and queues the message; quote_id is optional for a previously quoted exact payload. max_platform_fee is an optional EUR decimal string limiting only the IllyVoIP fee, not Meta charges or temporary wallet hold rounding.
Meta bills separately. Idempotency-Key is required: retry with the identical key and body; never create a replacement for an unknown result. 202 means queued, not delivered. IllyVoIP reserves its fee before dispatch and charges delivered outbound messages only.
Unknown outcomes retain their hold. Consent, service-window, ownership, account and balance checks still apply.
Conditions and examples
Production only; no WhatsApp Sandbox is available. Replace placeholders with your own account data. Response examples are abbreviated; use the OpenAPI schemas for the full contract. Meta bills its charges separately.
Response fields
message: Customer-facing explanation of the result.
HTTP responses
Expand a status to inspect its documented response format and examples. Example prices, IDs and timestamps are illustrative values, not quotes or account records.
202 Durably queued or exact replay; body contains success and message (not data). Delivery and settlement remain asynchronous.
application/json
successbooleanrequiredmessageobjectrequiredFull schema
{
"type": "object",
"required": [
"success",
"message"
],
"properties": {
"success": {
"type": "boolean"
},
"message": {
"type": "object"
}
}
}400 Invalid input.
401 Invalid API credential.
403 Account access denied.
409 Operation unavailable or request identity conflict.
503 Temporarily unavailable; a mutation outcome may be unknown. Preserve its request identity.
Production only
This operation is not available in Sandbox. Use an enabled Production account and review its effects before executing.