Conversations API
List, search and read analysed calls with a workspace API key: paging, filters, the summary shape and the full analysis object with faults, latency, slots, sentiment and transcript.
Conversations are analysed calls. With a workspace API key you can list them, search their transcripts and read the complete analysis of any one of them. All endpoints are GET, scoped to the key's workspace, and rate-limited to 600 requests per minute per key.
GET /api/conversations?take=50&status=Completed HTTP/1.1
Host: voicelens.app
X-Api-Key: vlk_9d1e…List conversations
/api/conversationsCursor-paged list of conversations, newest first unless sorted otherwise.
| Query parameter | Default | Meaning |
|---|---|---|
take | 50 | Page size, 1 to 200. |
cursor | Opaque cursor from the previous page's nextCursor. Only valid with the same sort. | |
sort | createdAt | Column to order by: createdAt, title, channel, status, health, faults, slots, line, latency or duration. |
dir | asc or desc. Defaults to asc for title, channel and status, desc otherwise. | |
channelId | Only calls from this channel. | |
agentId | Only calls with exactly this agentId. | |
status | Comma-separated list of PendingUpload, Pending, Transcribing, Analyzing, Completed, Failed, Skipped. | |
q | Free-text filter on title and source name. | |
unreviewed | true to return only completed calls nobody has marked as reviewed. | |
includeTestCalls | false | Include calls flagged as test calls. |
Metric sorts (health through duration) only apply to completed calls: calls still processing, failed or skipped have no metrics and are always returned after the completed ones, whichever direction you ask for. faults orders by severity (danger count, then warning, then info), and line puts calls whose line quality was not measured last as well. Ties are broken by id, so paging through a sorted list visits every call exactly once.
Date ranges and health filters are not available on the list; use the analytics endpoints for aggregates over time, or filter client-side on createdAtUtc and healthScore.
Response
{
"items": [ { "…": "ConversationSummary" } ],
"totalCount": 1284,
"countsByStatus": { "Completed": 1201, "Failed": 3, "Skipped": 80 },
"nextCursor": "eyJj…",
"take": 50
}Conversation summary
| Field | Type | Meaning |
|---|---|---|
id | uuid | Conversation id. |
title, sourceName | string | Title and original file or source name. |
status, processingError | string | Processing status and, when failed, the reason. |
channelId, channelName | The channel the call belongs to. | |
agentId, agentName, agentType | Agent identity from the ingest metadata. | |
createdAtUtc, reviewedAtUtc | ISO 8601 | Receipt time and, if reviewed, when. |
durationSec, turnCount | number | Length and number of transcript turns. |
healthScore | 0 to 100 | See Health score. |
totalFaults, dangerFaultCount, warningFaultCount, infoFaultCount | number | Open fault counts by severity. |
completionRate | 0 to 1 | Share of required slots captured. |
agentLatencyMean | seconds | Mean agent response latency. |
silenceRatio | 0 to 1 | Share of the call with nobody speaking. |
lineQualityScore, snrDb | number | Acoustic line quality (0 to 100) and signal-to-noise ratio. |
modelName | string | Transcription model used. |
isTestCall, testCallRunId | Set for calls placed by the test-call feature. |
Search transcripts
/api/conversations/searchPhrase search across transcript turns, returning matching calls newest first with the turns that matched. Cursor-paged.
| Query parameter | Default | Meaning |
|---|---|---|
q | required | 2 to 200 characters, matched literally and case-insensitively inside a single turn. |
speaker | any | any, agent or customer: restrict matches to one side. |
channelId, agentId | Filters as on the list. | |
from, to | ISO 8601 bounds on the call's receipt time; from inclusive, to exclusive. | |
cursor | Opaque cursor from the previous page's nextCursor; omit for the newest matches. | |
take | 20 | Page size, 1 to 50. |
includeTestCalls | false |
The page carries no grand totals: the server stops looking as soon as the page is full, which is what keeps the first results fast on large workspaces. nextCursor is null on the last page. For the totals, call the endpoint below.
{
"query": "cancel my contract",
"speaker": "customer",
"take": 20,
"nextCursor": "MjAyNi0wOS0x…",
"items": [
{
"conversation": { "…": "ConversationSummary" },
"matchCount": 2,
"turns": [
{ "turnIndex": 14, "speakerLabel": "customer", "start": 182.4, "end": 186.9, "snippet": "…I want to cancel my contract today…", "sentiment": -0.42 }
]
}
]
}/api/conversations/search/totalsHow many calls and turns match a search across every page.
Takes the same q, speaker, channelId, agentId, from, to and includeTestCalls as the search; cursor and take are ignored. This is the one request that has to read every searched call's transcript, so ask for it after the first page rather than before.
{ "query": "cancel my contract", "speaker": "customer", "totalCalls": 37, "totalTurns": 41 }Read one conversation
/api/conversations/{id}The complete analysis. Large; fetch it per call rather than in bulk.
The object is organised in groups. Field names are camelCase.
Identity and metadata
id, workspaceId, channelId, status, processingError, skipReason, processingAttempts, source, sourceName, title, externalCallId, agentId, agentName, agentType, customMetadata (your custom object), language, isTestCall, createdAtUtc, and audio { container, blobName, contentType, sizeBytes, durationSec }.
Transcription metadata
metadata { requestId, duration, channels, modelName, createdUtc, rawConfidence, speakerAttribution } plus agentSpeaker and customerSpeaker (which speaker label was identified as which party). speakerAttribution is multichannel or diarized.
speakerRoleSource says how agentSpeaker was decided: firstSpeaker (the parser's default, whoever spoke first, unverified), modelConfirmed or modelCorrected (the AI read the opening turns and agreed with, or overturned, that guess) or manual (an operator swapped the roles in the dashboard). speakerRoleNote carries the model's one-sentence reason when the source is a model decision, otherwise null. Outbound calls are the usual case for modelCorrected: the customer picks up and says "hello" before the agent introduces itself.
Talk time, latency and confidence
talkTime: seconds and share of the call per party, and silence.latency.agentResponseandlatency.customerResponse:{ mean, median, p95, max, count }over the response gaps;latency.perAgentTurn: the gap before each agent turn. See Latency.confidence { averageWordConfidence, averageSpeakerConfidence, lowConfidenceWordCount, lowConfidenceWords[], lowSpeakerConfidenceCount }.
Capture, coverage and compliance
completionandcoverage: the two rates with their numerators and denominators.slots[]:{ key, label, category, type, required, status, value, valueHistory[], volunteered, corrected, turnIndex }withstatusone ofCaptured,Corrected,Missing,NotApplicable.questions[]:{ key, label, required, asked, turnIndex }.complianceandcompliancePhrases[]: verdict per required or forbidden phrase.resolvedCasePath,resolvedCaseLabel: the case branch the call was graded under.
Faults
{
"code": "MISSED_CORRECTION",
"label": "Missed correction",
"description": "Customer corrected the appointment day; the agent did not acknowledge it.",
"severity": "warning",
"atSec": 143.2,
"endSec": 151.8,
"turnIndices": [11, 12],
"evidence": [
{ "turnIndex": 11, "atSec": 143.2, "text": "No, Thursday, not Tuesday." },
{ "turnIndex": 12, "atSec": 147.0, "text": "Great, so Tuesday at ten." }
],
"id": "…",
"verdict": null
}severity is danger, warning or info; verdict is null, confirmed or falsePositive once a reviewer has acted. Counts by severity and the healthScore sit alongside the array. See Fault codes.
Sentiment
sentiment { customerAverage, agentAverage, trajectory[], … } for English calls; absent otherwise. See Sentiment.
Transcript
turns[]: { index, speaker, speakerLabel, start, end, text, numWords, avgWordConfidence, avgSpeakerConfidence, sentiment }, and gaps[] with the silences between turns.
Line quality
lineQuality { version, score, snrDb, perChannel[], events[], … }. See Transcription quality.
Other
callSummary (generated summary, when enabled), the review state, the rubric template version stamp (evaluationTemplateVersionId), and capability flags canReevaluate, canRetranscribe, canSummarize.
Audio
Audio bytes are not available through API keys. Use a share link with audio enabled, or download from the dashboard.
Errors
401 for a missing or invalid key, 403 with code: "api_key_read_only" for any non-GET method, 404 for an id outside the key's workspace, 429 when the per-key rate limit is exceeded.