Server
Webhooks
Receive each conversation on your server as it happens.
A flow with a webhook URL posts JSON to it while each session runs and once when it ends.
Before you begin
You need:
- A public HTTPS endpoint on your server that accepts POST requests.
Set the webhook URL
Open the flow's Webhook tab in the dashboard and enter your URL. To set it from your server instead, update the flow:
await voxio.flows.update(flowKey, { webhookUrl: "https://example.com/voxio" });Receive the events
Accept the POST, answer straight away, and do slow work afterwards. This Express handler saves the transcript when a session finishes:
app.post("/voxio", express.json({ limit: "2mb" }), (req, res) => { const { status, session_id } = req.body;
if (status === "finished") { const history = req.body["session-data"]?.state?.conversation_history ?? []; saveTranscript(session_id, history); }
res.sendStatus(200);});Use session_id to tie each webhook to the browser session or call that produced it.
Payload
Every post has this shape:
{ "status": "finished", "session_id": "8b1f…", "session-data": { "state": { "conversation_history": [ { "role": "user", "content": "Hi" }, { "role": "assistant", "content": "Hello! How can I help?" } ] } }, "responses": [ { "node": "reply", "out": { "speak": "…", "hangup": false } } ]}responses holds what each workflow step produced on that turn. Every key your workflow outputs arrives there, not only speak, so you can send structured data such as a score, a booking or a lead straight to your server.
Statuses
status | Sent |
|---|---|
started | When the session begins. |
running | After each turn, with that turn’s responses. |
finished | Once, at the end, with the full conversation history. |
Next steps
- Sessions and usage: read a session again later.
- Flows: make the workflow output the data you need.