Agent-readable docs index: /docs/llms.txt. Full docs in one file: /docs/llms-full.txt. Download /docs/docs.zip to grep all markdown files locally.

Send transactional messages through the API

POST /api/v1/messages sends one transactional message and requires messages:write plus an Idempotency-Key of at most 200 characters. Use a new key for every new logical send.

Request fields

  • to: required; an email for email, or international phone for WhatsApp, SMS, and Smart.
  • channel: email, whatsapp, sms, or smart; omitted means smart, including templates.
  • message: plain text, required unless a saved template supplies content.
  • template: workspace template public ID; variables provides its caller-facing values.
  • subject / html / sender: email subject, optional HTML alternative, and optional active sender address. A template can supply the subject; an omitted sender uses the default active sender or available active sender.
  • test: true to validate without sending or charging.
  • purpose: use otp for phone verification messages so the OTP controls apply consistently.
  • first_name, last_name, custom_fields: optional persistent contact profile data.
  • list_id: an owned contact list; otherwise API Contacts is used.
  • session: optional WhatsApp session selection.
  • whatsapp_opt_in / whatsapp_opt_in_source: record genuine WhatsApp permission where applicable.
Template variables and profile fields differ. Per-send codes and variables are not all persisted automatically; store durable profile attributes deliberately.

Example: WhatsApp validation

Set the intended channel explicitly and validate the recipient and setup first. The JSON below is the request body; include both authentication and idempotency headers.
{ "to": "+2348012345678", "channel": "whatsapp", "message": "Hi Ada, order ORD-1042 has shipped.", "first_name": "Ada", "test": true }

Example: email template

Email uses an address destination and a confirmed sender. Supply the real saved template ID and its required variables. A raw email also needs a nonblank message and subject.
{ "to": "[email protected]", "channel": "email", "sender": "[email protected]", "template": "tpl_your_email_template", "variables": {"first_name": "Ada", "order_id": "ORD-1042"}, "test": true }

Successful responses

HTTP 201 Created contains success, actual channel, status, cost, destination, and message_id when present. Template sends can include the template public ID.
Validation returns status: "validated" and zero cost. Live provider acceptance commonly returns sent/accepted status according to the channel. Follow delivery receipts to determine later outcomes.

Handling failures and uncertainty

Read error_code before deciding whether to retry. Fix missing variables, sender readiness, or invalid destinations; honor rate-limit delays. After an ambiguous timeout, retry the exact request with its original idempotency key instead of creating another send.
Next: integrate batch sends, webhooks, and API errors.
Smart uses phone channels. To send email, set channel: "email"; omitting it for an email template still defaults to Smart.