Skip to main content
POST
Place an outbound call

Authorizations

Authorization
string
header
required

Tenant API key (vdx_live_…) as Authorization: Bearer.

Body

application/json
assistantId
string<uuid>
required

The assistant's uuid, shown on its configure page in the console. Names and slugs are not accepted.

toNumber
string
required
Example:

"+919876543210"

fromNumberId
string
required

A phone-number id (num-…) or its E.164 value.

contactRef
string
Maximum string length: 256
variables
object

At most 16 kB serialized.

Callbacks

POST
{$request.body#/webhookUrl}interactionCompleted

Body

application/json

The payload Vodex POSTs to your endpoint — not something this API serves. Documented here because it is the contract configured through PUT /v1/webhook-config.

interaction.completed, not call.completed: one stream for every channel, so a consumer writes one handler and switches on channel rather than integrating a new webhook when SMS or WhatsApp ships.

It is deliberately complete — a consumer that receives this needs no follow-up GET. analysis is an open envelope: summary and sentiment land there as additive keys, so a handler written today keeps parsing tomorrow's payloads.

Headers

The timestamp is inside the signed string, not merely alongside it: signing the body alone leaves a captured delivery replayable forever, because nothing in what was signed says when it was sent. Reject anything more than 300 seconds off in either direction. During a rotation both secrets sign, as repeated v1= values, so consumers can move without a coordinated deploy.

Retries

8 attempts at 10s, 30s, 2m, 10m, 30m, 2h, 6h, each with full jitter (a random point in [0, delay], so a consumer coming back from an outage is not hit by every queued delivery at the same instant). 408, 429, 5xx and transport failures retry; every other 4xx does not — repeating a request the consumer called wrong just burns the budget a real outage needs. A delivery that exhausts its attempts is the dead letter — status: failed with no nextAttemptAt — and stays visible at GET /v1/webhook-deliveries.

type
enum<string>
Available options:
interaction.completed
id
string

Idempotency key — stable across retries.

tenantId
string<uuid>
channel
enum<string>
Available options:
voice-ai,
sms
contactRef
string | null

Echoed from the dial request, never interpreted.

rawAddress
string | null

The counterparty address, for when no contactRef was passed.

direction
string
from
string | null
to
string | null
assistantId
string | null
engine
string | null
startedAt
string<date-time> | null
endedAt
string<date-time> | null
outcome
object

Orthogonal facts, never a prose string — a consumer should never have to sniff a string for what happened.

transcript
object[]

Turn-level, with offsets in seconds from the first traced event.

analysis
object

Open envelope — additive keys only.

quality
object
cost
object
artifacts
object

References, never bytes — audio is resolved through the authed API when a user presses play, so it never leaves its region unbidden.

variables
object

Exactly what the agent knew, frozen at call time — the assistant's config may have changed since.

Response

Retried — a timeout is transient.

Response

Dialing.

callId
string
Example:

"call-…"

room
string
to
string
from
string
cell
string
Example:

"us-central1"