Messages

Send approved templates (the only thing that works outside the 24-hour window), reply with text inside it, and check what happened to a message.

Paths are relative to https://api.chatboxai.dev/api, so /v1/messages/template means https://api.chatboxai.dev/api/v1/messages/template. Every request needs an API key, see Authentication.

Send a template

POST/v1/messages/template
Scopemessages:sendIdempotent

Send an approved template. This is the one that works outside the 24-hour window, so it is what an order-confirmation, shipping or delivery integration actually uses.

Request
POST /api/v1/messages/template
X-Api-Key: cbk_live_7mK2pQx9Lw4t....
Idempotency-Key: shopify-order-1234-shipped
Content-Type: application/json

{
  "to": "+919999900000",
  "name": "Asha Menon",
  "template": "order_shipped",
  "language": "en",
  "reference": "shopify:order:4521:shipped",
  "components": [
    {
      "type": "body",
      "parameters": [
        { "type": "text", "text": "Asha" },
        { "type": "text", "text": "#1234" },
        { "type": "text", "text": "Friday" }
      ]
    }
  ]
}
FieldRequiredNotes
toone ofThe customer's phone. Spaces, dashes and parentheses are stripped. Include the country code.
contactIdone ofOur id, if you already have it. Use instead of to.
namenoUsed only if to is somebody we have never seen, to name the new contact.
templateyesThe template name as approved, not its id.
languagenoDefaults to the template's own language.
componentsnoMeta's send-time components, passed through unchanged. Omit it and the template is filled in with the contact's name where it has a single {{1}}.
referencenoYour identifier for this message, up to 128 characters. Stored as sent and handed back on every webhook about it, and on the customer's reply to it. See matching an event to your own records.

Response:

200 OK
{
  "id": "clx9m4p2t0003",
  "waMessageId": "wamid.HBgMOTE5OTk5OTAwMDAwFQIAERgSN0E4...",
  "conversationId": "clx7k1m8n0002",
  "contactId": "clx8h2k9p0001",
  "direction": "OUTBOUND",
  "type": "TEMPLATE",
  "text": "Your order has shipped",
  "mediaUrl": null,
  "status": "SENT",
  "error": null,
  "reference": "shopify:order:4521:shipped",
  "createdAt": "2026-10-17T10:14:02.441Z"
}

status: "SENT" means WhatsApp accepted it. It does not mean it was delivered. Subscribe to message.delivered and message.failed, or poll GET /v1/messages/{id}.

If the contact does not exist, it is created. If they have opted out, you get 422 contact_opted_out and nothing is sent or charged.

Send a text message

POST/v1/messages/text
Scopemessages:sendIdempotent

Send a plain text message. Only works within 24 hours of the customer's last message to the business. Use it to answer someone, not to start a conversation.

Request
POST /api/v1/messages/text
Content-Type: application/json

{
  "to": "+919999900000",
  "text": "It's out for delivery and should reach you by 6pm.",
  "reference": "shopify:order:4521:eta"
}

reference works exactly as it does on a template send, and is optional in the same way. The response has the same shape as above. Outside the window you get:

422 Unprocessable Entity
{
  "error": {
    "code": "session_window_closed",
    "message": "WhatsApp only allows a plain text message within 24 hours of the customer writing to you. Send an approved template instead.",
    "details": { "contactId": "clx8h2k9p0001", "sessionExpiresAt": "2026-10-16T14:22:00.000Z" }
  }
}

Get a message

GET/v1/messages/{id}
Scopemessages:read

What happened to a message. {id} may be either the id we returned or the waMessageId, whichever you stored.

200 OK
{
  "id": "clx9m4p2t0003",
  "waMessageId": "wamid.HBgMOTE5OTk5OTAwMDAwFQIAERgSN0E4...",
  "conversationId": "clx7k1m8n0002",
  "contactId": "clx8h2k9p0001",
  "direction": "OUTBOUND",
  "type": "TEMPLATE",
  "text": "Your order has shipped",
  "mediaUrl": null,
  "status": "FAILED",
  "error": { "code": 131049, "title": "This message was not delivered to maintain healthy ecosystem engagement." },
  "reference": "shopify:order:4521:shipped",
  "createdAt": "2026-10-17T10:14:02.441Z"
}

status is one of QUEUED, SENT, DELIVERED, READ, FAILED. reference is whatever you sent with the message, or null, including for every message sent from the dashboard rather than through this API.

Error 131049 is Meta throttling a marketing template, not a bug in your integration. See marketing delivery is not guaranteed.