“API: send a WhatsApp message”
POST /api/v1/messages — send text, media or a template to a phone number. The contact and conversation are created for you.
Scope: messages:send
POST /api/v1/messages sends a message to a phone number. You pass an E.164 number (e.g. +14155550123), not an internal ID — Vatli finds or creates the contact and conversation, then sends.
Text
curl -X POST https://app.vatli.co/api/v1/messages \
-H "Authorization: Bearer vatli_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "to": "+14155550123", "type": "text", "text": "Hi 👋" }'
Free-form text only delivers inside the customer’s 24-hour window. To start a conversation, send a template.
Template
{
"to": "+14155550123",
"type": "template",
"template": {
"name": "order_update",
"language": "en_US",
"params": ["A123"]
}
}
params are the body variables in order ({{1}}, {{2}}, …). The template must be approved and the language must match exactly (en_US ≠ en).
Media
{
"to": "+14155550123",
"type": "document",
"media_url": "https://example.com/invoice-1043.pdf",
"filename": "invoice-1043.pdf",
"text": "Your invoice"
}
type can be image, video, document or audio. media_url must be publicly reachable; text becomes the caption.
Reply to a specific message
Add "reply_to_message_id": "<message uuid>" to quote a message. It must be in the same conversation.
Response — 201 Created
{
"data": {
"message_id": "…",
"whatsapp_message_id": "wamid.…",
"conversation_id": "…",
"contact_id": "…",
"contact_created": true
}
}
Delivery happens after the response. Track delivered, read and failed with webhooks (message.delivered, message.read, message.failed) or GET /conversations/{id}/messages.
Errors specific to this endpoint
| Status | code | Meaning |
|---|---|---|
| 400 | whatsapp_not_configured | The workspace has no connected WhatsApp number. |
| 502 | meta_error | Meta rejected the send. The message explains why — see Meta error codes. |
| 500 | template_malformed | The stored template couldn’t be rendered. Re-sync templates. |
Opted-out contacts are refused — Vatli never messages someone who replied STOP. See Opt-outs.