> 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 <token>"}

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 <token>'}};

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 <token>")

	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 <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> 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 <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->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 <token>',
  ],
]);

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 <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]

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()
```