Sending
POST /v1/messages
The body is to plus exactly one content key. The content
key names the type. There is no type field.
Every content key
{ "to": "254712345678", "text": "Hello" }
{ "to": "254712345678", "image": "<url|med_id|data uri>", "caption": "..." }
{ "to": "254712345678", "video": "<...>", "caption": "..." }
{ "to": "254712345678", "audio": "<...>", "voice": true }
{ "to": "254712345678", "document": "<...>", "filename": "Invoice-4417.pdf",
"caption": "Your invoice" }
{ "to": "254712345678", "location": { "lat": -1.29, "lng": 36.82,
"name": "UPEO.AI", "address": "..." } }
{ "to": "254712345678", "contact": { "name": "...", "phone": "..." } }
Optional on any send
from | Pick the sending number by msisdn when you have several. |
|---|---|
instance_id | The same choice, by id. |
reply_to | A message id to quote. |
preview_url | Whether a link in a text message gets a preview. |
mentions | People to @-mention: numbers, or jids from
GET /v1/chats/{jid}/members (a group that uses LIDs needs the @lid
jid). Put @ and the same digits in the text where the name should appear.
Text and captions only. |
mention_all | true for @all in a group. Write
@all in the text. WhatsApp only notifies everybody when the sending number is
an admin. |
If your account has exactly one number, from and instance_id
are optional everywhere.
Waiting for the result
?wait=true blocks up to 15 seconds until the message reaches
sent or failed, then returns the terminal state. Without it you
get 202 and status: queued immediately.
Idempotency
Send an Idempotency-Key header on anything that must not happen twice.
Honoured for 24 hours. The same key with the same body replays the original response;
the same key with a different body is a 409.
curl -X POST https://njiwa.upeo.ai/v1/messages \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: invoice-4417" \
-H "Content-Type: application/json" \
-d '{"to": "254712345678", "document": "https://example.com/invoice-4417.pdf"}'Pacing
Njiwa paces sends per number, by default one every three seconds. Sending as fast as the socket allows is how a number gets banned.
What 202 promises
A 202 means the message is stored and queued. From that point it is
Njiwa's problem, not yours: you do not need to poll it, hold it, or send it again.
| The number is offline | The message waits. It is sent when the number reconnects, not failed for being early. |
|---|---|
| A send fails | Retried up to five times with a widening gap, from a few seconds out to five minutes. |
| Njiwa restarts mid send | The message is put back and sent. Nothing in flight is dropped by a deploy. |
| It truly cannot be sent | It goes to failed with an
error saying why. It is never left sitting at queued
for ever. |
Idempotency-Key.