> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.v2.rasen.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.v2.rasen.ai/_mcp/server.

# List call history

GET https://api.v2.rasen.ai/v1/calls

Stable descending creation time/ID order. UTC [start,end), maximum 93 days. Includes this workspace's call records; no diagnostic payloads. updated_since selects changes polling; otherwise creation order applies. Cursor binds every filter and workspace. Metadata lookup supports recovery after intent-key expiry; reconcile all matches and do not automatically redial when ambiguous. ID-list filters use repeated query names. Raw supplied ID count across fields is at most 100. Cursor binds normalized filters; filtered lists are not exact batch retrieval. Changes to transcript, extraction, summary or tool outcomes advance updated_at, including after call terminality. Summary states can be filtered. updated_at is computed at read time from the call, its stored results and its tool outcomes; a GET never starts generation. For more than 100 ID values, use POST /calls/search with the same filter names. In updated_since mode start/end bound updated_at, not created_at; the creation-time default range does not apply. updated_since is the inclusive lower bound; if start is also supplied it must equal updated_since. end is an optional exclusive upper bound, capped by the server visibility watermark. The 93-day maximum scan span remains. Pagination holds its original watermark.

Reference: https://docs.v2.rasen.ai/api-reference/calls/list

## Authentication

- `Authorization` header (bearer token, required) — Create and manage workspace-owned keys through the existing app session routes, outside this public API. Creator and manager identities are audit actors only. Key validity follows workspace policy, expiry and explicit revocation, independently of creator membership. Do not include a workspace-selection header.

## Request

### Query parameters

- `limit` (integer, optional, default: 50) — Page size; 50 by default, at most 200.
- `cursor` (string, optional) — Opaque cursor bound to the workspace, every filter, grouping and limit. Send them unchanged with it. Expires after 24 hours.
- `state` (list of string, optional) — Exact canonical state filter. Known values: admitted, active, evidence_pending, complete, incomplete, aborted. Invalid filters are refused, not ignored. Repeat for OR within this field; AND with other fields. These are not ID entries; at most 16 values per field, the same bound as the POST form. An empty array is invalid and refused: SDKs refuse it before sending, and the server refuses an empty or blank value. Omission means no filter.
- `start` (datetime, optional) — Inclusive UTC timestamp. Range must be at most 93 days.
- `end` (datetime, optional) — Exclusive UTC timestamp. Default range is trailing 30 days.
- `updated_since` (datetime, optional) — Changes polling mode. Inclusive lower bound. Orders by updated_at then id ascending; cursor retains a fixed scan upper bound. After the last page use the returned scanned_through as the next updated_since and deduplicate by (id,updated_at). Updates after the bound appear on the next scan. This is current-state reconciliation, not a lossless event log.
- `terminal` (boolean, optional) — Filter terminality.
- `transcript_state` (list of string, optional) — Exact known transcript state; unsupported values refused. Repeat for OR within this field; AND with other fields. These are not ID entries; at most 16 values per field, the same bound as the POST form. An empty array is invalid and refused: SDKs refuse it before sending, and the server refuses an empty or blank value. Omission means no filter.
- `extraction_state` (list of string, optional) — Exact known extraction state; unsupported values refused. Repeat for OR within this field; AND with other fields. These are not ID entries; at most 16 values per field, the same bound as the POST form. An empty array is invalid and refused: SDKs refuse it before sending, and the server refuses an empty or blank value. Omission means no filter.
- `metadata_key` (string, optional) — Use with metadata_value for exact customer correlation. Both fields must be supplied.
- `metadata_value` (list of string, optional) — Exact metadata values for metadata_key (OR). Repeat the name for several values; they count toward the 100 raw filter values. Multiple calls may match one value. An empty array is invalid and refused: SDKs refuse it before sending, and the server refuses an empty or blank value. Omission means no filter.
- `call_id` (list of string, optional) — Repeat the query name for multiple IDs. OR within this field; AND across fields. Maximum 100 raw ID entries total across all ID filters. Blank values are invalid. Unknown/inaccessible IDs produce no rows, not an existence disclosure. An empty array is invalid and refused: SDKs refuse it before sending, and the server refuses an empty or blank value. Omission means no filter.
- `agent_id` (list of string, optional) — Repeat the query name for multiple IDs. OR within this field; AND across fields. Maximum 100 raw ID entries total across all ID filters. Blank values are invalid. Unknown/inaccessible IDs produce no rows, not an existence disclosure. An empty array is invalid and refused: SDKs refuse it before sending, and the server refuses an empty or blank value. Omission means no filter.
- `summary_state` (list of string, optional) — Repeat for OR within state; AND across filters. Unsupported states or blank values are refused. An empty array is invalid and refused: SDKs refuse it before sending, and the server refuses an empty or blank value. Omission means no filter.

