Send Endpoint
POST /devices/{device_id}/messages- Direct integration header:
Authorization: Bearer <app_token> - Internal Onebrick engineer flow may use
device_id-only only from trusted internal callers that pass the WA whitelist policy; external callers still needAuthorization: Bearer <app_token>. Content-Type: application/json- Device must be
connected - The runtime will try to resolve the destination into the best WhatsApp identity form available before sending, including LID resolution when WhatsApp returns one for the target contact.
Payload Contract
- Base:
to,type(defaults totextif omitted) - Text:
text - Media source: exactly one of
urlordata_base64 - Media metadata:
mime_type,caption,file_name,ptt - Contact:
contact_name,vcard - Location:
latitude,longitude,address - Interactive beta:
buttons[],footer,poll_question,poll_options[],poll_multi
Recipient Identity
- Accepted recipients include raw phone numbers, phone JIDs such as
6281234567890@s.whatsapp.net, LID JIDs such as150199452311775@lid, and group JIDs such as120363...@g.us. - Callers should pass the stable recipient they have and avoid rewriting identifiers outside the gateway. The gateway warms WhatsApp identity mappings, then lets
whatsmeowchoose the valid phone/LID send identity for the active session. - If WhatsApp shows
Waiting for this message, relink the sending device if needed and retry after the device isconnected.
Attachment Type Requirements
| Type | Required | Optional |
|---|---|---|
image | to, type=image, media source, mime_type | caption |
video | to, type=video, media source, mime_type | caption |
audio | to, type=audio, media source, mime_type | ptt |
document | to, type=document, media source, mime_type | file_name, caption |
sticker | to, type=sticker, media source, mime_type | - |
Payload Blueprints
Text
{
"to": "6281234567890",
"type": "text",
"text": "Hello from wa.onebrick.io"
}
Image
{
"to": "6281234567890",
"type": "image",
"mime_type": "image/jpeg",
"caption": "Payment slip",
"url": "https://example.com/slip.jpg"
}
Document (base64)
{
"to": "6281234567890",
"type": "document",
"mime_type": "application/pdf",
"file_name": "statement.pdf",
"data_base64": "<base64-pdf>"
}
Contact
{
"to": "6281234567890",
"type": "contact",
"contact_name": "John Doe",
"vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nTEL;TYPE=CELL:+6281234567890\nEND:VCARD"
}
Direct cURL Examples
Text
curl -X POST "https://wa.onebrick.io/devices/DEVICE_ID/messages" \
-H "Authorization: Bearer APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "6281234567890",
"type": "text",
"text": "Hello, this is an integration test."
}'
Forwarded text
curl -X POST "https://wa.onebrick.io/devices/DEVICE_ID/messages" \
-H "Authorization: Bearer APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "6281234567890",
"type": "text",
"text": "Forwarded operational update",
"forwarded": true,
"wa_forwarded": true,
"forwarding_score": 1
}'
Forwarded sends set WhatsApp ContextInfo.isForwarded and forwardingScore metadata. WhatsApp client rendering is authoritative for whether the forwarded label is shown.
Image by URL
curl -X POST "https://wa.onebrick.io/devices/DEVICE_ID/messages" \
-H "Authorization: Bearer APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "6281234567890",
"type": "image",
"mime_type": "image/jpeg",
"caption": "Latest invoice",
"url": "https://example.com/invoice.jpg"
}'
Validation, Size Limits, and Guardrails
- Media URLs must use
http/httpsand pass host safety checks. - MIME type can be restricted by server allowlist.
- Large media can be rejected by size limits.
- Interactive and poll message types require feature flag enablement.
- A synchronous API success means WhatsApp accepted the send request, not that the recipient client has already decrypted or displayed the message.
- Track delivery with webhook
receiptevents instead of assuming synchronous send success means final delivery.