Submitting a call
POST /calls, field by field.
POST /calls accepts a call for processing and returns immediately. Transcription and analysis
happen asynchronously; the result reaches you as a call.completed webhook.
Audio reaches Call Lens through an upload: request one, send the bytes, and present the ticket here.
{
"mode": "upload",
"upload_ticket": "eyJpdiI6…",
"started_at": "2026-08-05T09:14:00Z",
"provider": "zoom",
"provider_call_id": "CA123",
"idempotency_key": "CA123"
}Required fields
| Field | Notes |
|---|---|
mode | Always upload. |
upload_ticket | The ticket from POST /uploads, verbatim. |
started_at | When the call started. |
provider_call_id (max 255 characters) and idempotency_key (max 255 characters) are also
required if your key has webhooks enabled — see
correlation identifiers.
Optional fields
| Field | Notes |
|---|---|
ended_at | Must not be before started_at. |
duration_ms | Minimum 1. Call Lens measures duration itself and prefers its own observation. |
provider | The system the call came from. Max 64 characters. |
identity_key | Your identifier for the agent, used to resolve them to an employee. Max 255 characters. |
employee_id | The Call Lens employee, if you already know it. |
channel_layout | mono_mixed, dual_agent_customer, or multi. dual_agent_customer asks us to attribute speech by channel, which only some speech-to-text providers can do — if yours cannot, the call is refused with a 422 naming the provider rather than accepted and left unprocessed. Submit without this field, or as mono_mixed, to be transcribed with speaker diarization instead. |
direction | inbound, outbound, or unknown. |
counterparty_e164 | The other party's number. Max 32 characters. |
priority | live or backfill. Use backfill for historical imports so they yield to live traffic. |
provider_metadata | Any JSON object. Stored on the call as submitted. Not returned to you anywhere today — not in this response, not on call.completed. |
Responses
{ "success": true, "message": "Call accepted.", "data": { "id": "gQ7bYx", "status": "queued" } }201 on a new call, 200 on a replay. See idempotency.
The id is an opaque string. Call Lens never exposes internal numeric identifiers.
status is queued when the call is on its way through the pipeline, or identity_unresolved
when Call Lens could not match identity_key to an employee. The second is not a failure and the
audio is not discarded — the call waits in a queue an administrator can resolve, and enters the
pipeline once it is attributed.
Refusals specific to the upload are listed under uploading audio.
Modes that no longer exist
Earlier versions of this API documented mode: "pull", which took a source_url, and
mode: "push", which took an audio_key. Both now return 422.
Neither could produce a transcribable call. Nothing ever fetched a source_url — the URL was
validated and discarded, so the call was created with no audio and failed as soon as the pipeline
reached it, having already consumed part of your ingestion allowance. push required write access
to Call Lens storage, which is not something an API key has ever granted.
If you built against either, switch to uploading audio. Nothing that worked before has stopped working.