Chat Delivery Webhook
Osvi POSTs a chat agent’s reply to the delivery URL configured on the agent whenever the reply can’t be returned inline: for a turn accepted via Send Message (Async), and for any operator-authored message (a Tell, a plain support message, or a takeover reply) sent through Send Support / Control Command. A session’s most recent messages decide where its replies go: if the customer has been messaging over a chat WebSocket connection, replies are delivered as events on that socket instead of to this webhook.
A turn can send more than one envelope: zero or more replies, followed by exactly one final envelope with turn_complete: true. A turn that produced no visible reply (for example, one that was merged into another turn already in progress) still sends that final envelope alone, with content: "", so your integration always sees a definite end to every accepted turn.
This webhook is not signed. If you need to verify a delivery came from Osvi, configure a custom header (e.g. a bearer token) as one of the agent’s delivery headers and check for it on your endpoint.
- A turn accepted through Send Message (Async) — the reply arrives here instead of in the
202response. - Any operator-authored message sent through Send Support / Control Command — a
tell, a plain support message, or a takeover reply.
POST /v1/chat/inbound / /inbound/async).Configuring a delivery URL
Set this under the chat agent’s Settings tab, in the Delivery card:The envelope
Every delivery is aPOST with a JSON body describing one reply, or a turn’s completion:
id, type: "interaction", created_at, interaction_id, tool_type, schema_version, presentation, interaction_status, interaction_revision, and (once answered) selected_option_id/response_payload — see Interactive messages for what those mean.
How a turn ends
A turn can produce more than one reply. They arrive as separate envelopes, in delivery order, and are always followed by exactly one final envelope withturn_complete: true — that’s your signal the turn is fully done and nothing more is coming for it.
A turn that produces no reply at all — most commonly because your message arrived while another turn for the same session was still running and got folded into it — still sends that final envelope on its own, with content: "" and turn_complete: true. Every turn you get accepted for is guaranteed exactly one completion signal, even one with nothing to say.
Delivery, retries, and ordering
- Respond with any 2xx status within 15 seconds to acknowledge a delivery.
- A non-2xx response, a timeout, or a connection error is retried automatically — up to 6 attempts total, spaced a few seconds apart at first and up to about a minute apart later. Design your endpoint to be safe to receive more than once (see
idempotency_keyabove). - If every attempt fails, Osvi stops retrying that delivery — there’s no further automatic redelivery after the 6th attempt.
- Deliveries for a turn are sent in order and are not retried out of order; a retry of an earlier delivery is not sent again once a later one for the same turn has succeeded.
- Deactivating the agent, or removing its delivery URL, stops future delivery attempts — replies already in flight are not guaranteed to arrive after that point.
Body
The chat session this reply belongs to.
"4718a326-417b-4dda-90d0-21fd65a11cb8"
The agent that produced this reply.
"agent_IsZ3Q6Sf_60Eh26XQMGbz-R_og"
Your identifier for the customer, when known.
"+15551112222"
The reply text. Empty when this envelope only carries a turn-completion marker (see turn_complete).
"Sure — I can help with that. What's your order number?"
Always assistant — this webhook only delivers replies, never customer messages.
assistant "assistant"
Who authored the content — the agent itself, or a human operator (a Tell, a plain support message, or a takeover reply). Omitted when not applicable.
ai, operator "ai"
Unix timestamp (seconds) of delivery.
1749034825
Identifies the turn this reply belongs to — present when the reply was produced by a turn (e.g. one accepted via Send Message Async).
"9c3e2f1a4b5d4e6f8a9b0c1d2e3f4a5b"
Zero-based position of this reply among the (possibly several) replies of its turn, when the reply was produced by a turn. Not every reply carries one; rely on delivery order rather than this field to sequence replies.
0
Echoes the idempotency_key from the inbound request that produced this turn, when one was set — use it to correlate this delivery with your original request.
"wh-2f8a1c-attempt-1"
true only on the last envelope of a turn, marking it finished. A turn that produced no visible reply (e.g. one merged into another turn) still sends exactly one envelope with content: "" and turn_complete: true, so your integration always sees a definite end to every accepted turn.
true
Session mode at turn completion. Sent alongside turn_complete.
ai, support "ai"
Whether the agent has escalated the conversation for a human operator. Sent alongside turn_complete.
false
Present only when this reply is an interactive message: the message id.
"3f9c2b1a-8e4d-4c2a-9b1e-2d3f4a5b6c7d"
Present only when this reply is an interactive message.
interaction "interaction"
Present only when this reply is an interactive message.
"2026-06-04T11:40:25.690486Z"
Present only when this reply is an interactive message. See Interactive messages.
"b6a3e6c2-2d61-4a4b-9c9a-5a2d9f6a2b10"
Present only when this reply is an interactive message.
ui_buttons, ui_carousel, ui_date_picker "ui_buttons"
Present only when this reply is an interactive message.
2
Present only when this reply is an interactive message — the content to render. Shape depends on tool_type; see Interactive messages.
Present only when this reply is an interactive message. pending while waiting for an answer, accepted once answered, cancelled if superseded (e.g. the customer sent a plain message instead), expired if it timed out unanswered.
pending, accepted, cancelled, expired "pending"
Present only when this reply is an interactive message.
1
Present only once an interactive message has been answered.
null
Present only once an interactive message has been answered with a structured response.
null
Response
Respond with any 2xx status within 15 seconds to acknowledge receipt. A non-2xx response, a timeout, or a connection error is retried automatically — up to 6 attempts in total, spaced a few seconds to about a minute apart — after which Osvi stops retrying that delivery. Deliveries are not retried if the agent's delivery URL was removed or the agent was deactivated in the meantime.
