POST a body and a chat id to a connected bridge - plus how to address a person or a group, and how to make a retry safe.
One POST with two fields: who, and what. chat is the recipient, body is the text.
The response is the message id WhatsApp assigned. Hold on to it: delivery and read receipts arrive later on your webhook keyed by that same id, and it is what you quote if you need us to trace a send.
curl -X POST https://wabridges.com/api/instances/user-123/proxy/send/text \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chat": "15550001234",
"body": "hello"
}'
{
"message_id": "ACE41E988162AB19A4A7BB7A9E663693",
"timestamp": 1777180605
}
A plain international number without punctuation is enough for a one-to-one chat - 15550001234. It is expanded to the full WhatsApp address for you.
Groups have no phone number, so they can only be addressed by their full id, which ends in @g.us. You get that id from the chat_id of any message the group sends you, which is the practical reason to store chat_id on every inbound event rather than just the sender's phone.
{"chat": "15550001234", "body": "hello"}
{"chat": "15550001234@s.whatsapp.net", "body": "hello"}
{"chat": "120363000000000001@g.us", "body": "hi team"}
A timed-out send is genuinely ambiguous - the request may have reached WhatsApp before the connection died. Send an Idempotency-Key and it stops being ambiguous.
The first use performs the send and stores the response for 24 hours. A repeat of the same key replays that stored response, marked X-Idempotency-Replayed: true, without sending anything. A duplicate that arrives while the first is still in flight gets 409 idempotency_conflict. Only successful responses consume a key, so a failed send can be retried with the same one.
Use one key per logical action - an order id, a UUID you generate before the first attempt - and reuse it for every retry of that action.
curl -X POST https://wabridges.com/api/instances/user-123/proxy/send/text \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Idempotency-Key: order-4417-confirmation" \
-H "Content-Type: application/json" \
-d '{"chat": "15550001234", "body": "Your order shipped"}'
Errors come back as {"error": "...", "code": "..."}. Branch on code - it is stable and machine-readable, where the message is prose that may be reworded.
503 - the session is not connected. Re-pair, or wait out the Retry-After. See check it is connected.400 - a missing or malformed field, usually a chat that is not a number or a full id.502 - WhatsApp itself rejected or failed the request.429 - you are over 120 requests per minute. The Retry-After header says how long to wait.The full list, and how to make a retry safe, is on errors and retries.
Every response carries an X-Request-Id. If a send goes wrong in a way this page does not explain, that id lets us find the exact request instead of guessing.
The same shape sends everything else: /send/media for images, audio, documents and voice notes, /send/reaction to react to a message id, /send/typing to show the typing indicator before a slow reply. Fields and payloads for each are in the API reference.
Something here not matching what you see? Write to us - a person answers.