Sending messages
One endpoint covering the whole Cloud API surface.
POST /api/v1/messagesA send always carries three things: the connection to send from, the recipient, and exactly one content field.
{
"connectionId": "cnx_...",
"to": "+237699001122",
"text": "Hello π"
}The number is in international format. Get connectionId from GET /api/v1/connections. Add
replyTo with the wamid of an inbound message to quote it in your reply.
Content fields
One field at a time
Sending two content fields in the same request does not send two messages: only the first recognised one is used. Make two calls.
Text and media
| Field | Content | Limits |
|---|---|---|
text | A string, or { body, previewUrl } | 4096 characters |
image | JPEG, PNG | 5 MB, caption 1024 characters |
video | MP4, 3GPP (H.264 + AAC) | 16 MB |
audio | AAC, AMR, MP3, M4A, OGG | 16 MB, no caption |
document | PDF, DOC(X), XLS(X), PPT(X), TXT | 100 MB |
sticker | Static or animated WebP | 100 KB / 500 KB |
Location, contacts, reaction
| Field | Content |
|---|---|
location | { latitude, longitude, name, address } |
locationRequest | { body } β shows a "Send location" button |
contacts | An array of contact cards |
reaction | { messageId, emoji } β an empty string removes the reaction |
Interactive messages
{
"connectionId": "cnx_...",
"to": "+237699001122",
"buttons": {
"body": "How can we help?",
"footer": "Genuka",
"buttons": [
{ "id": "order", "title": "My order" },
{ "id": "support", "title": "A problem" }
]
}
}| Field | Description | Limits |
|---|---|---|
buttons | Quick-reply buttons | 3 max, 20-character titles |
list | Sections and rows | 10 sections, 10 rows in total |
cta | A single button carrying a URL | url + displayText |
The user's answer arrives by webhook, carrying the id of the button or row they picked.
Templates
Outside the 24-hour window, only an approved template will be delivered.
{
"connectionId": "cnx_...",
"to": "+237699001122",
"template": {
"name": "order_confirmation",
"language": "en",
"body": ["Awa", "ORD-1042"]
}
}A template send opens a billable Meta conversation on the client's own WABA β Meta bills the client directly. Service messages sent inside the 24-hour window are free.
Create and track templates through /api/v1/templates. A template in PAUSED or REJECTED
status cannot be used: check its status before launching a campaign.
Escape hatch
If a message type is not exposed yet, raw forwards a Cloud API fragment verbatim:
{
"connectionId": "cnx_...",
"to": "+237699001122",
"raw": { "type": "interactive", "interactive": { "type": "flow" } }
}No validation is applied to raw β errors come back from Meta as-is.
Common errors
| Meta code | Meaning | What to do |
|---|---|---|
131047 | More than 24h since the last inbound message | Send a template |
131026 | Recipient unreachable or not on WhatsApp | Do not retry |
131050 | User opted out of marketing | Never send them marketing again |
131049 | Per-user marketing cap reached | Retry later |
132001 | Template missing or not approved in that language | Check name and language |
130429 | Throughput exceeded | Slow down, retry with backoff |