These routes need
messages:read and messages:write. They are deliberately
not covered by assistants:write — a key issued to edit a prompt should not
thereby be able to message a merchant’s customers.Reading
limit is 1–100, default 50. A cursor naming nothing in this conversation is a
400, not an empty page — silently returning the first page would make a
paging client loop forever.
The message shape
Sending
string
default:"text"
text, template, image, video, audio, document, interactive,
location or reaction.string
A
channel.message_id from this thread. WhatsApp draws it as a quoted reply,
which is how an answer to a question asked four messages ago stops reading like
a non-sequitur.
Prefer
link over media_id wherever a public URL exists: Meta fetches and
caches by URL, so one catalogue photo sent to a thousand customers is fetched
once instead of uploaded once and served a thousand times.
201 returns the stored message and the conversation. It is recorded as
role: "human" and fires message.sent like any other outbound message.
Two failures to handle
422 outside_customer_service_window
422 outside_customer_service_window
The 24-hour window has closed and this is not a template.Checked before Meta is called, so you get a named condition and a remedy
rather than an unmapped provider error. Read
window.expires_at off the
conversation and show a countdown instead of discovering the limit by failing.502 channel_rejected
502 channel_rejected
Meta refused the message. Their words are in the body. Common causes: a template
that is not approved yet, a number that has been blocked by the recipient, or a
media URL Meta could not fetch.
Taking over from the assistant
{"on": false} to give it back.
Handover is a judgement somebody made, so only somebody releases it. The one
exception is credit exhaustion: a conversation paused because the merchant ran
out of credits resumes on its own when they top up, provided no human has
replied in the meantime.
The merchant’s own staff can do this from their phone. Replying from the
WhatsApp Business App takes over automatically, and
/human, /ai and
/clear pause, release and wipe a thread. Every one of those reaches you as
handoff.requested — so your inbox stays correct even when nobody used your UI.Asking the assistant to answer
message.sent.
Useful for a “draft a reply” button, or to re-run a turn that failed on a
provider outage.
Refused with 409 human_control while a human holds the conversation,
unless you pass force. Without that, your own takeover would be silently
undone by your own next call.
What a conversation looks like
whatsapp_number is the number this thread is happening on. Replies go out from
it automatically — answering from a merchant’s other number would arrive, to the
customer, as a message from a stranger.