## Response

### 200

List call history.

- `items` (list of CallListItem, required)
- `next_cursor` (string, required, nullable) — Opaque continuation cursor. Null means the last page.
- `scanned_through` (datetime, required, nullable)
- `poll_after_seconds` (integer, required)

## Errors

### 400 Bad Request Error

Invalid input or cursor. Correct the request.

- `error` (ErrorResponseError, required) — Only code and message are required. Rasen sends details, request_id and retry on every error, but clients must parse an error that lacks them, so a typed error is never lost to a parsing failure.

### 401 Unauthorized Error

Invalid, expired or revoked API key. Creator departure or membership changes do not invalidate a workspace key.

- `error` (ErrorResponseError, required) — Only code and message are required. Rasen sends details, request_id and retry on every error, but clients must parse an error that lacks them, so a typed error is never lost to a parsing failure.

### 403 Forbidden Error

Operation not allowed by current credential or workspace access.

- `error` (ErrorResponseError, required) — Only code and message are required. Rasen sends details, request_id and retry on every error, but clients must parse an error that lacks them, so a typed error is never lost to a parsing failure.

### 429 Too Many Requests Error

Rate limited. Respect Retry-After and retry the same intent where permitted.

- `error` (ErrorResponseError, required) — Only code and message are required. Rasen sends details, request_id and retry on every error, but clients must parse an error that lacks them, so a typed error is never lost to a parsing failure.

### 500 Internal Server Error

Internal error. The effect may have happened. Retry the same request with the same Idempotency-Key; read the resource before creating a new intent. For an operation that takes an Idempotency-Key, a client retry with the same key is safe: the server replays the stored outcome if the first attempt took effect; if the first attempt had no effect, the retry performs the operation once. Never retry with a new key.

- `error` (ErrorResponseError, required) — Only code and message are required. Rasen sends details, request_id and retry on every error, but clients must parse an error that lacks them, so a typed error is never lost to a parsing failure.

### 503 Service Unavailable Error

Service unavailable. Respect Retry-After where present. For an operation that takes an Idempotency-Key, a client retry with the same key is safe: the server replays the stored outcome if the first attempt took effect; if the first attempt had no effect, the retry performs the operation once. Never retry with a new key.

- `error` (ErrorResponseError, required) — Only code and message are required. Rasen sends details, request_id and retry on every error, but clients must parse an error that lacks them, so a typed error is never lost to a parsing failure.

## Types

### CallListItem

Compact call metadata/readiness; effective variables require GET /calls/\{call\_id}. List IDs first, then read bounded details for relevant calls. No bulk transcript or variable payload expansion.

- `id` (string, required) — Opaque call identifier. Do not parse its contents.
- `agent_id` (string, required) — Opaque agent identifier. Do not parse its contents.
- `published_version_id` (string, required, nullable)
- `state` (string, required) — Canonical call lifecycle value; clients must tolerate new values. Terminality is given separately. Known values: admitted, active, evidence_pending, complete, incomplete, aborted.
- `terminal` (boolean, required)
- `direction` (string, required) — Open response vocabulary. Preserve unknown values; never assume they mean success.
- `created_at` (datetime, required)
- `ended_at` (datetime, required, nullable)
- `end_reason` (string, required, nullable) — Safe registered call-end reason.
- `metadata` (map from string to string, required)
- `transcript_state` (string, required) — Open response vocabulary. Preserve unknown values; never assume they mean success.
- `extraction_state` (string, required) — Open response vocabulary. Preserve unknown values; never assume they mean success.
- `from_number_id` (string, required, nullable) — Number used for this call; null for non-phone calls.
- `updated_at` (datetime, required)
- `poll_after_seconds` (integer, required)
- `summary_state` (string, required) — Open response vocabulary. Preserve unknown values; never assume they mean success.

