> ## Documentation Index
> Fetch the complete documentation index at: https://docs.telzino.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List Agent Change History

> See who changed an agent's settings, when, from where, and what changed

Use this endpoint to read an agent's change history: every recorded settings change, newest first, with who made it, when, where it came from, and each field's old and new value. It is the same record the Change History tab shows in the Portal and in Connect.

Each entry has a permanent `id`. Pass it to [Revert Agent to a Version](/api-reference/agents/revert) to put the agent back to how it was at that point.

## Path Parameters

<ParamField path="agentId" type="string" required>
  The unique identifier of the agent (UUID format)
</ParamField>

## Query Parameters

<ParamField query="page" type="integer" default="1">
  Page number for pagination (1-indexed). Page 1 holds the newest changes. A value that is not a whole number of 1 or more falls back to `1`, and a page past the end returns an empty list. Invalid values never return `400`.
</ParamField>

<ParamField query="limit" type="integer" default="50">
  Number of versions per page (max 100). A value that is not a whole number of 1 or more falls back to `50`, and a value over `100` is capped at `100`.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.telzino.com/v1/agents/123e4567-e89b-12d3-a456-426614174000/history?page=1&limit=50" \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const agentId = '123e4567-e89b-12d3-a456-426614174000';

  const response = await fetch(
    `https://api.telzino.com/v1/agents/${agentId}/history?page=1&limit=50`,
    {
      headers: { 'Authorization': 'Bearer YOUR_ACCESS_TOKEN' }
    }
  );

  const { data, pagination } = await response.json();
  ```

  ```python Python theme={null}
  import requests

  agent_id = '123e4567-e89b-12d3-a456-426614174000'

  response = requests.get(
      f'https://api.telzino.com/v1/agents/{agent_id}/history',
      headers={'Authorization': 'Bearer YOUR_ACCESS_TOKEN'},
      params={'page': 1, 'limit': 50}
  )

  result = response.json()
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": [
      {
        "id": 13993,
        "version": 62,
        "action": "reverted",
        "reverted_from_id": 13789,
        "created_at": "2026-10-08T15:23:04Z",
        "actor": {
          "id": "api:9e1e500f-9c05-4dbb-ad54-401de1daaf54",
          "email": null
        },
        "source": "dashboard-api",
        "changes": [
          {
            "field": "email_tool_instructions",
            "before": "Send the caller a summary after every call.",
            "after": "Send the caller a summary only when they ask for one."
          }
        ]
      },
      {
        "id": 13789,
        "version": 61,
        "action": "updated",
        "reverted_from_id": null,
        "created_at": "2026-10-06T17:34:29Z",
        "actor": {
          "id": "auth0|64f1c2a9e1b2c3d4e5f60718",
          "email": "jane@example.com"
        },
        "source": "dashboard-ui",
        "changes": [
          {
            "field": "config.dtmf_enabled",
            "before": null,
            "after": true
          },
          {
            "field": "greeting_message",
            "before": "Hi, thanks for calling!",
            "after": "Hi, thanks for calling Acme Dental!"
          }
        ]
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 50,
      "total": 62,
      "totalPages": 2,
      "hasNext": true,
      "hasPrev": false
    }
  }
  ```

  ```json 401 theme={null}
  {
    "error": "invalid_request",
    "error_description": "Missing or malformed Authorization header"
  }
  ```

  ```json 404 theme={null}
  {
    "error": "not_found",
    "error_description": "Agent not found or access denied"
  }
  ```

  ```json 503 theme={null}
  {
    "error": "temporarily_unavailable",
    "error_description": "Change history is temporarily unavailable. Retry shortly."
  }
  ```
</ResponseExample>

## Response Fields

| Field | Type | Description |
| - | - | - |
| `id` | integer | Permanent version id. Use it to [revert](/api-reference/agents/revert). It never changes. |
| `version` | integer | Display number, `1` = the oldest version on record. It can shift when old versions are removed by the account's retention setting, so store `id`, not `version`. |
| `action` | string | `created`, `updated`, `reverted` or `deleted` |
| `reverted_from_id` | integer \| null | For a revert, the `id` of the version it restored. `null` otherwise. |
| `created_at` | string | When the change was saved (ISO 8601, UTC) |
| `actor.id` | string | Who made the change: a user id, `api:<accountId>` for a change made with an API key, or `system` |
| `actor.email` | string \| null | The user's email, when the actor is a known user |
| `source` | string | Where the change came from: `dashboard-ui` (Portal), `connect-ui` (Connect), `dashboard-api` (this API), `revert`, or `system` |
| `changes` | array | Every field that changed in this version, with its `before` and `after` value. Always empty for a `deleted` entry (recorded when an agent is deleted; a deleted agent returns `404`, so the API does not normally show one). |

## Behavior

**Only what changed.** Each entry lists the fields that changed in that version, not the whole agent. Settings stored as one object (such as `config`) are split per key, so a change shows as `config.dtmf_enabled` rather than the whole object. A field that did not exist before (or was removed) has `before` (or `after`) set to `null`. Values are returned as stored, so a prompt change carries the full old and new prompt.

**Newest first.** Page 1 holds the most recent changes. Use `pagination.hasNext` to walk back through older versions. A page past the end returns an empty `data` array with the real `total`.

**Recorded a few seconds after the save.** A change made through the Portal, Connect or the API appears here a few seconds after it is saved, not instantly.

**What is recorded.** The agent's main settings: name and description, instructions and greeting, AI model, language and timezone, voice and speech settings, call transfer and warm transfer settings, recording settings, call, echo and automated-caller detection, the email tool, knowledge base settings, pronunciations, the notification email, the failover destination, and the `config` settings (such as `config.dtmf_enabled`). **Not recorded:** agent status (active / inactive), functions, outbound and voicemail greetings, AMD/IVR, web transfer, screenshare, email server, call limits and retries, agent type, integrations and credentials, SIP, and knowledge base documents.

**LiveKit agents only.** Agents on other providers have no recorded history and return an empty list.

<Info>
  Scoped API keys can use this endpoint for agents inside their reseller or organization. An agent outside the key's scope returns `404`, the same as an agent that does not exist.
</Info>

## Common Uses

### See who changed an agent and when

Read the newest changes to find out who edited an agent's prompt or greeting, and from which app:

```bash theme={null}
curl "https://api.telzino.com/v1/agents/{agentId}/history?limit=10" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### Export the full history

