API reference

Send WhatsApp messages from your own CRM, billing or e-commerce system. Authentication, the send endpoint, idempotency, per-send document attachments, status polling and every error code.

The Developer API lets an external system — billing software, a CRM, an e-commerce backend, an internal tool — send an approved WhatsApp template on your number.

Authentication

Generate a key in the dashboard: Settings → API keys → Generate key.

The key is shown once. Store it somewhere safe; we only keep a hash, so a leaked database of ours never yields a usable key. Keys look like:

skai_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Send it either way — whichever your HTTP client makes easier:

Authorization: Bearer skai_your_key_here
X-API-Key: skai_your_key_here

Generate a separate key per integration so one can be revoked without breaking the others. Revoking is immediate.

Send a message

POST /api/v1/messages

Queues an approved template for delivery. Returns immediately with a tracking id — the actual send happens asynchronously off a durable, rate-limited queue, so you do not implement pacing or retries.

Request

{
  "phone": "919812345678",
  "template_name": "invoice_ready",
  "variables": ["Ramesh", "INV-2043", "4,500"],
  "reference": "INV-2043",
  "header_document_url": "https://yourapp.com/invoices/INV-2043.pdf",
  "header_filename": "Invoice-INV-2043.pdf"
}
Field Type Required Notes
phone string Yes Any readable format. A bare 10-digit Indian mobile gets 91 prepended automatically
template_name string Yes Must exist on your account and be APPROVED
variables string[] No Fills {{1}}, {{2}} … in order. Count must match the template exactly
reference string No Your own idempotency key, max 120 chars. See below
header_document_url string No Per-send file for a template with a media header
header_filename string No Display name for the document

Response — 202 Accepted

{ "id": 4417, "status": "pending" }

status is one of pending, sent, failed.

Example

curl -X POST https://your-api-host/api/v1/messages \
  -H "Authorization: Bearer skai_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "9812345678",
    "template_name": "appointment_reminder",
    "variables": ["Ramesh", "14 March", "4:00 PM"],
    "reference": "appt-9931"
  }'

Your exact API host is given to you with your key.

Idempotency

Pass a reference that is unique per real-world event — an invoice number, an appointment id, an order id.

If you call again with the same reference, the API returns the original record instead of sending a second message. This makes retries safe: a network timeout where you never saw the response can be retried without the customer getting two messages.

{ "id": 4417, "status": "sent" }

Without a reference, every call is a new send.

Per-send documents

A template's header format is fixed at approval, but the actual file may differ on every send.

So one approved invoice_ready template with a DOCUMENT header can deliver every customer their own PDF:

{
  "phone": "919812345678",
  "template_name": "invoice_ready",
  "variables": ["Ramesh", "4,500"],
  "header_document_url": "https://yourapp.com/invoices/INV-2043.pdf",
  "header_filename": "Invoice-INV-2043.pdf"
}

The URL must be publicly reachable — Meta fetches it directly. Signed URLs work if they stay valid long enough to be fetched.

Check status

GET /api/v1/messages/{id}
{ "id": 4417, "status": "sent" }

Use this if you want confirmation rather than treating the 202 as fire-and-forget.

Errors

Code Meaning What to do
401 Missing, invalid or revoked API key Check the header and that the key is still active
403 Account inactive or paused Resume it in Settings, or contact us
409 No WhatsApp number connected Finish connecting your number
422 Invalid phone number Must be a valid 10–15 digit number
422 Template not found Create it, then Sync templates after Meta approves
422 Template not approved Wait for APPROVED status
422 Variable count mismatch Supply exactly as many as the template expects
422 No media header on template Remove header_document_url, or use a template that has one
404 Message not found The id does not belong to your account

Validation happens at the door, before queueing — a mismatched payload fails immediately with a clear message rather than becoming a confusing async failure you discover by polling.

Rate limiting and throughput

Sends drain from a queue paced at roughly 12 messages per second, which keeps a burst inside Meta's limits. You can post as fast as you like; the queue absorbs it.

Your real ceiling is Meta's daily business-initiated conversation limit for your number, which rises automatically with consistent good-quality sending.

Things worth knowing

  • The API sends templates only. Free-form messages are restricted by Meta to the 24-hour window and are sent from the inbox.
  • Replies to API-sent messages arrive in your inbox like any other conversation, and the AI agent answers them normally.
  • Delivery status from Meta flows into the same reporting the dashboard uses.

Need a different endpoint?

The API covers template sends because that is what most integrations need. If you need something else — contact sync, conversation export, webhook delivery of inbound messages, triggering a Flow — ask. We add endpoints on request and it is inexpensive custom work.

Need it to work differently?

The platform is the starting point, not the ceiling. Tell us what your process needs and we will build it — at a price we will negotiate.