API Reference
Send Freeform Message
Send a free-text WhatsApp message within an active 24-hour session
On this page
This endpoint sends a freeform (free-text) WhatsApp message to a recipient. Unlike template messages, freeform messages can contain any text but require an active 24-hour messaging window — meaning the recipient must have sent a message to your WhatsApp sender within the last 24 hours.
Freeform messages can only be sent during an active 24-hour messaging window. If the session has expired, you must send a template message first to re-initiate the conversation. Use the Session Status endpoint to check if a session is active.
This endpoint is rate-limited to 5 requests per second per user.
Request Body
sender_idintegerrequired
The ID of the WhatsApp sender to send from (obtained from the Get Senders endpoint)
recipient_phonestringrequired
The recipient's phone number in international format (e.g., +1234567890)
messagestring
The message content to send (max 4096 characters). Optional when media_url is provided — in that case it is used as the media caption. Audio files are the exception: WhatsApp does not support captions on audio, so the text is ignored when media_url points to an audio file. Either message or media_url is required.
media_urlstring
Optional public URL of a file to send — an image, audio file, video, or document. The file must be reachable at a public URL (WhatsApp fetches it at send time). When set, message is used as the caption for images, videos and documents. Audio files cannot carry a caption — if you send an audio file, any message text is ignored. Either message or media_url is required.
filenamestring
Optional filename shown to the recipient, mainly useful for documents (e.g. invoice.pdf).
Response Fields
successboolean
Whether the message was sent successfully
conversation_idinteger
The ID of the conversation associated with this message
message_idinteger
The ID of the conversation message record
whatsapp_message_idinteger
The ID of the WhatsApp message record
message_sidstring
The Twilio message SID for tracking delivery
session_statusobject
Updated session status after sending the message
Error Responses
402 Insufficient Balance
403 Session Expired
404 Not Found
503 Sender Offline
curl -X POST "https://app.voxlink.ai/api/user/whatsapp/send-freeform" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sender_id": 12,
"recipient_phone": "+1234567890",
"message": "Thank you for your inquiry! Our team will review your request and get back to you within 2 hours."
}'
const response = await fetch(
'https://app.voxlink.ai/api/user/whatsapp/send-freeform',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
sender_id: 12,
recipient_phone: '+1234567890',
message: 'Thank you for your inquiry! Our team will review your request and get back to you within 2 hours.'
})
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.post(
'https://app.voxlink.ai/api/user/whatsapp/send-freeform',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'sender_id': 12,
'recipient_phone': '+1234567890',
'message': 'Thank you for your inquiry! Our team will review your request and get back to you within 2 hours.'
}
)
print(response.json())
curl -X POST "https://app.voxlink.ai/api/user/whatsapp/send-freeform" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sender_id": 12,
"recipient_phone": "+1234567890",
"message": "Here is the menu you asked for!",
"media_url": "https://example.com/files/menu.pdf",
"filename": "menu.pdf"
}'
{
"success": true,
"conversation_id": 1234,
"message_id": 567,
"whatsapp_message_id": 890,
"message_sid": "SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"session_status": {
"is_open": true,
"can_send_freeform": true,
"requires_template": false,
"message": "Session open (23 hr 45 min remaining). Unlimited free-form messages allowed.",
"minutes_remaining": 1425,
"expires_at": "2026-02-25T10:30:00+00:00"
}
}
{
"success": false,
"error": "Insufficient balance. Please top up your account.",
"error_code": "INSUFFICIENT_BALANCE"
}
{
"success": false,
"error": "The 24-hour messaging window is closed. Customer must reply first, or use a template message.",
"error_code": "SESSION_EXPIRED",
"session_status": {
"is_open": false,
"can_send_freeform": false,
"requires_template": true,
"message": "Session expired. Send a template or wait for customer to reply.",
"expired_at": "2026-02-23T10:30:00+00:00"
}
}
{
"success": false,
"error": "Sender not found or does not belong to you",
"error_code": "SENDER_NOT_FOUND"
}
{
"success": false,
"error": "Invalid phone number format. Use E.164 format (e.g., +14155551234).",
"error_code": "INVALID_PHONE"
}
{
"success": false,
"error": "Sender is not online. Current status: Offline",
"error_code": "SENDER_OFFLINE"
}
24-Hour Messaging Window
WhatsApp enforces a 24-hour messaging window policy:
- When a customer sends a message to your WhatsApp Business number, a 24-hour window opens.
- During this window, you can send freeform messages without restrictions.
- After the window expires, you must use a template message to re-initiate the conversation.
- Each new customer message resets the 24-hour timer.
Use the Session Status endpoint to check whether a session is active before attempting to send a freeform message.
Notes
- Maximum message length is 4,096 characters (WhatsApp limit).
- A file (image, audio, video, or document) can be attached with
media_url. It must be hosted at a publicly reachable URL — WhatsApp fetches it at send time. When sending media,messageis optional and is used as the caption. Audio is the exception: WhatsApp does not support captions on audio files, so whenmedia_urlpoints to an audio file themessagetext is not sent. - The sender must be
online. Offline senders return a503error. - Message costs are automatically deducted from your account balance.
- Rate limit: 5 requests per second per user.
Related guides
API Reference
Introduction
Welcome to the VoxLink API
Read guide →API Reference
Authentication
Learn how to authenticate your API requests
Read guide →API Reference
Get current user
Get the authenticated user's profile information
Read guide →API Reference
List assistants
List all assistants for the authenticated user with pagination
Read guide →