Walk every page until `hasNext` is `false`:

```javascript theme={null}
async function getFullHistory(agentId, token) {
  const entries = [];
  let page = 1;
  while (true) {
    const res = await fetch(
      `https://api.telzino.com/v1/agents/${agentId}/history?page=${page}&limit=100`,
      { headers: { 'Authorization': `Bearer ${token}` } }
    );
    const { data, pagination } = await res.json();
    entries.push(...data);
    if (!pagination.hasNext) break;
    page++;
  }
  return entries;
}
```

### Find a version to restore

Look for the last version before an unwanted change, then pass its `id` to [Revert Agent to a Version](/api-reference/agents/revert).

## Troubleshooting

| Error | Cause | Solution |
| - | - | - |
| `401` "Missing or malformed Authorization header" | No token, or a malformed one | Send `Authorization: Bearer YOUR_ACCESS_TOKEN` (see [Authentication](/api-reference/authentication)) |
| `401` with any other message | The token has expired, or was issued before the API key's secret was rotated | Get a new token (see [Authentication](/api-reference/authentication)) |
| `404` "Agent not found or access denied" | Wrong agent ID, or the agent belongs to another account or is outside the key's scope | Verify the ID with [List Agents](/api-reference/agents/list) and check your access token |
| `503` "Change history is temporarily unavailable" | A temporary problem on our side | Retry shortly |
| `500` "Internal server error" | An unexpected error | Retry; if it keeps happening, contact support |
| Empty `data` with `total: 0` | The agent is not a LiveKit agent, or it has not been changed since history recording began | Nothing to fix |
| A change you just made is missing | Changes are recorded a few seconds after the save | Read the history again shortly |
| A change you made is never listed | The field is one that is not recorded (see **What is recorded** above) | Expected behavior |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.