Skip to main content

Webhook Payloads

This page documents the structure of webhook payloads sent by Vocobase when events occur.

Headers

Every webhook request includes these headers:

Event: inbound.route

This event is sent when a partner-configured pre-answer policy is available for a Vobiz or Plivo inbound call.

Payload structure

Headers

Inbound route webhooks for this feature use feature-specific headers:

Response contract

Partners return JSON with an action value:
  • ANSWER_WITH_AI
  • SELECT_AGENT
  • TRANSFER
  • REJECT
When action is TRANSFER, to_number must be E.164. When action is SELECT_AGENT, agent_id must be set. Vocobase records each resolved route decision for partner observability. Query GET /api/v2/inbound-route-decisions to inspect action, source, webhook status, webhook latency, failure reason, transfer target, and created session or phone-call IDs.

Event: call.status.updated

Sent whenever Vocobase learns that a telephony call moved to a new meaningful call status. This event is for real-time orchestration: live dashboards, partner-owned dialer queues, and concurrency release. call.status.updated is sent for phone calls only. Browser WebRTC sessions do not have a carrier call leg and therefore do not emit this event.

Payload structure

Field reference

Call status values

Vocobase normalizes provider-specific call states into one vocabulary:

Provider normalization

Partners should branch on data.status, not on provider-specific values. Vocobase stores the raw provider value for debugging.

External queue orchestration

If you run your own dialer, use call.status.updated to manage slots:
Do not wait for session.completed to release a dialer slot. session.completed is the final rich result after transcript, recording, billing, and extraction processing.

Event: session.completed

Sent when a Vocobase session has reached final post-call processing. For telephony calls, this happens after the call leg ends and the bot/session pipeline has persisted transcript, recording metadata, billing, variables, and extraction results.

Payload structure

Field reference

Data object fields

Transcript entry format

Each entry in the transcript array has:
recording_url is a presigned URL valid for 7 days from the moment the webhook fires. Download and persist the recording on your side if you need long-term retention. If the URL expires before you can download it, call GET /calls/{call_id}/recording-url to mint a fresh one with another 7-day window.

Final call status on session.completed

call.status in session.completed reflects the final known carrier state. For real-time intermediate statuses, use call.status.updated.

Call disposition values

Transferred calls

When an agent transfers a live call to a human:
  1. The bot speaks the configured announcement (transfer_message).
  2. Vocobase transfers the caller to transfer_target.
  3. The session.completed webhook includes transfer metadata.
The session.completed webhook fires once the bot leg ends, not when the caller eventually hangs up with the human. This means:
  • duration_seconds reflects only the bot leg (caller-on-with-bot time).
  • recording_url, when present, is the bot-leg recording. The human side is not recorded.
  • call.transferred is true; call.transferred_at is the redirect moment; call.transfer_target is the destination E.164.
Use call.transferred as the cheap discriminator if your downstream automation needs to distinguish a transferred call from a normal hangup.

Polling GET /calls/{id} vs webhook

Both the webhook and GET /api/v2/calls/{id} return the same data shape, so a partner that can’t accept inbound webhooks (or wants to reconcile dropped deliveries) can poll the GET endpoint instead. A call can appear completed before all transcript, recording, and extraction fields are ready. The processing_complete boolean tells you when the response is final:
In practice the session.completed webhook will reach you before polling kicks in — polling is the fallback for partners that can’t accept inbound webhooks, or for reconciliation after a delivery failure.
For sessions created before this field shipped, pipeline_completed_at will be null permanently. Treat null + status: completed on an older row as “final” — those rows pre-date the signal.

Post-call extraction

When the agent has a Custom Analysis config defined, the platform runs an LLM extraction over the transcript after every completed call and ships the result inline in the same session.completed webhook — no second webhook to handle. Configure extraction via the dashboard’s “Variables & Analytics” tab on the agent editor or via PUT /api/v2/agent/:id with extraction_config.

Extraction object structure

Extraction failures never block webhook delivery. The unified payload always ships with extraction.status indicating outcome — partners that need extraction values can branch on status === 'success', partners that just need transcript + recording can ignore the field.

Replay extraction against a past session

If you edit extraction_config and want to backfill an existing session, call POST /api/v2/calls/{call_id}/extract with { "dry_run": false }. Optional dry_run: true returns the result without persisting. The replay uses the agent’s current config (not the config at original-call time).

Pre-call variables

The variables field on every webhook echoes the per-call values that were substituted into the agent’s prompt and greeting. Configure variable names via the dashboard “Variables & Analytics” tab or PUT /api/v2/agent/:id with variables: ["callee_name", "mobile_number"]. Supply per-call values via POST /api/v2/calls/start body field variables: { callee_name: "Sajal" }. Missing values render as empty strings — the platform never errors on missing variables.

Next steps

Webhook Setup

Configure webhook endpoints and verify signatures.

Error Handling

Understand retry behavior and failure handling.