Send a call
POST https://ingest.voix.tech/submitA single endpoint accepts every call. It is authenticated with your API key and takes a JSON body describing the call.
Two-phase submission
Most telephony systems become aware of a call at two moments: when it starts and when it ends. The Ingest API is built around this: you can submit the same call twice, and VOIX combines the two submissions into one record.
Phase 1: call started
Send the call’s metadata as soon as the call begins, without a recording. This registers the call so that it appears immediately.
{
"callId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
"from": "+31612345678",
"to": "+31201234567",
"startTime": "2026-06-16T09:05:35.000Z",
"outgoing": false
}Response:
{ "status": "received", "callId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed" }Re-send the stable fields on both phases. Always include from, to,
startTime, and outgoing on the second phase as well, not only the new fields.
VOIX matches the two submissions by callId and takes the latest values, so
re-sending these fields keeps the record correct without depending on what was stored
on the first submission.
Single-request submission
The two-phase flow is a convenience, not a requirement. If your system only becomes
aware of a call once it has ended, send everything in a single request with the
recordingUrl included. VOIX proceeds directly to transcribing.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
callId | UUID | Yes | Your stable identifier for the call. Reused across both phases and for any retry. Acts as the idempotency key. |
recordingUrl | URL | On the finishing phase | A URL from which VOIX can fetch the recording. Its presence is what triggers transcription. |
recordingUrl2 | URL | No | A second recording for channel-separated audio: one file per leg. Send your own line as recordingUrl (channel 0), the other party as recordingUrl2. |
from | string | Yes | The calling number. |
to | string | Yes | The number that was called. |
startTime | ISO 8601 datetime | Yes | When the call started, e.g. 2026-06-16T09:05:35.000Z. |
outgoing | boolean | No | true if your side placed the call, false if it was inbound. If omitted, VOIX infers direction from the conversation. |
duration | integer (seconds) | No | Call length in seconds. Typically sent on the finishing phase. |
teamId | UUID | Only with a workspace-wide key | Which team the call belongs to. Required when your API key is workspace-wide; ignored when it is team-scoped. |
userId | UUID | No | The team member who handled the call. If omitted, VOIX attempts to identify the agent from the transcript. See Attribution. |
The body is strict. Any field not listed above causes the request to be rejected
with 400. Send only these keys.
Multi-channel audio
By default VOIX receives one mixed (mono) recording and separates the speakers itself. If your telephony platform can record each party on its own channel, send it that way: VOIX attributes each speaker by channel, which is exact and needs no acoustic diarization.
There are two ways to send channel-separated audio, and both are autodetected — there is no flag to set:
- One stereo file — a single
recordingUrlwith two distinct channels. VOIX detects that the channels differ and splits them per speaker. (A “stereo” file that is really the same audio on both channels is treated as mono.) - Two files — send
recordingUrlandrecordingUrl2, one recording per leg.
Channel convention: channel 0 — the left channel of a stereo file, or
recordingUrl when you send two files — must be your own line (the agent /
rep). Channel 1 (right, or recordingUrl2) is the other party. VOIX uses this to
label the rep and the customer deterministically, and to build a voiceprint of the
rep. A single mono recording is the default.
{
"callId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
"recordingUrl": "https://recordings.example.com/call-12345-agent.mp3",
"recordingUrl2": "https://recordings.example.com/call-12345-customer.mp3",
"from": "+31612345678",
"to": "+31201234567",
"startTime": "2026-06-16T09:05:35.000Z",
"outgoing": true,
"duration": 184
}The resulting transcript has the same shape as a mono call.
Responses
/submit returns 202 Accepted with one of two bodies, depending on whether the
recording was included:
| When | Body |
|---|---|
No recordingUrl yet (phase 1) | { "status": "received", "callId": "…" } |
recordingUrl present (phase 2) | { "status": "transcribing", "callId": "…", "jobId": "…" } |
From that point, the call is processed automatically. Track its progress through the call lifecycle.
What you cannot set
Transcription behaviour, the spoken language, how many speakers to expect, and timestamps are owned by VOIX and tuned for consistent quality. There are no parameters to override them. This is deliberate: it keeps every call in your account directly comparable, rather than dependent on settings a sender happened to pass. Language, for instance, is detected automatically.
The one thing you can influence is how speakers are separated: sending channel-separated audio lets VOIX attribute speakers by channel instead of acoustically. The output shape is identical either way, so calls stay comparable.