# Get agent topic analytics

Return topic-discovery status and per-topic conversation, sentiment, and evaluation metrics for an agent in the requested window.

## Endpoint

`GET /api/v1/workspaces/{workspace_id}/agents/{agent_id}/topics`

## Authentication

| Class | Authentication | Minimum role | API key |
| --- | --- | --- | --- |
| customer-api | Bearer API key or dashboard session cookie; dashboard mutations also require X-CX-Request: 1. | member | Allowed |

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `workspace_id` | path | `string` | Yes | — |
| `agent_id` | path | `string` | Yes | — |
| `from` | query | `string or null` | No | — |
| `to` | query | `string or null` | No | — |
| `branch_id` | query | `string or null` | No | — |

## Request body

This operation has no request body.

## Example

```bash
curl --request GET 'https://operade.ai/api/v1/workspaces/ws_demo/agents/agt_demo/topics?from=2026-08-01T00%3A00%3A00Z&to=2026-08-08T00%3A00%3A00Z' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

## Responses

| Status | Description | Content |
| --- | --- | --- |
| 4XX | Client Error | application/json: `ErrorResponse` |
| 200 | Successful Response | application/json: `AgentTopicsResponse` |

### 4XX application/json response schema

| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `$` | `object` | ErrorResponse | — | No | Yes | — | — |
| `error` | `object` | ErrorItem | — | No | Yes | — | — |
| `error.code` | `string` | — | — | No | Yes | — | — |
| `error.details` | `object` | — | — | No | No | — | — |
| `error.message` | `string` | — | — | No | Yes | — | — |

### 200 application/json response schema

| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `$` | `object` | AgentTopicsResponse | — | No | Yes | — | — |
| `error_code` | `string or null` | — | — | Yes | Yes | "quota_exhausted", "provider_unavailable", "invalid_response", "internal" | — |
| `last_run_at` | `string or null` | — | date-time | Yes | Yes | — | — |
| `next_run_at` | `string` | — | date-time | No | Yes | — | — |
| `status` | `string` | — | — | No | Yes | "off", "processing", "failed", "waiting", "ready" | — |
| `topics` | `array<AgentTopic>` | — | — | No | Yes | — | — |
| `topics[]` | `object` | AgentTopic | — | No | Yes | — | — |
| `topics[].conversation_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].description` | `string` | — | — | No | Yes | — | — |
| `topics[].label` | `string` | — | — | No | Yes | — | — |
| `topics[].metrics` | `object` | AgentTopicMetrics | — | No | Yes | — | — |
| `topics[].metrics.evaluation_criteria` | `array<TopicEvaluationMetrics>` | — | — | No | Yes | — | — |
| `topics[].metrics.evaluation_criteria[]` | `object` | TopicEvaluationMetrics | — | No | Yes | — | — |
| `topics[].metrics.evaluation_criteria[].criteria_id` | `string` | — | — | No | Yes | — | — |
| `topics[].metrics.evaluation_criteria[].failure_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.evaluation_criteria[].success_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.evaluation_criteria[].unknown_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.overall_success` | `object` | TopicSuccessMetrics | — | No | Yes | — | — |
| `topics[].metrics.overall_success.denominator` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.overall_success.failure_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.overall_success.rate` | `number or null` | — | — | Yes | Yes | — | — |
| `topics[].metrics.overall_success.success_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.sentiment` | `object` | TopicSentimentMetrics | — | No | Yes | — | — |
| `topics[].metrics.sentiment.count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.sentiment.max` | `number or string or null` | — | — | Yes | Yes | — | — |
| `topics[].metrics.sentiment.min` | `number or string or null` | — | — | Yes | Yes | — | — |
| `topics[].metrics.sentiment.negative_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.sentiment.neutral_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.sentiment.positive_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].metrics.sentiment.sum` | `number or string` | — | — | No | Yes | — | — |
| `topics[].previous_conversation_count` | `integer` | — | — | No | Yes | — | — |
| `topics[].topic_id` | `string` | — | — | No | Yes | — | — |
| `window` | `object` | AnalyticsTimeRange | — | No | Yes | — | — |
| `window.from` | `string` | — | date-time | No | Yes | — | — |
| `window.to` | `string` | — | date-time | No | Yes | — | — |

### Response example

```json
{
  "status": "off",
  "error_code": "quota_exhausted",
  "last_run_at": "2026-01-01T00:00:00Z",
  "next_run_at": "2026-01-01T00:00:00Z",
  "window": {
    "from": "2026-01-01T00:00:00Z",
    "to": "2026-01-01T00:00:00Z"
  },
  "topics": []
}
```

## Errors

Reviewed common and route-declared errors are summarized here; the list is not exhaustive. Start with the [distributed error index](/docs/reference/api/errors) to find each code's canonical domain page.

| Status | Code | Description |
| --- | --- | --- |
| 401 | `unauthenticated` | Authentication is missing, invalid, or revoked. |
| 403 | `forbidden` | The authenticated caller does not have access to this operation. |
| 404 | `not_found` | The requested workspace resource was not found. |
| 422 | `validation_failed` | The analytics window, filter combination, tab, grouping, or requested resource is invalid. |

## Related operations

- [Dismiss an analytics Spotlight insight](/docs/api-reference/analytics/dismiss-analytics-spotlight-insight) — `POST /api/v1/workspaces/{workspace_id}/analytics/spotlight/{insight_key}/dismiss`
- [Export an analytics tab](/docs/api-reference/analytics/export-analytics-tab) — `GET /api/v1/workspaces/{workspace_id}/analytics/tabs/{tab}/export`
- [Get the live conversation count](/docs/api-reference/analytics/get-analytics-live-count) — `GET /api/v1/workspaces/{workspace_id}/analytics/live-count`
