POST /v1/actions/send-text-message
Send a free-form text message to a contact during the 24-hour customer service window.
Sends a free-form text message. Only valid inside the 24-hour customer service window — i.e. the contact has sent you a message in the last 24 hours.
If the window is closed, Meta rejects the message with code 131047 (Re-engagement message). Use send-template-message to re-engage.
POST /api/v1/actions/send-text-message
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
phone |
string | yes | International format with + |
message |
string | yes | Up to 4096 characters. Supports WhatsApp markup (*bold*, _italic_, ~strike~, `code`). |
curl -X POST https://www.qyvo.io/api/v1/actions/send-text-message \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"phone": "+14155550123",
"message": "Yes, we ship to Canada — flat rate $14 CAD."
}'
fetch('https://www.qyvo.io/api/v1/actions/send-text-message', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.QYVO_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone: '+14155550123',
message: 'Yes, we ship to Canada — flat rate $14 CAD.',
}),
});
Http::withToken(env('QYVO_TOKEN'))
->post('https://www.qyvo.io/api/v1/actions/send-text-message', [
'phone' => '+14155550123',
'message' => 'Yes, we ship to Canada — flat rate $14 CAD.',
])->json();
httpx.post(
'https://www.qyvo.io/api/v1/actions/send-text-message',
headers={'Authorization': f"Bearer {os.environ['QYVO_TOKEN']}"},
json={'phone': '+14155550123', 'message': 'Yes, we ship to Canada — flat rate $14 CAD.'},
).raise_for_status()
Response — 200 OK
{
"id": "01J1Z...",
"status": "sent",
"whatsapp_message_id": "wamid.HBgL...",
"contact_id": "01J1Y..."
}
Errors
| Status | Cause |
|---|---|
422 |
Message rejected by Meta — most often 131047 Re-engagement message (window closed). Switch to a template. |
422 |
No WhatsApp account configured — onboard a number first |
422 |
Validation error (phone empty, message > 4096 chars) |
Why the window matters
Meta's policy distinguishes:
- Free-form text — only allowed when the contact messaged you in the last 24h. Free of charge.
- Templates — pre-approved by Meta, can be sent any time. Charged per category (utility, marketing, authentication).
If you're unsure whether the window is open, look at the contact's last_message_at (returned by get-contact). If it's older than 24h, send a template.
