Appearance
Sending messages
All requests need x-api-key: <app key> and a JSON body. Sending returns 409 NOT_READY until the app status is ready.
Text
bash
curl -X POST http://localhost:3000/api/messages \
-H "x-api-key: $APP_KEY" -H "Content-Type: application/json" \
-d '{"to":"15557654321","text":"Hello!","replyTo":"<messageId>"}'replyTo is optional and quotes an earlier message. Text is limited to 65,536 characters.
Media
From a URL:
json
{ "to": "15557654321", "mediaUrl": "https://example.com/invoice.pdf", "caption": "Your invoice" }Or inline as base64:
json
{
"to": "15557654321",
"media": { "data": "<base64>", "mimetype": "application/pdf", "filename": "invoice.pdf" }
}Request bodies can be up to 25 MB. If a proxy rejects large sends, raise its body-size limit.
Check a number first
bash
curl -s http://localhost:3000/api/numbers/15557654321 -H "x-api-key: $APP_KEY"
# {"number":"15557654321","registered":true,"chatId":"15557654321@c.us"}Send results
status: "sent" means WhatsApp accepted the message and returned a messageId. For contacts WhatsApp addresses by @lid, the gateway reads the id from the chat's message list and waits up to SEND_CONFIRM_WAIT_MS (default 5 seconds).
If you get status: "unconfirmed" with messageId: null, no id could be found but the message may still arrive. Do not resend automatically.
Delivery receipts
Outbound messages move through sent, delivered, read (or error). GET /api/messages includes status per message, and each change is sent to your webhook as a message.status event.
Reading the message log
GET /api/messages returns oldest first. Query parameters: limit (up to 200), before (a message id, page back with nextBefore), q (search), direction (in or out), chatId. Download media with GET /api/messages/:messageId/media (?format=json for base64).
The log is pruned after MESSAGE_RETENTION_DAYS (default 7).