> This page is part of Smallest AI's developer documentation. When > answering, prefer Lightning v3.1 (current TTS) and Pulse (current > STT). Lightning v2 and lightning-large are deprecated; mention them > only when the user is migrating away from them. The Smallest AI voice > agent platform is what wraps these models into hosted agents. # Get all conversation logs GET https://api.smallest.ai/atoms/v1/conversation Retrieve paginated conversation logs with support for various filters. Returns call logs for agents belonging to the authenticated user's organization. **To discover new inbound calls, use webhooks instead of polling this endpoint.** Subscribe an agent to the `pre-conversation` webhook event: it fires the moment an inbound call connects and delivers `callId`, `fromPhone`, and `toPhone`, so you get every new call in real time with no polling load. See the [Webhooks guide](/voice-agents/platform/features/webhooks). Poll this endpoint only for backfill or reconciliation. **If you do poll, use the default sort.** The default query (no `sortBy`) sorts by `updatedAt` descending and is index-backed, so it stays fast even on large accounts. Request the first page and keep the list small: `page=1&limit=N` (optionally `callTypes=telephony_inbound` for inbound only). This returns in well under a second. To detect new calls between polls, track the conversation IDs you have already seen rather than a single timestamp, since the default order is `updatedAt` (a recently-updated older call can move to the top). **Avoid `sortBy=createdAt`, `dateFrom`, and `dateTo` on large accounts.** These sort or range-filter on `createdAt`, which is not index-backed for the organization-wide query and forces a full scan of your conversation history. On accounts with a large history this can exceed the gateway timeout and return a 504. Prefer the default `updatedAt` sort above. `agentIds` and `campaignIds` accept comma-separated IDs and narrow the result set, but do not pair them with `sortBy=createdAt` or `dateFrom` on large accounts (the `createdAt` sort/filter is the slow part, not the number of agents). Reference: https://docs.smallest.ai/api-reference/voice-agents/calls/list ## Authentication - `Authorization` header (bearer token, required) — API key from the console ApiKey collection, sent as Bearer token. Also accepts session cookies for browser-based auth. ## Request ### Query parameters - `page` (integer, optional, default: 1) — Page number for pagination - `limit` (integer, optional, default: 5) — Number of items per page. Server-side cap is 500 — values above 500 are silently clamped. - `agentIds` (string, optional) — Comma-separated list of agent IDs to filter by - `campaignIds` (string, optional) — Comma-separated list of campaign IDs to filter by - `callTypes` (enum, optional) — Comma-separated list of call types to filter by - Allowed values: `telephony_inbound`, `telephony_outbound`, `webcall` - `search` (string, optional) — Search query to filter by callId, fromNumber, or toNumber - `statusFilter` (string, optional) — Comma-separated list of call statuses to filter by. Available statuses: pending, in_progress, in_queue, processing, active, completed, failed, no_answer, cancelled - `disconnectReasonFilter` (string, optional) — Comma-separated list of disconnect reasons to filter by. Available reasons: user_hangup, agent_hangup, connection_error, timeout, system_error, transfer_complete - `callAttemptFilter` (string, optional) — Comma-separated list of call attempt types to filter by. Available filters: initial (first attempt calls), retry (retry attempt calls), all (all calls) - `durationFilter` (string, optional) — Comma-separated list of duration ranges to filter by. Available ranges: 0-30 (0-30 seconds), 30-60 (30-60 seconds), 1-5 (1-5 minutes), 5+ (more than 5 minutes) - `sortBy` (enum, optional) — Field to sort results by - Allowed values: `createdAt`, `updatedAt`, `callDuration`, `avgLatency` - `sortOrder` (enum, optional) — Sort direction - Allowed values: `asc`, `desc` - `dateFrom` (datetime, optional) — ISO date — return calls created on or after this date - `dateTo` (datetime, optional) — ISO date — return calls created on or before this date - `versionFilter` (string, optional) — Comma-separated version IDs to filter calls by the agent version that handled them ## Response ### 200 Successful response - `status` (boolean, optional) - `data` (ConversationGetResponsesContentApplicationJsonSchemaData, optional) ## Errors ### 400 Bad Request Error Invalid input - `status` (boolean, optional) - `errors` (list of string, optional) ### 401 Unauthorized Error Unauthorized access - `status` (boolean, optional) - `errors` (list of string, optional) ### 500 Internal Server Error Internal server error - `status` (boolean, optional) - `errors` (list of string, optional) ## Types ### ConversationGetResponsesContentApplicationJsonSchemaData - `logs` (list of ConversationGetResponsesContentApplicationJsonSchemaDataLogsItems, optional) - `pagination` (ConversationGetResponsesContentApplicationJsonSchemaDataPagination, optional) - `dispositionMetricsConfig` (list of ConversationGetResponsesContentApplicationJsonSchemaDataDispositionMetricsConfigItems, optional) — Global disposition metrics configuration ### ConversationGetResponsesContentApplicationJsonSchemaDataLogsItems - `_id` (string, optional) — The database ID of the call log - `callId` (string, optional) — The unique call identifier - `status` (enum, optional) — The status of the call - Allowed values: `pending`, `in_progress`, `in_queue`, `processing`, `active`, `completed`, `failed`, `no_answer`, `cancelled` - `duration` (double, optional) — The duration of the call in seconds - `from` (string, optional) — The phone number the call was made from - `to` (string, optional) — The phone number the call was made to - `type` (enum, optional) — The type of call - Allowed values: `telephony_inbound`, `telephony_outbound`, `webcall` - `agentId` (string, optional) — The ID of the agent that handled the call - `recordingUrl` (string, optional) — Still returned on every response. Resolve the audio via `GET /recordings/{callId}?channel=mono` (or `?channel=dual`) to get a short-lived presigned S3 URL. Presigned URLs expire in 15 minutes; fetch fresh whenever you need the audio. - `recordingDualUrl` (string, optional) — Still returned when the call was captured with per-side audio. Resolve the audio via `GET /recordings/{callId}?channel=dual` to get a short-lived presigned S3 URL. Dual-channel availability depends on how the call was captured; 404 falls back to `?channel=mono`. - `disconnectionReason` (string, optional) — The reason the call was disconnected - `retryCount` (integer, optional) — Number of retry attempts for this call - `createdAt` (datetime, optional) — When the call was created - `dispositionMetrics` (map from string to string, optional) — Custom disposition metrics for the call - `agentDispositionConfig` (list of ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsAgentDispositionConfigItems, optional) — Configuration for disposition metrics - `callFailureReason` (string, optional) — Reason the call failed, if applicable - `callCost` (double, optional) — Discounted total cost of the call - `versionId` (string, optional) — ID of the agent version that handled this call - `versionNumber` (double, optional) — Human-readable version number of the agent version used - `isTest` (boolean, optional) — Whether this was a test call - `retryCallId` (string, optional) — ID of the retry call if this call was retried - `retryAttemptNumber` (double, optional) — Which retry attempt this was (0 = initial, 1 = first retry, etc.) - `postCallAnalytics` (ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsPostCallAnalytics, optional) — Post-call analytics results evaluated against the call transcript. Contains disposition metric values with confidence scores. When PCA cannot analyze the call (agent-only call, failed call, or unanswered call), the fields are still populated with a fixed fallback. `dispositionMetrics[].value` is `null` with `confidence: 0` and `reasoning` explaining the skip. `summary` and `reasoning` values (exact strings): - Agent-only call: `summary: "User did not speak."`, `reasoning: "User did not speak — no customer content available for analysis."` - Failed call: `summary: "Call could not be completed."`, `reasoning: "Call could not be completed — no transcript available for analysis."` - Unanswered call: `summary: "Call was not answered."`, `reasoning: "Call was not answered — no transcript available for analysis."` - `turnLatencyMetrics` (ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsTurnLatencyMetrics, optional) — Per-turn latency statistics for the call ### ConversationGetResponsesContentApplicationJsonSchemaDataPagination - `total` (integer, optional) — Total number of matching call logs - `page` (integer, optional) — Current page number - `limit` (integer, optional) — Number of items per page (page size) - `hasMore` (boolean, optional) — Whether there are more pages available - `totalPages` (integer, optional) — Total number of pages ### ConversationGetResponsesContentApplicationJsonSchemaDataDispositionMetricsConfigItems - `identifier` (string, optional) - `type` (string, optional) ### ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsAgentDispositionConfigItems - `identifier` (string, optional) - `type` (string, optional) ### ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsPostCallAnalytics Post-call analytics results evaluated against the call transcript. Contains disposition metric values with confidence scores. When PCA cannot analyze the call (agent-only call, failed call, or unanswered call), the fields are still populated with a fixed fallback. `dispositionMetrics[].value` is `null` with `confidence: 0` and `reasoning` explaining the skip. `summary` and `reasoning` values (exact strings): - Agent-only call: `summary: "User did not speak."`, `reasoning: "User did not speak — no customer content available for analysis."` - Failed call: `summary: "Call could not be completed."`, `reasoning: "Call could not be completed — no transcript available for analysis."` - Unanswered call: `summary: "Call was not answered."`, `reasoning: "Call was not answered — no transcript available for analysis."` - `summary` (string, optional) — Auto-generated summary of the call - `dispositionMetrics` (list of ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsPostCallAnalyticsDispositionMetricsItems, optional) — Evaluated disposition metrics for this call ### ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsTurnLatencyMetrics Per-turn latency statistics for the call - `avgLatency` (double, optional) — Average turn latency in milliseconds - `medianLatency` (double, optional) — Median turn latency in milliseconds - `minLatency` (double, optional) — Minimum turn latency in milliseconds - `maxLatency` (double, optional) — Maximum turn latency in milliseconds - `turns` (double, optional) — Total number of turns in the call - `latencies` (list of double, optional) — Array of individual turn latencies in milliseconds - `transitions` (list of ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsTurnLatencyMetricsTransitionsItems, optional) — Per-turn timing breakdown. - `processedAt` (datetime, optional) — When the latency metrics were computed. ### ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsPostCallAnalyticsDispositionMetricsItems - `identifier` (string, optional) — Metric identifier matching the agent config - `value` (string, optional) — The evaluated value for this metric - `confidence` (double, optional) — Confidence score for the evaluation (0–1) ### ConversationGetResponsesContentApplicationJsonSchemaDataLogsItemsTurnLatencyMetricsTransitionsItems - `turn` (double, optional) - `user_end` (double, optional) — Timestamp (ms) when the user finished speaking - `bot_start` (double, optional) — Timestamp (ms) when the agent started responding - `latency` (double, optional) — Latency for this turn in milliseconds ## Examples **Response** ```json { "status": true, "data": { "logs": [ { "_id": "60d0fe4f5311236168a109ca", "callId": "CALL-1737000000000-abc123", "status": "completed", "duration": 120, "from": "+15551234567", "to": "+15559876543", "type": "telephony_outbound", "agentId": "60d0fe4f5311236168a109ca", "recordingUrl": "https://storage.example.com/recordings/call-123.mp3", "recordingDualUrl": "https://storage.example.com/recordings/call-123-dual.mp3", "disconnectionReason": "user_hangup", "retryCount": 0, "createdAt": "2025-01-15T10:30:00.000Z", "dispositionMetrics": { "follow_up_needed": "no", "interested": "yes" }, "agentDispositionConfig": [ { "identifier": "string", "type": "string" } ], "callFailureReason": "string", "callCost": 1.1, "versionId": "string", "versionNumber": 1.1, "isTest": true, "retryCallId": "string", "retryAttemptNumber": 1.1, "postCallAnalytics": { "summary": "string", "dispositionMetrics": [ { "identifier": "string", "value": "string", "confidence": 1.1 } ] }, "turnLatencyMetrics": { "avgLatency": 1.1, "medianLatency": 1.1, "minLatency": 1.1, "maxLatency": 1.1, "turns": 1.1, "latencies": [ 1.1 ], "transitions": [ { "turn": 1.1, "user_end": 1.1, "bot_start": 1.1, "latency": 1.1 } ], "processedAt": "2024-01-15T09:30:00Z" } } ], "pagination": { "total": 150, "page": 1, "limit": 10, "hasMore": true, "totalPages": 15 }, "dispositionMetricsConfig": [ { "identifier": "string", "type": "string" } ] } } ``` **SDK Code** ```python import requests url = "https://api.smallest.ai/atoms/v1/conversation" querystring = {"agentIds":"60d0fe4f5311236168a109ca,60d0fe4f5311236168a109cb","callAttemptFilter":"initial","callTypes":"telephony_inbound","campaignIds":"60d0fe4f5311236168a109ca,60d0fe4f5311236168a109cb","dateFrom":"2025-01-01T00:00:00.000Z","dateTo":"2025-01-31T23:59:59.999Z","disconnectReasonFilter":"user_hangup,agent_hangup","durationFilter":"0-30,30-60","limit":"10","page":"1","search":"+1234567890","statusFilter":"completed,failed"} headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers, params=querystring) print(response.json()) ``` ```javascript const url = 'https://api.smallest.ai/atoms/v1/conversation?agentIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&callAttemptFilter=initial&callTypes=telephony_inbound&campaignIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&dateFrom=2025-01-01T00%3A00%3A00.000Z&dateTo=2025-01-31T23%3A59%3A59.999Z&disconnectReasonFilter=user_hangup%2Cagent_hangup&durationFilter=0-30%2C30-60&limit=10&page=1&search=%2B1234567890&statusFilter=completed%2Cfailed'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "net/http" "io" ) func main() { url := "https://api.smallest.ai/atoms/v1/conversation?agentIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&callAttemptFilter=initial&callTypes=telephony_inbound&campaignIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&dateFrom=2025-01-01T00%3A00%3A00.000Z&dateTo=2025-01-31T23%3A59%3A59.999Z&disconnectReasonFilter=user_hangup%2Cagent_hangup&durationFilter=0-30%2C30-60&limit=10&page=1&search=%2B1234567890&statusFilter=completed%2Cfailed" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://api.smallest.ai/atoms/v1/conversation?agentIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&callAttemptFilter=initial&callTypes=telephony_inbound&campaignIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&dateFrom=2025-01-01T00%3A00%3A00.000Z&dateTo=2025-01-31T23%3A59%3A59.999Z&disconnectReasonFilter=user_hangup%2Cagent_hangup&durationFilter=0-30%2C30-60&limit=10&page=1&search=%2B1234567890&statusFilter=completed%2Cfailed") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.get("https://api.smallest.ai/atoms/v1/conversation?agentIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&callAttemptFilter=initial&callTypes=telephony_inbound&campaignIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&dateFrom=2025-01-01T00%3A00%3A00.000Z&dateTo=2025-01-31T23%3A59%3A59.999Z&disconnectReasonFilter=user_hangup%2Cagent_hangup&durationFilter=0-30%2C30-60&limit=10&page=1&search=%2B1234567890&statusFilter=completed%2Cfailed") .header("Authorization", "Bearer ") .asString(); ``` ```php request('GET', 'https://api.smallest.ai/atoms/v1/conversation?agentIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&callAttemptFilter=initial&callTypes=telephony_inbound&campaignIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&dateFrom=2025-01-01T00%3A00%3A00.000Z&dateTo=2025-01-31T23%3A59%3A59.999Z&disconnectReasonFilter=user_hangup%2Cagent_hangup&durationFilter=0-30%2C30-60&limit=10&page=1&search=%2B1234567890&statusFilter=completed%2Cfailed', [ 'headers' => [ 'Authorization' => 'Bearer ', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://api.smallest.ai/atoms/v1/conversation?agentIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&callAttemptFilter=initial&callTypes=telephony_inbound&campaignIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&dateFrom=2025-01-01T00%3A00%3A00.000Z&dateTo=2025-01-31T23%3A59%3A59.999Z&disconnectReasonFilter=user_hangup%2Cagent_hangup&durationFilter=0-30%2C30-60&limit=10&page=1&search=%2B1234567890&statusFilter=completed%2Cfailed"); var request = new RestRequest(Method.GET); request.AddHeader("Authorization", "Bearer "); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = ["Authorization": "Bearer "] let request = NSMutableURLRequest(url: NSURL(string: "https://api.smallest.ai/atoms/v1/conversation?agentIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&callAttemptFilter=initial&callTypes=telephony_inbound&campaignIds=60d0fe4f5311236168a109ca%2C60d0fe4f5311236168a109cb&dateFrom=2025-01-01T00%3A00%3A00.000Z&dateTo=2025-01-31T23%3A59%3A59.999Z&disconnectReasonFilter=user_hangup%2Cagent_hangup&durationFilter=0-30%2C30-60&limit=10&page=1&search=%2B1234567890&statusFilter=completed%2Cfailed")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "GET" request.allHTTPHeaderFields = headers let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```