curl -X POST "https://app.supported.tech/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.supported.tech/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 requestsresponse = requests.post( 'https://app.supported.tech/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.supported.tech/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": 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"}
WhatsApp
Send Freeform Message
Send a free-text WhatsApp message within an active 24-hour session
POST
/
user
/
whatsapp
/
send-freeform
curl -X POST "https://app.supported.tech/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.supported.tech/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 requestsresponse = requests.post( 'https://app.supported.tech/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.supported.tech/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": 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"}
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.
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.
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.
curl -X POST "https://app.supported.tech/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.supported.tech/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 requestsresponse = requests.post( 'https://app.supported.tech/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.supported.tech/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": 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"}
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.
⌘I
Assistant
Responses are generated using AI and may contain mistakes.