### ErrorResponseError

Only code and message are required. Rasen sends details, request_id and retry on every error, but clients must parse an error that lacks them, so a typed error is never lost to a parsing failure.

- `code` (string, required) — Stable code. Branch on code (and details.reason for conflict), never on message. Each code has one HTTP status; see components.x-error-catalog.
- `message` (string, required) — Safe description; no provider payload or submitted secrets.
- `details` (map from string to any, optional) — Safe code-specific details. The public fields for each code are listed in components.x-error-catalog. Details never contain a request fingerprint, a hash of a request, secret material or another tenant's data. forbidden may include required_capabilities (a list).
- `request_id` (string, optional) — Same value as the X-Request-Id header. Quote it to support.
- `retry` (string, optional) — Retry class of this code: no (fix the request or state first), yes (retry the same request and the same Idempotency-Key), retry_after (wait for Retry-After, then retry the same request). Open response vocabulary. Preserve unknown values; never assume they mean success.

## Examples

**Response**

```json
{
  "items": [
    {
      "id": "call_01j00000000000000000000000",
      "agent_id": "agent_01j00000000000000000000000",
      "published_version_id": "published_version_01j00000000000000000000000",
      "state": "complete",
      "terminal": true,
      "direction": "inbound",
      "created_at": "2026-09-25T10:00:00Z",
      "ended_at": "2026-09-25T10:05:00Z",
      "end_reason": "hangup_requested",
      "metadata": {},
      "transcript_state": "pending",
      "extraction_state": "not_requested",
      "from_number_id": "from_number_01j00000000000000000000000",
      "updated_at": "2026-09-25T10:06:00Z",
      "poll_after_seconds": 30,
      "summary_state": "not_requested"
    }
  ],
  "next_cursor": "eyJwYWdlIjoyfQ",
  "scanned_through": "2026-09-25T10:10:00Z",
  "poll_after_seconds": 30
}
```

**SDK Code**

```python calls_list_example
import requests

url = "https://api.v2.rasen.ai/v1/calls"

querystring = {"end":"2026-09-25T00:00:00Z","start":"2026-09-01T00:00:00Z"}

headers = {"Authorization": "Bearer <api_key>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript calls_list_example
const url = 'https://api.v2.rasen.ai/v1/calls?end=2026-09-25T00%3A00%3A00Z&start=2026-09-01T00%3A00%3A00Z';
const options = {method: 'GET', headers: {Authorization: 'Bearer <api_key>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```ruby calls_list_example
require 'uri'
require 'net/http'

url = URI("https://api.v2.rasen.ai/v1/calls?end=2026-09-25T00%3A00%3A00Z&start=2026-09-01T00%3A00%3A00Z")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <api_key>'

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

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

HttpResponse<String> response = Unirest.get("https://api.v2.rasen.ai/v1/calls?end=2026-09-25T00%3A00%3A00Z&start=2026-09-01T00%3A00%3A00Z")
  .header("Authorization", "Bearer <api_key>")
  .asString();
```

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

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.v2.rasen.ai/v1/calls?end=2026-09-25T00%3A00%3A00Z&start=2026-09-01T00%3A00%3A00Z', [
  'headers' => [
    'Authorization' => 'Bearer <api_key>',
  ],
]);

echo $response->getBody();
```

```csharp calls_list_example
using RestSharp;

var client = new RestClient("https://api.v2.rasen.ai/v1/calls?end=2026-09-25T00%3A00%3A00Z&start=2026-09-01T00%3A00%3A00Z");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <api_key>");
IRestResponse response = client.Execute(request);
```

```swift calls_list_example
import Foundation

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

let request = NSMutableURLRequest(url: NSURL(string: "https://api.v2.rasen.ai/v1/calls?end=2026-09-25T00%3A00%3A00Z&start=2026-09-01T00%3A00%3A00Z")! 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()
```