Sending

Send a message

The headline endpoint. Pick a channel, point at a recipient, write a body, hit POST. Most integrations are five lines of code.

LIVE NOW

SMS (Africa's Talking) and Email (7 providers) are fully live. Push and WhatsApp adapters are next — see the roadmap.

Two paths to send

Either way calls the same backend, lands the same way in your message log, hits the same provider. Pick whichever fits the moment.

PathAuthUse when
POST /v1/messagesAPI keyYour back-end service is sending on behalf of a user
POST /v1/admin/messagesSign-in sessionSomeone on your team is sending from the dashboard

From the API

POST/v1/messages

SMS example

curl
curl -X POST https://api-raven-cloud.autotribes.app/v1/messages \
  -H "X-Raven-Key: rk_live_a3f7b2c1_..." \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "sms",
    "to": "+254722000000",
    "body": "Hi Ada, your order #AC-1042 is on its way."
  }'

Email example

curl
curl -X POST https://api-raven-cloud.autotribes.app/v1/messages \
  -H "X-Raven-Key: rk_live_a3f7b2c1_..." \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "to": "ada@acme.co.ke",
    "from": "orders@mail.acme.co.ke",
    "subject": "Your order #AC-1042 is on its way",
    "bodyHtml": "<p>Hi Ada, your order is on its way. Track it <a href=\"...\" >here</a>.</p>",
    "bodyText": "Hi Ada, your order is on its way."
  }'

Response — 202 Accepted

json
{
  "id": "8ad4f7c2-9e3b-4a1c-bc2f-1d8e3a9b7c4d",
  "status": "queued",
  "channel": "email",
  "to": "ada@acme.co.ke",
  "enqueuedAt": "2026-05-01T10:23:18.114Z"
}

Body parameters

FieldTypeNotes
channelstring · requiredsms · email · push · whatsapp
tostring · requiredE.164 phone (+254...) for SMS, or email address for email
bodystring · required for SMS1–4096 chars. SMS auto-segments at 160.
fromstring · required for emailRFC5322 email address, e.g. orders@mail.acme.co.ke
subjectstring · required for emailEmail subject line
bodyHtmlstring · emailHTML body. Recommended alongside bodyText.
bodyTextstring · emailPlain-text fallback. Always include — some clients and spam filters require it.
externalIdstring · optionalYour own ID — useful for reconciliation

From the dashboard

Go to Compose, pick a channel, type a recipient and a body, hit Send. The same payload is built for you and POSTed to /v1/admin/messages. Useful for one-off ops sends, customer-support replies, or testing a new template before wiring it into your back-end.

What happens after you POST

  1. We persist a row in messages with status queued and return the id immediately.
  2. A background worker picks it up within ~50ms.
  3. The worker resolves your provider credentials, calls the provider (e.g. Africa's Talking).
  4. Status becomes sent with the provider's message id and cost.
  5. Provider webhooks update status to delivered, bounced, or read as the lifecycle progresses.
  6. Every step is logged to delivery_events — visible in your dashboard timeline.

Idempotency

ALWAYS SET ONE

Pass idempotency_keyfor every send. If your service retries a timed-out request, you don't want two SMS landing on the customer's phone. Use your own internal IDs (e.g. order-AC-1042).

Repeat calls with the same idempotency key + same payload return the original response without re-sending. Different payload? You get a 409 telling you the key is already used.