WhatsApp requires an open 24-hour “customer care” window to send free-form text. If the recipient has not messaged your number in the last 24 hours, use
POST /messages/template instead.Endpoint
messages.send.
Headers
| Header | Value |
|---|---|
Authorization | Bearer apitk_... |
Content-Type | application/json |
Accept | application/json |
Path parameters
Your workspace subdomain.
Body parameters
Recipient’s phone number in E.164 format.
Message body. Max 4096 characters.
One of
text, interactive, cta_url. Defaults to text.Optional header (interactive / cta_url messages). Max 60 characters.
Optional footer. Max 60 characters.
Interactive button array. 1–3 items. Each button is
{ id: string (max 256), title: string (max 20) }.For
cta_url messages: the button label. Max 20 characters.For
cta_url messages: the URL the button opens.Optional contact payload. Used when auto-creating or updating the contact backing this message. Any of:
firstname, lastname, email, country, assigned_id, groups.Example request
Interactive reply buttons (1–3)
Send a message with tappable reply buttons. When the user taps a button, theid is sent back as an incoming message to your webhook.
cURL
- Max 3 buttons per message
- Button
titlemax 20 chars - Button
idmax 256 chars (returned verbatim on tap)
CTA URL button (1 URL)
Send a message with a single button that opens a URL in the browser.cURL
- Only 1 URL button per message (Meta restriction)
button_textmax 20 charsbutton_urlmust be a valid HTTPS/HTTP URL
Button type limits: Meta allows only ONE action type per free-form message — either 1–3 reply buttons OR 1 CTA URL button. To mix button types (Reply + URL + Call), you need a pre-approved Meta template via
POST /messages/template.Example response
200 OK
Auto-created contacts
Ifphone_number does not match an existing contact, Xobito auto-creates one. The firstname defaults to the phone number unless you supply contact.firstname. contact_created: true indicates a new contact was created.
Error responses
| Status | When | Example body |
|---|---|---|
401 | Missing / invalid token | {"status":"error","message":"Invalid API token"} |
403 | Missing ability | {"status":"error","message":"Token does not have the required ability: messages.send"} |
422 | Validation | {"status":"error","message":"Validation failed","errors":{"message_body":["The message body may not be greater than 4096 characters."]}} |
429 | Rate limit | {"message":"Too many requests","retry_after":45} |
500 | Send failure | {"status":"error","message":"Failed to send message"} |
Polling delivery status
This endpoint returns the initialstatus (usually sent). To follow delivery progress (delivered, read, failed), poll GET /messages/{messageId}/status with the returned message_id.