VoxLink.ai

API Reference

Send Freeform Message

Send a free-text WhatsApp message within an active 24-hour session

Updated 27 July 2026

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

is_openboolean

  Whether the 24-hour messaging window is currently open

can_send_freeformboolean

  Whether freeform messages can be sent right now

requires_templateboolean

  Whether a template message is required

messagestring

  Human-readable description of the session state

minutes_remaininginteger

  Minutes remaining in the 24-hour window

expires_atstring

  ISO 8601 timestamp when the session expires

Error Responses

402 Insufficient Balance

successboolean

false

errorstring

Insufficient balance. Please top up your account.

error_codestring

INSUFFICIENT_BALANCE

403 Session Expired

successboolean

false

errorstring

Message indicating the 24-hour messaging window has expired

error_codestring

SESSION_EXPIRED

session_statusobject

  Current session status with `is_open`, `can_send_freeform`, `requires_template`, and `message` fields

404 Not Found

successboolean

false

errorstring

Sender not found or does not belong to you

error_codestring

SENDER_NOT_FOUND

503 Sender Offline

successboolean

false

errorstring

Message indicating the sender is currently offline

error_codestring

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:

  1. When a customer sends a message to your WhatsApp Business number, a 24-hour window opens.
  2. During this window, you can send freeform messages without restrictions.
  3. After the window expires, you must use a template message to re-initiate the conversation.
  4. 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, message is optional and is used as the caption. Audio is the exception: WhatsApp does not support captions on audio files, so when media_url points to an audio file the message text is not sent.
  • The sender must be online. Offline senders return a 503 error.
  • Message costs are automatically deducted from your account balance.
  • Rate limit: 5 requests per second per user.

Related guides