Send a WhatsApp text from one of your connected numbers to someone who messaged that number in the last 30 days. To send a photo or document, see Send photos & documents.
https://api.waconnect.ai/v1/messagescurl https://api.waconnect.ai/v1/messages \
-H "Authorization: Bearer wc_live_your_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: booking-381-reminder" \
-d '{"from":"+12125550147","to":"+14155550123","text":"Reminder: your appointment is tomorrow at 3 pm."}'Body
fromstringoptional- Your WhatsApp number that sends it, in international format: +12125550147. It must be connected.
numberIdstring (uuid)optional- Or pick the sending number by its id (from GET /v1/numbers). Send from or numberId, not both. With neither, the number is picked only when your key can use exactly one number; otherwise the request answers 400 NUMBER_REQUIRED.
tostringrequired- The recipient with the country code — for US numbers, +1 then the 10 digits: +14155550123. Spaces, dashes and brackets are fine: +1 (415) 555-0123.
textstringrequired- The message, up to 4,096 characters. Emojis and line breaks are fine. Optional when you send media.
mediaobjectoptional- A photo or document to send, with text as its caption. See [Send photos & documents](/docs/guides/send-media).
Who you can message#
API numbers only reply. You can send to a phone that messaged the same number in the last 30 days; each new message from them restarts the 30 days. Sending to anyone else answers 403 OUTSIDE_REPLY_WINDOW, and nothing is queued or charged.
Sending pace#
Each number sends like a person types: one message every 1 to 3 seconds, with "typing…" shown just before it, and at most 20 messages in any 60 seconds. Messages above that wait their turn and go out in the order you sent them; none are dropped. scheduledFor in the response tells you when the message goes out.
What happens next#
The API answers 202 Accepted straight away, with the message in PENDING status. WaConnect then:
- queues it for its turn and sends the
message.queuedwebhook; - shows "typing…" to the recipient, then sends it through your number;
- sends the
message.sentwebhook and charges $0.005.
{
"id": "01a0f4c2-8b1e-7a0c-9d3f-2e6b5a4c1d00",
"numberId": "01a0f44d-c969-75b1-955d-3841d817f711",
"direction": "OUTBOUND",
"contact": { "phone": "+14155550123", "name": null },
"kind": "TEXT",
"text": "Reminder: your appointment is tomorrow at 3 pm.",
"media": null,
"status": "PENDING",
"error": null,
"sentVia": "api",
"sentAt": "2026-10-01T10:00:00.000Z",
"scheduledFor": "2026-10-01T10:00:01.500Z"
}Follow the delivery#
A message moves through PENDING → SENT → DELIVERED → READ, or ends in FAILED with a reason in error.
- Best: listen for the
message.queued,message.sentandmessage.statuswebhooks. - Messages aren't stored in WaConnect, so the webhooks are the only way to follow a message's status. Save them on your side.
Which number sends it#
Name the sending number with from or numberId. You can leave both out only when your API key can use exactly one number; that number sends it, connected or not. If it's disconnected, you get 409 NUMBER_NOT_CONNECTED, and WaConnect never switches to another number. With two or more numbers, leaving both out answers 400 NUMBER_REQUIRED.
Sending from many numbers with one app works the same way: give the key all of them, and name the number on every request.
Common errors#
Check code, not the status. See all error codes.
| Status | Code | Why |
|---|---|---|
400 | INVALID_PHONE / VALIDATION_FAILED | to isn't in international format, or text is empty or too long. |
400 | NUMBER_REQUIRED | Your key can use several numbers and you sent neither from nor numberId. |
402 | CREDITS_REQUIRED | Out of credits. |
403 | OUTSIDE_REPLY_WINDOW | The recipient hasn't messaged this number in the last 30 days. API numbers only reply. Nothing is sent or charged. |
404 | NUMBER_NOT_FOUND | from or numberId isn't one of your numbers, or your key can't use it. |
409 | NUMBER_NOT_CONNECTED | That number isn't connected right now. |
409 | NO_NUMBER | Your key can't use any number yet. |
422 | NOT_ON_WHATSAPP | The recipient isn't on WhatsApp. Nothing is sent or charged. |
Always send an Idempotency-Key
If a request times out, retry it with the same key — you'll get the original message back instead of a duplicate. See Idempotency.