All send endpoints return the standard envelope and are async-friendly: HTTP
200 (status: "sent") means the provider accepted immediately; HTTP 202 (status: "pending") means it was queued. Treat both as success and rely on delivery webhooks for the final state. Correlate using data.message_id.Choosing a message type
| You want to… | Use | Needs an open window? |
|---|---|---|
| Reply within an active customer-care thread | send-text | Yes |
| Start a conversation or message outside the window | send-template | No (opens/refreshes it) |
| Send an invoice, photo, or video | send-media | Yes |
| Offer quick-reply buttons or a list | send-interactive | Yes |
| Acknowledge a message the customer sent you | mark-read | n/a |
Text, media, and interactive (window-gated)
These three require an open 24-hour window by default. If you’re not sure the window is open, send a template first (see below) or expectWINDOW_CLOSED (HTTP 422). You may pass check_window: false to skip the check, but only when you are certain the window is open.
- Text
- Media
- Interactive
body is 1-4096 characters. sender_id is optional - omit it to use the workspace’s first active sender.Templates (not window-gated)
Templates are the only way to message someone outside the 24-hour window, so they’re how you start a conversation. A successful template send opens or refreshes the window, after which freeform messages become deliverable.sender_id is required here and must own the named, approved template. Provide every required variable - missing keys cause TEMPLATE_PARAM_COUNT_MISMATCH. See Templates for how to discover a template’s params.
Handling a closed window
A robust pattern: try the freeform send, and if you getWINDOW_CLOSED, fall back to a template.
Marking inbound messages as read
When a customer messages you, send a read receipt so they see the blue ticks. Only inbound messages belonging to a sender in your workspace can be marked read. This endpoint always responds synchronously with HTTP 200.INVALID_MESSAGE (422); a message outside your workspace returns FORBIDDEN (403).
Tips
- Digits-only E.164 recipients (e.g.
255712345678). A leading+is stripped automatically. - Respect the rate limit (60 req/min per key by default). On
429, honor theRetry-Afterheader and back off. - Don’t treat 202 as failure. The absence of
provider_message_idjust means the send was queued. - Correlate via
data.message_idso each delivery webhook attaches to the right message in your system.
Next: Senders & conversations | Templates | Delivery events