For AI agents: a documentation index is available at /docs/llms.txt. Append .md to any page URL for markdown, or send Accept: text/markdown.
Agent Analytics export API
Use the export API to pull production agent sessions, curated datasets, and evaluator configurations into your own offline evaluation pipeline.
The export API returns production agent data as JSON so you can run evaluations in your own tooling. The API covers sessions, the datasets you curate in Amplitude, and the evaluator configurations you define. An offline pipeline can read the same sessions, the same judging criteria, and the same scores the product uses.
This API is read-only. To send data in, refer to Send agent events without the AI SDK.
These endpoints aren't part of the OpenAPI-defined Developer API, so they don't appear in that reference and the amp CLI doesn't support them. Call them directly over HTTP.
Authentication and request requirements
- All endpoints use HTTP Basic authentication. Use your project's API key as the username and the secret key as the password. Refer to Find your API key and secret key.
- The authenticated project determines which data you receive. No
project_idparameter exists, and a key can't request another project's data. - Pagination cursors are opaque strings. Pass
next_page_tokenfrom the previous response unchanged. - Keep
sort_orderand all filters identical across every page of one traversal. Pagination reads live data rather than a snapshot, so data that changes during a traversal can change later pages.
Regions
Send requests to the data center that hosts your project.
| Region | Base URL |
|---|---|
| US | https://developer-api.amplitude.com |
| EU | https://developer-api.eu.amplitude.com |
Keys aren't interchangeable between regions. A US project's key returns 401 against the EU host.
Lookback and session visibility
Two product rules shape what a response contains, and both apply before pagination:
- Lookback window: Your plan's entitlement limits how far back sessions are available. A request for an explicit time range outside that window returns
400rather than narrowing the range. An organization with no lookback entitlement can't use the session and dataset endpoints. Assign an entitlement before you start. - Session cap: An organization that reached its session cap can't export newer sessions. Sessions already enriched stay available.
Amplitude reports excluded sessions rather than dropping them silently. Collection responses carry an omissions array that counts what the filters removed and why.
The two collection endpoints exclude a withheld session and count it in omissions. The single-session endpoint returns 403 instead, because there's nothing to omit from.
| Reason | Meaning |
|---|---|
session_not_found | A dataset member's session no longer exists. |
outside_lookback_window | The session falls outside your lookback entitlement. |
session_cap | The organization reached its session cap, so Amplitude withholds the session. |
Omission counts describe the whole matching collection, not the current page. The counts repeat on every page, so don't add them across pages.
List sessions
Returns a paginated list of sessions for the authenticated project, with metadata and human review. Traces, spans, and turns come from the single-session endpoint.
GET /v1/agent-analytics/export/sessions
curl 'https://developer-api.amplitude.com/v1/agent-analytics/export/sessions' \
-u '{api_key}:{secret_key}'
Filter by agent and time range:
curl 'https://developer-api.amplitude.com/v1/agent-analytics/export/sessions?agent_name=support-bot&start_time=2026-01-01T00%3A00%3A00Z&end_time=2026-01-31T23%3A59%3A59Z&page_size=100' \
-u '{api_key}:{secret_key}'
Fetch the next page:
curl 'https://developer-api.amplitude.com/v1/agent-analytics/export/sessions?page_size=100&page_token={next_page_token}' \
-u '{api_key}:{secret_key}'
Query parameters
| Name | Description |
|---|---|
user_id | Optional. String. Returns sessions for one user ID. |
agent_name | Optional. String. Returns sessions for one agent. |
start_time | Optional. ISO 8601 string with a timezone offset. Lower bound on session start time, inclusive. A value outside your lookback window returns 400. |
end_time | Optional. ISO 8601 string with a timezone offset. Upper bound on session start time, inclusive. An end time earlier than the start time returns 400. |
page_size | Optional. Integer between 1 and 200. Defaults to 50. |
page_token | Optional. String. Opaque cursor from a previous response's next_page_token. |
sort_order | Optional. String. desc returns newest sessions first (default). asc returns oldest first. Keep sort_order consistent across pages. |
Response
{
"sessions": [
{
"session": {
"object": "agent_session",
"id": "string",
"project_id": "string",
"user_id": "string",
"agent_name": "string",
"start_time": "2026-01-15T10:00:00.000Z",
"end_time": "2026-01-15T10:04:12.000Z",
"duration_ms": 252000,
"num_traces": 3,
"num_errors": 0,
"models_used": ["string"],
"total_input_tokens": 2406,
"total_output_tokens": 225,
"total_cost_usd": 0.001285,
"status": "enriched",
"enrichment_status": "completed",
"last_message": "string",
"metadata": {}
},
"human_review": { "comments": [], "tags": [] }
}
],
"next_page_token": "string",
"omissions": [{ "reason": "session_cap", "count": 12 }]
}
| Property | Description |
|---|---|
sessions[].session.id | Session identifier. Use this value as {session_id} when you request a single session. |
sessions[].session.duration_ms | Wall-clock duration of the session in milliseconds. |
sessions[].session.status | Lifecycle state of the session, such as closed or enriched. |
sessions[].session.enrichment_status | State of quality-signal enrichment, such as pending or completed. |
sessions[].session.last_message | The final message in the conversation, when message content is available. |
sessions[].human_review | Comments and tags reviewers added in Amplitude. |
next_page_token | Cursor for the next page. Absent on the last page. |
omissions | Counts of sessions the filters removed, by reason. |
Get one session
Returns one session with its full traces, spans, sanitized turns, evaluation results, enrichments, and dataset memberships.
GET /v1/agent-analytics/export/sessions/{session_id}
Use the id from the session list. Session IDs are the identifiers your instrumentation sends, not the numeric row IDs shown elsewhere in Amplitude.
curl 'https://developer-api.amplitude.com/v1/agent-analytics/export/sessions/{session_id}' \
-u '{api_key}:{secret_key}'
Response
{
"session": { "object": "agent_session" },
"traces": [
{
"object": "agent_trace",
"id": "string",
"spans": [
{
"object": "agent_span",
"id": "string",
"name": "llm_completion",
"attributes": {},
"raw_input": "string",
"raw_output": "string"
}
]
}
],
"turns": [
{
"object": "agent_turn",
"id": "string",
"trace_id": "string",
"turn_index": 1,
"role": "user",
"latency_ms": 0,
"created_at": "2026-01-15T10:00:00.000Z",
"provider_request_id": null
}
],
"evaluations": [
{
"object": "agent_evaluation",
"evaluator_id": "string",
"evaluator_type": "detector",
"granularity": "session",
"span_id": null,
"passed": null,
"status": "success",
"model_used": "string",
"cost_usd": 0.00146,
"latency_ms": 4427,
"created_at": "2026-01-15T10:00:00.000Z",
"result": {}
}
],
"enrichments": [{ "object": "agent_session_enrichment" }],
"datasets": [],
"human_review": { "comments": [], "tags": [] },
"conversation_turn_count": 4,
"shared_attributes": {}
}
| Property | Description |
|---|---|
traces[].spans[].attributes | Span attributes as your instrumentation sent them. The key set varies by SDK and agent. |
traces[].spans[].raw_input | Input text for the span, when message content is available. |
traces[].spans[].raw_output | Output text for the span, when message content is available. |
turns | Ordered turn records. Message content lives on the spans, not on turns. |
turns[].created_at | Timestamp of the turn. Sort on this value to reconstruct the conversation in order. |
turns[].provider_request_id | The model provider's own identifier for the completion. Use it to join a turn to your own inference records. null on user turns, and on assistant turns where your instrumentation didn't capture it. Refer to Provider request IDs. |
evaluations | Results from the evaluators you defined, one entry per evaluator. Refer to Evaluation results. |
enrichments | Quality signals, topic classifications, and rubric scores Amplitude computed. |
datasets | Datasets this session belongs to. |
conversation_turn_count | Number of user-facing conversation turns. |
shared_attributes | Deduplicated span attributes. Refer to Shared attributes. |
Provider request IDs
turns[].provider_request_id carries the identifier the model provider assigned to the completion. Amplitude reads it from the gen_ai.response.id attribute your instrumentation sends. It's the join key between an Amplitude turn and the request record on the provider's side, which makes it the field to use when you send evaluation scores back to a provider or reconcile cost against their billing.
The format is the provider's, not Amplitude's. Some providers return a prefixed string such as chatcmpl-..., others a bare token with no prefix. Treat the value as opaque: match it against your own records, don't parse it or assume a shape.
It's null in three cases: on user turns, which have no completion; on assistant turns from instrumentation that doesn't capture the attribute; and on sessions Amplitude ingested before the field existed. There's no backfill, so treat an absent ID as a gap rather than an error.
Evaluation results
Each entry in evaluations is the most recent result from one evaluator for this session. Amplitude reports its own built-in signals in enrichments instead.
| Property | Description |
|---|---|
evaluator_id | The evaluator that produced this result. Fetch its definition from Get an evaluator configuration. |
evaluator_type | The evaluator's shape, such as detector, classifier, or rubric. It determines which keys result carries. |
granularity | What the evaluator scored. session for a whole session; span-level evaluators also set span_id. |
passed | Whether the result met the evaluator's pass threshold, or null when the evaluator has no threshold. |
status | success when the evaluator produced a result. On any other status, result may be empty and result.error explains why. |
model_used, cost_usd, latency_ms | What it cost Amplitude to run this evaluator. Absent for rule-based evaluators that don't call a model. |
result | The evaluator's output. Its keys depend on evaluator_type. |
Amplitude passes result through as the evaluator produced it, so its keys vary:
| Evaluator type | Keys |
|---|---|
| Rubric | score, normalized_score |
| Classifier | primary, secondary |
| Detector | detected, signals |
Most results also carry rationale explaining the outcome, and evidence quoting the parts of the conversation that support it.
These are the keys worth branching on, not a complete list. A result can carry others, such as the evaluator's own confidence scores or counts of how many turns it read, and that set changes as the evaluator pipeline does. Read the keys you need and ignore the rest.
result also repeats several envelope fields, among them evaluator_id, status, cost_usd, and latency_ms. Prefer the envelope copies. Amplitude normalizes those to the types this reference documents, while the values inside result stay as the evaluator wrote them and can differ in precision.
Treat classifier values as labels to display and group by, not as an enum to branch on. The evaluating model generates them, and the set of values an evaluator can return may change as that model or its prompt changes. If your pipeline needs a fixed set of outcomes, map the values you care about and handle unrecognized ones rather than assuming the list is closed.
Shared attributes
A span attribute that repeats across spans, such as a system prompt or a tool definition, is stored once in the session-level shared_attributes map. Each occurrence carries a reference in place of the value:
{ "$shared_attribute": "a1b2c3d4" }
Resolve a reference by looking up its value in shared_attributes. Deduplication is lossless, and it can reduce a response from several megabytes to a few hundred kilobytes. A session with nothing repeated returns shared_attributes as an empty object.
A session too large to return in one response fails with 400 rather than returning partial data. An export never silently truncates traces or turns.
Get a dataset
Returns a dataset with a paginated list of its member sessions, including ground-truth labels and human review.
GET /v1/agent-analytics/export/datasets/{dataset_id}
curl 'https://developer-api.amplitude.com/v1/agent-analytics/export/datasets/{dataset_id}?page_size=50' \
-u '{api_key}:{secret_key}'
Query parameters
| Name | Description |
|---|---|
page_size | Optional. Integer between 1 and 200. Defaults to 50. |
page_token | Optional. String. Opaque cursor from a previous response's next_page_token. |
sort_order | Optional. String. desc (default) or asc, ordered by when the session was added to the dataset. |
Session filters such as user_id and agent_name aren't valid on this endpoint and return 400.
Response
{
"dataset": {
"object": "agent_dataset",
"id": "string",
"project_id": "string",
"name": "string",
"description": "string",
"agent_name": "string",
"source_type": "manual",
"created_at": "2026-01-15T10:00:00.000Z",
"updated_at": "2026-01-15T10:00:00.000Z"
},
"members": [
{
"object": "agent_dataset_member",
"session_id": "string",
"added_at": "2026-01-15T10:00:00.000Z",
"selection_reason": "string",
"ground_truth_labels": {
"evaluator_results": {},
"overridden_evaluators": [],
"review_status": "partial",
"reviewed_by": "string",
"reviewed_at": "2026-01-15T10:00:00.000Z"
},
"session": { "object": "agent_session" },
"human_review": { "comments": [], "tags": [] }
}
],
"next_page_token": "string",
"omissions": []
}
| Property | Description |
|---|---|
members[].ground_truth_labels | Human-verified labels for this session. evaluator_results maps evaluator ID to its verified verdict, and overridden_evaluators lists the evaluators a reviewer corrected. |
members[].ground_truth_labels.review_status | How complete the review is, such as partial or verified. |
members[].session | Session metadata, in the same shape the session list returns. |
Each member carries session metadata only. Request the session individually for its traces and turns.
Get an evaluator configuration
Returns one evaluator configuration, including its prompt, model, and labels, so you can reproduce the same judgment in your own tooling.
GET /v1/agent-analytics/export/evaluators/{evaluator_id}
This endpoint doesn't read session data, so the lookback window and session cap don't apply.
curl 'https://developer-api.amplitude.com/v1/agent-analytics/export/evaluators/{evaluator_id}' \
-u '{api_key}:{secret_key}'
Response
{
"config": {
"object": "agent_evaluator",
"id": "string",
"project_id": "string",
"topic": "string",
"status": "draft",
"output_type": "binary",
"run_on": "all",
"description": "string",
"tags": [{ "id": "yes", "label": "True", "description": "string", "examples": [] }],
"prompt": "string",
"model": "string",
"evaluation_method": "llm",
"granularity": "session",
"created_at": "2026-01-15T10:00:00.000Z",
"updated_at": "2026-01-15T10:00:00.000Z"
}
}
| Property | Description |
|---|---|
config.topic | Display name of the evaluator. |
config.status | Whether the evaluator is draft or active. |
config.output_type | Shape of the verdict, such as binary or rubric. |
config.tags | The labels the evaluator can return, with descriptions and examples. |
config.prompt | The judging prompt, for LLM evaluators. |
config.model | The model the evaluator runs on, for LLM evaluators. |
config.evaluation_method | llm for a model-judged evaluator, code for a deterministic one. |
Status and error codes
| Code | Description |
|---|---|
200 OK | Successful request. |
400 Bad Request | Invalid parameter, a time range outside your lookback window, a reversed time range, or a session too large to return. |
401 Unauthorized | Missing or invalid credentials, or a key from a different region. |
403 Forbidden | The requested session is withheld by the session cap. Only the single-session endpoint returns this code. |
404 Not Found | No session, dataset, or evaluator with that ID exists in the authenticated project. |
429 Too Many Requests | Rate limit exceeded. Retry after the interval in the Retry-After header. |
503 Service Unavailable | Temporary. Retry after the interval in the Retry-After header. |
Errors use application/problem+json with an error_code field and a retryable flag.
Was this helpful?