POST /v1/conversations/items puts something into a person’s thread from your
own system: a recruiter’s note, a reminder sent as the agent, or an instruction
the agent turns into its next message. It also starts a thread with someone you
have never spoken to, by your number and theirs.
Who you post to
to is either a conversation or a pair of numbers:
number is one of your WhatsApp senders or phone numbers, in E.164. peer is
the person’s number; a national-format one is read against number’s country.
The pair names the person’s contact
phone:<number>:<peer>, the same one their phone calls, WhatsApp calls and
WhatsApp messages share — created if this is the first time.
The item goes into the thread you named, or else the person’s open chat’s
thread, or else their newest thread. With no thread at all, a new one is opened
with status: "inactive": it stays out of the default inbox list until they
reply.
While the person has an open chat, anything but a note must go into that chat’s
thread: their reply lands there, and an instruction elsewhere would have to end
the chat. Naming another conversation is a 409 with code: "chat_open_elsewhere", whose message names the open chat’s conversation. Post
by number and peer and the open chat’s thread is picked for you.
What each contact can receive:
Anything else is a
422 with code: "channel_unsupported".
The request
The answer is
201 with the stored item, the same shape
GET /v1/conversations/{conversation_id}/items returns, with post_type
(template, agent_text, note or instruction), author and
idempotency_key set. A valid request always stores its item: a provider
that refuses the send answers 201 with delivery_status: "failed" and
delivery_error, not an error status.
Notes and instructions
A note is background the agent reads from then on, in that thread and in any later session that loads it — a phone call included:422 no_agent when
there is neither. An API chat must be open (409
chat_ended otherwise).
Both reach the model as <instructions> below the agent’s own prompt, so they do
not disturb the cached prompt. Neither carries a channel. Instructions are
turns: a message from the person during one replaces it (the instruction stays in
the history), and each answered instruction is billed as an
answered message.
An instruction is refused while the person is on a call with your agent
(409 voice_session_live). Notes are accepted, and reach the next session, not
the live call.
Choosing the agent
Send an agent to make it what answers this person; leave it out to continue whatever is running. A post takes the same agent fields as an outbound call, on WhatsApp and Telegram contacts:
“The same agent” means the same
agent_id (or inline definition), version,
override, vars and secrets. userdata is not part of it. A template does not
open a chat on its own, since most are never answered.
A chat started this way does not ask the inbound webhook,
and keeps running if the number’s messages trigger is pointed at another agent.
The number must have its messages trigger on, or the reply would never reach
Talqing (422 messages_off).
WhatsApp’s 24-hour window
WhatsApp allows free-form messages only for 24 hours after the person last messaged or called your number, answered or not. The conversation’sref.whatsapp_window_expires_at says when it closes. Templates may go any time.
Outside the window, agent_text and instruct with on_window_closed: "fail"
are refused with 409 whatsapp_window_closed. With an opener:
delivery_status: "held". Their next message releases it, before the agent
answers them. A tap on the opener’s own button releases it and starts no turn,
since the held message is the answer. One opener is in flight per person at a
time: a second held message waits behind the first’s. A held message that is not
released within 7 days becomes expired; if the opener itself fails, the
messages held behind it fail too.
An instruction’s reply follows the instruction’s on_window_closed, whenever it
is written.
Delivery
An outbound WhatsApp message moves throughdelivery_status:
A send the provider refuses is
failed at once, a rate limit or a provider
outage included. Nothing resends it: the provider may have delivered it before
failing, and a duplicate message is worse than a missing one. Post it again to
retry.
Telegram has no receipts: a message accepted by Telegram is sent. Every move of
an outbound WhatsApp or Telegram message — agent replies and batch templates
included — sends the conversation.item.status
webhook, carrying the idempotency_key you posted with.
Errors
See errors for the envelope.