API reference
Messages
Send text, media, templates and interactive messages; read status.
Send a message
POST
/messagesscope: messages:sendQueues a message and returns 202 Accepted immediately. Delivery status then arrives via webhooks.
Common fields
| Field | Type | Description |
|---|---|---|
to | string, required | Recipient phone number with country code, digits only or with + (max 20 chars). |
type | string, required | text, image, video, audio, document, template or interactive. |
from | string, optional | A phone_number_id from GET /me. Defaults to your first active number. |
Text
{ "to": "14155550100", "type": "text", "text": { "body": "Your order #1042 has shipped." } }text.body is required, up to 4096 characters.
Image, video, audio, document
{
"to": "14155550100",
"type": "document",
"media": {
"link": "https://example.com/invoice-1042.pdf",
"caption": "Invoice #1042",
"filename": "invoice-1042.pdf"
}
}media.link must be a public https URL. caption (max 1024) and filename (max 200) are optional.
Template
{
"to": "14155550100",
"type": "template",
"template": {
"name": "order_update",
"language": "en_US",
"components": [
{ "type": "body", "parameters": [
{ "type": "text", "text": "Jane" },
{ "type": "text", "text": "#1042" }
] }
]
}
}Only APPROVED templates can be sent — list them with GET /templates. language and components are optional.
Interactive buttons
{
"to": "14155550100",
"type": "interactive",
"interactive": {
"body": "Would you like to reschedule?",
"buttons": [ { "title": "Yes" }, { "title": "No" }, { "title": "Call me" } ]
}
}body up to 1024 characters; 1–3 buttons, titles up to 20 characters.
The 24-hour window. Text, media and interactive messages are only accepted within 24 hours of the customer’s last message. Outside the window the API returns
422 — send an approved template instead.Messages to contacts who opted out, or beyond your plan’s monthly quota, are rejected with 422.
Response
HTTP/1.1 202 Accepted
{ "id": 4812, "status": "queued", "to": "14155550100", "conversation_id": 377 }Get a message
GET
/messages/{id}scope: messages:read{
"id": 4812, "conversation_id": 377, "direction": "outbound", "type": "template",
"body": null, "status": "delivered", "wamid": "wamid.HBgM…", "error": null,
"sent_at": "2026-10-07 10:15:02", "delivered_at": "2026-10-07 10:15:04", "read_at": null,
"created_at": "2026-10-07 10:15:01"
}Statuses: queued → sent → delivered → read, or failed (with a reason in error).
List messages
GET
/messagesscope: messages:read| Query | Description |
|---|---|
status | Filter by status |
direction | inbound or outbound |
to | Filter by contact phone number |
page, per_page | Pagination — per_page 1–100, default 25 |
Newest first. Response: { "data": [ … ], "meta": { "page": 1, "last_page": 8, "total": 187 } }.