Analysis API
Query intents, violations, conversations, events, and trace data programmatically
Use the Analysis API to query the same production data available in Voxmith: Intents, Violations, Conversations, and Events. It is useful for internal tools, scheduled reports, and investigations driven by an AI agent.
This reference is intentionally not indexed by search engines. Endpoint names containing
sentiment and sop are legacy API names; the corresponding Voxmith concepts are
Intents and Violations.
Before you begin
Create an API key in Voxmith, then set it as an environment variable using your runtime, deployment platform, or preferred .env loader:
VOXMITH_API_KEY=your_api_keyEvery request uses:
- Base URL:
https://api.voxmith.com - Header:
x-api-key: $VOXMITH_API_KEY - Content type:
application/jsonfor request bodies
Most endpoints accept time_range. Supported values are 5min, 1h, 1d, 1w, 1m, all, and custom durations such as custom:2h30m. Most endpoints default to 30d when the value is omitted or invalid.
Recommended workflow
| Goal | Start with | Then drill into |
|---|---|---|
| Understand user demand | sentiment-stats |
sentiment-messages → conversation-detail |
| Find broken agent behavior | sop-stats |
sop-messages → conversation-detail |
| Debug one execution | conversation-spans |
event-io |
| Build a conversation feed | user-stories |
conversation-detail |
| Ask an open-ended question | Deterministic endpoints above | run-spotlight-query as a fallback |
Use exact intent or violation titles returned by the list and stats endpoints. Do not invent normalized tags. Intents and violations are classified proactively, so there is no manual classification step.
Intents
POST /dashboard/api/sentiment-stats
Lists top intent clusters and counts in a time window. Best for: Ranking the intents that matter across recent conversations.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
time_range |
No | 30d |
Window to aggregate. |
metadata_filters |
No | [] |
Filters by event, conversation, user metadata, or user_id. |
Response schema:
| Field | Type | Description |
|---|---|---|
total_analyzed |
integer |
Count of unique events matched to active intents. |
total_messages |
integer |
Count of events in the same filtered window. |
top_tags |
object[] |
Up to 10 ranked intent clusters. |
top_tags[].tag |
string |
Intent title. |
top_tags[].count |
integer |
Number of matched unique events. |
tag_distribution |
object[] |
Same ranked cluster list used by the dashboard distribution view. |
tag_distribution[].tag |
string |
Intent title. |
tag_distribution[].count |
integer |
Number of matched unique events. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sentiment-stats" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"time_range":"1w"}'
POST /dashboard/api/sentiment-messages
Returns paginated user messages that matched one intent cluster.
Best for: Inspecting evidence after selecting an exact intent title from sentiment-stats or sentiments.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tag |
Yes | None | Intent title from sentiment-stats or sentiments. |
time_range |
No | 30d |
Window to search. |
page |
No | 1 |
Page number. |
limit |
No | 50, max 100 |
Messages per page. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
messages |
object[] |
User-side matched messages for the requested intent tag. |
messages[].message_id |
string |
Matched event id. Intent message rows use the input-side id when applicable. |
messages[].conversation_id |
string |
Conversation UUID. |
messages[].timestamp |
string |
Event timestamp. |
messages[].role |
string |
user, assistant, or system. |
messages[].message |
string |
Readable matched message text. |
messages[].input |
string |
Readable input text when loaded. |
messages[].output |
string |
Readable output text when loaded. |
messages[].matched_tags |
string[] |
Matching intent titles. |
messages[].user_id |
string |
Customer-provided user id when present on the conversation. |
total_count |
integer |
Total matching unique events for the filter. |
page |
integer |
Applied page number. |
limit |
integer |
Applied page size. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sentiment-messages" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tag":"Draft an email","time_range":"1w","page":1,"limit":25}'
POST /dashboard/api/sentiment-timeline
Returns a bucketed count timeline for one intent cluster. Best for: Seeing whether one intent is rising, falling, or spiking over time.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tag |
Yes | None | Intent title. |
time_range |
No | 30d |
Window to chart. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
timeline |
object[] |
Bucketed counts for the requested intent tag. |
timeline[].timestamp |
string |
Bucket start timestamp in RFC3339 format. |
timeline[].value |
number |
Count for the bucket. |
bucket_seconds |
integer |
Bucket width used for the timeline. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sentiment-timeline" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tag":"Draft an email","time_range":"1w"}'
POST /dashboard/api/sentiment-timelines
Returns bucketed timelines for multiple intent clusters in one call. Best for: Comparing several known intents over the same time window.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tags |
Yes | None | Intent titles. |
time_range |
No | 30d |
Window to chart. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
timelines |
object<string,object[]> |
Object keyed by intent title. Each value is that intent's bucketed timeline. |
timelines.<tag>[].timestamp |
string |
Bucket start timestamp in RFC3339 format. |
timelines.<tag>[].value |
number |
Count for the bucket. |
bucket_seconds |
integer |
Bucket width used for all timelines. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sentiment-timelines" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tags":["Draft an email","Schedule a meeting"],"time_range":"1w"}'
POST /dashboard/api/summarize-intent-distribution
Summarizes why one intent cluster is appearing in the selected time window.
Best for: Producing a short explanation after reviewing sentiment-stats or sentiment-messages.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tag |
Yes | None | Intent title from sentiment-stats or sentiments. |
time_range |
No | 30d |
Window to summarize. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
summary |
string |
Natural-language explanation of the main patterns behind the matched intent events. |
buckets |
object[] |
Summarizer-produced buckets. Empty array when no matching input messages exist. |
buckets[].label |
string |
Natural-language bucket label from the summarizer. |
buckets[].count |
integer |
Number of sampled matched messages in the bucket. |
buckets[].message_ids |
string[] |
Matched message ids supporting the bucket. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/summarize-intent-distribution" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tag":"Draft an email","time_range":"1w"}'
GET /dashboard/api/sentiments
Lists active and suggested intent definitions. Best for: Finding an existing intent before querying or creating one.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
| None | No | None | No request body. |
Response schema:
Output format: object[] at the JSON response root. Decode directly as an array/list, not as { "sentiments": [...] }.
| Field | Type | Description |
|---|---|---|
(root) |
object[] |
Active and suggested intent definitions for the API-key organization. |
(root)[].id |
string |
Stable intent id. |
(root)[].title |
string |
Intent title used as the query tag. |
(root)[].description |
string |
Matching guidance. |
(root)[].active |
boolean |
True for active or suggested definitions accepted by readers. |
(root)[].status |
string |
active, inactive, or suggested. |
(root)[].evidence_message_count |
integer |
Suggested-intent evidence message count. |
(root)[].evidence_conversation_count |
integer |
Suggested-intent evidence conversation count. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sentiments" \
-H "x-api-key: $VOXMITH_API_KEY"
POST /dashboard/api/sentiments
Creates a new intent definition for future proactive classification. Best for: Creating an intent only when no existing definition covers the need.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
title |
Yes | None | Stable intent name. Duplicate active/suggested titles are skipped. |
description |
No | "" |
Intent matching guidance. |
active |
Yes | None | Must be true for agent-created intents. If omitted or false, the intent is inactive and will not be useful for proactive classification. |
Response schema:
Created response:
| Field | Type | Description |
|---|---|---|
id |
string |
Stable intent id. |
title |
string |
Created intent title. |
description |
string |
Created intent description. |
active |
boolean |
Final active state. Send active:true in the request for agent-created production intents. |
status |
string |
Final lifecycle status. |
Duplicate skip response:
| Field | Type | Description |
|---|---|---|
skipped |
boolean |
true when an active or suggested intent with the same title already exists. |
message |
string |
Duplicate explanation. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sentiments" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Draft an email","description":"User wants the agent to draft, edit, or send an email.","active":true}'
PUT /dashboard/api/sentiments/{id}
Updates an existing intent definition or lifecycle status.
Best for: Correcting, enabling, or disabling an existing intent. Use active, not status.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
id path param |
Yes | None | Intent id from GET /sentiments or create response. |
title |
No | Existing value | New title; cannot be empty. |
description |
No | Existing value | New matching guidance. |
active |
No | Existing value | Set true to enable the intent or false to disable it. |
Response schema:
| Field | Type | Description |
|---|---|---|
id |
string |
Updated intent id. |
success |
boolean |
true when the mutation was accepted. |
active |
boolean |
Final active state. |
status |
string |
Final lifecycle status. |
Call:
curl -sS -X PUT "https://api.voxmith.com/dashboard/api/sentiments/$INTENT_ID" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"description":"User wants the agent to draft, edit, or send an email.","active":true}'Violations
POST /dashboard/api/sop-stats
Lists the most common violations and their counts in a time window. Best for: Ranking the agent rules violated most often.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
time_range |
No | 30d |
Window to aggregate. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
total_analyzed |
integer |
Count of unique events matched to active violations. |
total_messages |
integer |
Count of events in the same filtered window. |
top_tags |
object[] |
Up to 10 ranked violation rule clusters. |
top_tags[].tag |
string |
Violation title. |
top_tags[].count |
integer |
Number of matched unique events. |
tag_distribution |
object[] |
Same ranked cluster list used by the dashboard distribution view. |
tag_distribution[].tag |
string |
Violation title. |
tag_distribution[].count |
integer |
Number of matched unique events. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sop-stats" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"time_range":"1w"}'
POST /dashboard/api/sop-messages
Returns paginated assistant messages that violated one rule. Best for: Inspecting evidence after selecting an exact violation title. Violations match assistant output, while intents match user input.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tag |
Yes | None | Violation title from sop-stats or sops. |
time_range |
No | 30d |
Window to search. |
page |
No | 1 |
Page number. |
limit |
No | 50, max 100 |
Messages per page. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
messages |
object[] |
Assistant-side matched messages for the requested violation rule tag. |
messages[].message_id |
string |
Matched assistant event id. |
messages[].conversation_id |
string |
Conversation UUID. |
messages[].timestamp |
string |
Event timestamp. |
messages[].role |
string |
user, assistant, or system. |
messages[].message |
string |
Readable matched message text. |
messages[].input |
string |
Readable input text when loaded. |
messages[].output |
string |
Readable output text when loaded. |
messages[].matched_tags |
string[] |
Matching violation rule titles. |
messages[].user_id |
string |
Customer-provided user id when present on the conversation. |
total_count |
integer |
Total matching unique events for the filter. |
page |
integer |
Applied page number. |
limit |
integer |
Applied page size. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sop-messages" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tag":"Confirm scheduling conflicts proactively","time_range":"1w","page":1,"limit":25}'
POST /dashboard/api/sop-violations
Returns a paginated feed of violation events across all rules. Best for: Exploring violations before choosing a single rule to investigate.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
time_range |
No | 30d |
Window to search. |
page |
No | 1 |
Page number. |
limit |
No | 20, max 100 |
Violating events per page. |
metadata_filters |
No | [] |
Parsed but currently not applied by this endpoint. Use sop-messages when metadata filtering by a specific violation rule is required. |
Response schema:
| Field | Type | Description |
|---|---|---|
violations |
object[] |
Paginated violating events across all violation rule definitions. |
violations[].message_id |
string |
Violating assistant event id. |
violations[].conversation_id |
string |
Conversation UUID. |
violations[].timestamp |
string |
Event timestamp. |
violations[].violations |
string[] |
Violation titles matched by the event. |
violations[].message_content |
string |
Readable assistant output when available. |
violations[].sop_title |
string |
Matched violation title when resolved. |
violations[].violation_description |
string |
Violation description when populated. |
violations[].user_id |
string |
Customer-provided user id when present. |
violations[].event_id |
string |
Underlying event id when populated. |
total_count |
integer |
Total unique violating events in the time window. |
page |
integer |
Applied page number. |
limit |
integer |
Applied page size. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sop-violations" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"time_range":"1w","page":1,"limit":20}'
POST /dashboard/api/sop-timeline
Returns a bucketed count timeline for one violation rule. Best for: Seeing whether one violation is rising, falling, or spiking over time.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tag |
Yes | None | Violation title. |
time_range |
No | 30d |
Window to chart. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
timeline |
object[] |
Bucketed counts for the requested violation rule tag. |
timeline[].timestamp |
string |
Bucket start timestamp in RFC3339 format. |
timeline[].value |
number |
Count for the bucket. |
bucket_seconds |
integer |
Bucket width used for the timeline. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sop-timeline" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tag":"Confirm scheduling conflicts proactively","time_range":"1w"}'
POST /dashboard/api/sop-timelines
Returns bucketed timelines for multiple violation rule clusters in one call. Best for: Comparing several known violations over the same time window.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tags |
Yes | None | Violation titles. |
time_range |
No | 30d |
Window to chart. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
timelines |
object<string,object[]> |
Object keyed by violation rule title. Each value is that rule's bucketed timeline. |
timelines.<tag>[].timestamp |
string |
Bucket start timestamp in RFC3339 format. |
timelines.<tag>[].value |
number |
Count for the bucket. |
bucket_seconds |
integer |
Bucket width used for all timelines. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sop-timelines" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tags":["Confirm scheduling conflicts proactively","No unsupported guarantees"],"time_range":"1w"}'
POST /dashboard/api/summarize-sop-distribution
Summarizes why one violation rule is being violated in the selected time window.
Best for: Producing a short explanation after reviewing sop-stats or sop-messages.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
tag |
Yes | None | Violation title from sop-stats or sops. |
time_range |
No | 30d |
Window to summarize. |
metadata_filters |
No | [] |
Metadata filters. |
Response schema:
| Field | Type | Description |
|---|---|---|
summary |
string |
Natural-language explanation of the main violation patterns. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/summarize-sop-distribution" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tag":"Confirm scheduling conflicts proactively","time_range":"1w"}'
GET /dashboard/api/sops
Lists active and suggested violation rule definitions. Best for: Finding an existing violation rule before querying or creating one.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
| None | No | None | No request body. |
Response schema:
Output format: object[] at the JSON response root. Decode directly as an array/list, not as { "sops": [...] }.
| Field | Type | Description |
|---|---|---|
(root) |
object[] |
Active and suggested violation rule definitions for the API-key organization. |
(root)[].id |
string |
Stable violation rule id. |
(root)[].title |
string |
Violation title used as the query tag. |
(root)[].description |
string |
Rule text or matching guidance. |
(root)[].active |
boolean |
True for active or suggested definitions accepted by readers. |
(root)[].status |
string |
active, inactive, or suggested. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sops" \
-H "x-api-key: $VOXMITH_API_KEY"
POST /dashboard/api/sops
Creates a new violation rule definition for proactive violation detection.
Best for: Creating a rule only when no existing violation definition covers it. Send active:true to classify future messages and asynchronously backfill up to 1,000 recent conversations.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
title |
Yes | None | Stable violation rule name. Duplicate active/suggested titles are skipped. |
description |
No | "" |
Rule text or matching guidance. |
active |
Yes | None | Must be true for agent-created violation rules. Active rules classify future messages and asynchronously backfill up to 1,000 recent conversations. |
Response schema:
Created response:
| Field | Type | Description |
|---|---|---|
id |
string |
Stable violation rule id. |
title |
string |
Created violation rule title. |
description |
string |
Created violation rule description. |
active |
boolean |
Final active state. Send active:true in the request for agent-created production rules. |
status |
string |
Final lifecycle status. |
Duplicate skip response:
| Field | Type | Description |
|---|---|---|
skipped |
boolean |
true when an active or suggested violation rule with the same title already exists. |
message |
string |
Duplicate explanation. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/sops" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Confirm scheduling conflicts proactively","description":"Assistant must identify scheduling conflicts and ask for confirmation before booking or sending calendar changes.","active":true}'
PUT /dashboard/api/sops/{id}
Updates an existing violation rule definition or lifecycle status. Best for: Correcting, enabling, or disabling a violation rule. Activating a rule or changing its active description asynchronously backfills up to 1,000 recent conversations.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
id path param |
Yes | None | Violation rule ID from GET /sops or the create response. |
title |
No | Existing value | New title; cannot be empty. |
description |
No | Existing value | New rule text or matching guidance. |
active |
No | Existing value | Set true to enable the violation rule or false to disable it. |
Response schema:
| Field | Type | Description |
|---|---|---|
id |
string |
Updated violation rule id. |
success |
boolean |
true when the mutation was accepted. |
active |
boolean |
Final active state. |
status |
string |
Final lifecycle status. |
Call:
curl -sS -X PUT "https://api.voxmith.com/dashboard/api/sops/$VIOLATION_ID" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"description":"Assistant must surface conflicts and get explicit confirmation before taking scheduling action.","active":true}'Conversations and events
POST /dashboard/api/user-stories
Lists conversations with event rows, metadata, intent matches, and violations. It can also page conversation- or user-metadata groups, then page users within one selected group.
Best for: Building a paginated group → user → conversation inventory. Use event-io or raw-logs for exact input and output.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
time_range |
No | 30d |
Window based on conversation created_at. |
page |
No | 1 |
Page number. |
page_size |
No | 50, max 100 |
Conversations, groups, or users per page. The dashboard requests 15 distinct group values at a time. |
connection_type |
No | [] |
String or array. Filters conversation.metadata.transport_type. |
agent_name |
No | [] |
String or array. Filters event agent_name. |
exclude_io |
No | false |
If true, omits input_args and output_result. |
metadata_filters |
No | [] |
Metadata filters. |
sentiment_ids |
No | [] |
Intent UUIDs; conversations must contain an event matching any selected intent. |
sop_ids |
No | [] |
Violation UUIDs; conversations must contain an event matching any selected violation. |
allow_limited_preview |
No | false |
Dashboard preview flag; agents should leave it false. |
search_field |
With search_value |
None | Exact selected identifier. Grouped requests accept only group_value. |
search_value |
With search_field |
None | Exact identifier or grouped metadata value selected from search options. |
group_by |
No | None | {source,key} where source is conversation_metadata or user_metadata. Omit for the original conversation response. |
group_level |
No | groups when group_by is present |
groups pages metadata values; users pages users within group_value; conversations pages conversations for group_user_key. |
group_value |
For grouped children | None | Exact metadata value whose users or conversations should be returned. |
group_user_key |
For conversations |
None | Opaque key returned by the grouped-user response. |
Response schema:
| Field | Type | Description |
|---|---|---|
conversations |
object[] |
Conversation rows with event children and metadata. |
conversations[].id |
string |
Conversation UUID. |
conversations[].created_at |
string |
Conversation creation timestamp. |
conversations[].metadata |
object<string,string> |
Conversation metadata. |
conversations[].user_id |
string |
Customer-provided user id. |
conversations[].user_metadata |
object<string,any> |
Customer user metadata. |
conversations[].events |
object[] |
Events in this conversation, including child spans. |
conversations[].events[].event_id |
string |
Event UUID. |
conversations[].events[].event_type |
string |
Event primitive type. |
conversations[].events[].event_name |
string |
Agent/tool/model/event name. |
conversations[].events[].io_id |
string |
Event I/O row id. |
conversations[].events[].parent_id |
string |
Parent event id for child spans. |
conversations[].events[].timestamp |
string |
Event timestamp. |
conversations[].events[].latency |
integer |
Latency in milliseconds. |
conversations[].events[].success |
boolean |
True when the event succeeded. |
conversations[].events[].conversation_id |
string |
Conversation UUID. |
conversations[].events[].metadata |
object<string,string> |
Allowlisted pricing metadata: explicit cost, model/provider, and token fields. Nested SDK usage/response values are flattened to those pricing fields; the original blobs are not exposed. |
conversations[].events[].sentiments_match |
string[] |
Intent titles matched on the event. |
conversations[].events[].sops_violated |
string[] |
Violation titles matched by the event. |
conversations[].events[].input_args |
string |
Readable input text unless exclude_io:true. |
conversations[].events[].output_result |
string |
Readable output text unless exclude_io:true. |
user_summaries |
object[] |
Full filtered-history metrics for each user visible on the current ungrouped interactive page; omitted for grouped responses and empty for limited-preview responses. Optional aggregation failures degrade these fields to zero values. |
user_summaries[].key |
string |
Stable user:<user_id> key, or conversation:<conversation_id> for an anonymous conversation. |
user_summaries[].conversation_count |
integer |
Conversations for this user across the active timeline and filters. |
user_summaries[].message_count |
integer |
Distinct captured events across those conversations, including tool events. |
user_summaries[].intent_count |
integer |
Distinct event/intent matches across those conversations. |
user_summaries[].intent_labels |
string[] |
Up to 20 matched intent titles. |
user_summaries[].violation_count |
integer |
Distinct event/violation matches across those conversations. |
user_summaries[].violation_labels |
string[] |
Up to 20 matched violation titles. |
user_summaries[].cost_metadata |
object<string,string>[] |
Aggregated explicit-cost or model/provider token buckets for client-side pricing. |
page |
integer |
Applied page number. |
page_size |
integer |
Applied page size. |
total_pages |
integer |
Current page, plus one when a lookahead row proves a next page exists. |
has_more |
boolean |
True when another page is available. |
partial_data |
boolean |
True when optional hydration or enrichment failed and the returned page is incomplete. |
With group_by and group_level:"groups" (the grouped default), the response contains groups instead of conversations. Each group includes value, user_count, conversation_count, message_count, intent and violation counts/labels, last_active, and cost_metadata. The legacy message_count field counts distinct captured events, including tool events, and equals the sum shown for its child conversations. With group_level:"users", the response contains users with the same metrics plus an opaque key, user_id, label, and representative_conversation_id. Send that key as group_user_key with group_level:"conversations" to retrieve the user's conversations through the exact same group membership logic. Metadata arrays can place one conversation in more than one group.
Each cost_metadata entry is either an explicit USD cost bucket or a model/provider token bucket. Token buckets combine requests that share the same input-token count, expose that count as tokens.request_input, and use tokens.aggregated:"true"; clients should select any request-level pricing tier from tokens.request_input, then apply it to the aggregated token totals. pricing.invalid:"true" marks malformed numeric metadata. If an event has neither a valid explicit cost nor enough valid model/token data to price it, a computed total is incomplete.
Call:
curl -sS "https://api.voxmith.com/dashboard/api/user-stories" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"time_range":"1w","page":1,"page_size":15,"exclude_io":true}'Grouped metadata call:
curl -sS "https://api.voxmith.com/dashboard/api/user-stories" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"time_range":"1w","page":1,"page_size":15,"group_by":{"source":"user_metadata","key":"organization_id"},"group_level":"groups"}'
POST /dashboard/api/conversation-detail
Fetches one conversation's metadata, transcript messages, and full span tree.
Best for: Loading messages and trace spans when you already have a conversation_id.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
conversation_id |
Yes | None | Conversation UUID. |
event_id |
No | None | Passed to conversation-spans to focus spans around an event root subtree. |
load_io |
No | true |
Passed to conversation-messages; if false, omits message text. |
Response schema:
| Field | Type | Description |
|---|---|---|
conversation |
object or null |
Conversation metadata, or null if metadata lookup fails. |
conversation.created_at |
string |
Conversation creation timestamp when conversation is not null. |
conversation.id |
string |
Conversation UUID when conversation is not null. |
conversation.metadata |
object<string,string> |
Conversation metadata map when conversation is not null. |
conversation.user_id |
string |
Customer-provided user id. |
conversation.user_metadata |
object<string,any> |
Customer user metadata. |
messages |
object or null |
Transcript payload, or null if the messages subrequest fails. |
messages.conversation_id |
string |
Conversation UUID when messages is not null. |
messages.timestamp |
string |
Conversation creation timestamp string. |
messages.user_id |
string |
Customer-provided user id, or empty string. |
messages.messages |
object[] |
User-facing top-level transcript rows. |
messages.messages[].id |
string |
Event id for assistant/system rows; user input rows use {event_id}_input. |
messages.messages[].role |
string |
user, assistant, or system. |
messages.messages[].timestamp |
string |
Event timestamp. |
messages.messages[].latency |
integer |
Latency in milliseconds. User input rows use 0. |
messages.messages[].success |
boolean |
True when the event succeeded. User input rows use true. |
messages.messages[].message |
string |
Readable message text when load_io:true. |
messages.total_messages |
integer |
Number of returned transcript rows. |
spans |
object or null |
Span payload, or null if the spans subrequest fails. |
spans.conversation_id |
string |
Conversation UUID when spans is not null. |
spans.spans |
object[] |
Event/span rows for the full conversation or event-focused subtree. |
spans.spans[].id |
string |
Event/span id. |
spans.spans[].agent_name |
string |
Agent/tool/model/span name. |
spans.spans[].parent_id |
string |
Parent event id, or empty string for a root span. |
spans.spans[].timestamp |
string |
Event timestamp. |
spans.spans[].latency |
integer |
Latency in milliseconds. |
spans.spans[].success |
boolean |
True when the span succeeded. |
spans.spans[].event_metadata |
object<string,string> |
Event metadata map. Empty object when no metadata exists. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/conversation-detail" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"conversation_id":"'$CONVERSATION_ID'","load_io":true}'
POST /dashboard/api/conversation-messages
Returns the user-facing transcript for one conversation. Best for: Replaying the user-visible message flow without internal tool or model spans.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
conversation_id |
Yes | None | Conversation UUID. |
load_io |
No | true |
If true, resolves readable user input and assistant output. |
Response schema:
| Field | Type | Description |
|---|---|---|
conversation_id |
string |
Conversation UUID. |
timestamp |
string |
Conversation creation timestamp string. |
user_id |
string |
Customer-provided user id, or empty string. |
messages |
object[] |
User-facing top-level transcript rows. Child/tool/model spans are not included. |
messages[].id |
string |
Event id for assistant/system rows; user input rows use {event_id}_input. |
messages[].role |
string |
user, assistant, or system. |
messages[].timestamp |
string |
Event timestamp. |
messages[].latency |
integer |
Latency in milliseconds. User input rows use 0. |
messages[].success |
boolean |
True when the event succeeded. User input rows use true. |
messages[].message |
string |
Readable message when load_io:true. Text-only messages remain plain strings; multimodal messages use a versioned JSON string containing text and hosted image_url content blocks. |
total_messages |
integer |
Number of returned transcript rows. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/conversation-messages" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"conversation_id":"'$CONVERSATION_ID'","load_io":true}'
POST /dashboard/api/conversation-spans
Returns the event/span hierarchy for one conversation, including child spans. Best for: Debugging tool calls, model execution, latency, errors, and parent-child spans.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
conversation_id |
Yes | None | Conversation UUID. |
event_id |
No | None | If omitted, returns up to 500 spans for the conversation. If provided, walks up to the root ancestor and returns that root subtree. |
Response schema:
| Field | Type | Description |
|---|---|---|
conversation_id |
string |
Conversation UUID. |
spans |
object[] |
Event/span rows for the full conversation or event-focused subtree. |
spans[].id |
string |
Event/span id. |
spans[].agent_name |
string |
Agent/tool/model/span name. |
spans[].parent_id |
string |
Parent event id, or empty string for a root span. |
spans[].timestamp |
string |
Event timestamp. |
spans[].latency |
integer |
Latency in milliseconds. |
spans[].success |
boolean |
True when the span succeeded. |
spans[].event_metadata |
object<string,string> |
Event metadata map. Empty object when no metadata exists. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/conversation-spans" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"conversation_id":"'$CONVERSATION_ID'","event_id":"'$EVENT_ID'"}'
POST /dashboard/api/event-io
Fetches only the readable input and output for an exact event id.
Best for: Fetching readable input and output when you already have an event_id.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
event_id |
Yes | None | Event UUID. |
Response schema:
| Field | Type | Description |
|---|---|---|
input |
string or null |
Readable user/input text, or null if the event has no IO row/input. |
output |
string or null |
Readable assistant/output text, or null if the event has no IO row/output. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/event-io" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event_id":"'$EVENT_ID'"}'
POST /dashboard/api/raw-logs
Fetches raw event rows with optional metadata, agent, connection, success, and IO filters. Best for: Paginating raw events with metadata, status, latency, and optional input and output.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
time_range |
No | 30d |
Event timestamp window. Use all when looking up an event id with unknown timestamp. |
page |
No | 1 |
Page number. |
page_size |
No | 100, max 500 |
Event rows per page. Use 1 for exact event lookup. |
exclude_io |
No | false |
If false, includes input_args and output_result previews capped at 64 KiB per field; if true, returns event metadata without IO. Use /event-io for a full single-event payload. |
connection_type |
No | [] |
String or array. Filters conversation.metadata.transport_type. |
agent_name |
No | [] |
String or array. Filters event agent_name. |
client_config |
No | "" |
Filters conversation.metadata.client_config. |
success |
No | unset | If true, only success events. If false, any non-success events. |
metadata_filters |
No | [] |
Arbitrary metadata/user filters. Supports event_metadata, conversation_metadata, user_metadata, and user_id. |
Filter guidance:
- Use dedicated fields for
exclude_io,agent_name, andsuccess;metadata_filterscannot express those event columns or output-shaping options. connection_typeis equivalent tometadata_filters[{source:"conversation_metadata", key:"transport_type"}]; preferconnection_typefor this common filter.client_configis equivalent tometadata_filters[{source:"conversation_metadata", key:"client_config"}]; preferclient_configfor this common filter.- Use
metadata_filtersfor arbitrary event/conversation/user metadata keys anduser_id. - If dedicated filters and
metadata_filtersare both sent, the backend applies all of them with AND semantics.
Response schema:
| Field | Type | Description |
|---|---|---|
logs |
object[] |
Event rows matching the filters. |
logs[].event_id |
string |
Event UUID. |
logs[].conversation_id |
string |
Conversation UUID. |
logs[].event_type |
string |
Event primitive type. |
logs[].event_name |
string |
Agent/tool/model/event name. |
logs[].timestamp |
string |
Event timestamp. |
logs[].latency |
integer |
Latency in milliseconds. |
logs[].success |
boolean |
True when the event succeeded. |
logs[].input_args |
string |
Readable input preview, capped at 64 KiB, when exclude_io:false. |
logs[].output_result |
string |
Readable output preview, capped at 64 KiB, when exclude_io:false. |
logs[].checkpoints |
string |
Raw checkpoint metadata string when present. |
logs[].metadata |
string |
JSON string containing event metadata. |
logs[].parent_id |
string |
Parent event id for child spans. |
pagination |
object |
Pagination object. |
pagination.page |
integer |
Applied page number. |
pagination.page_size |
integer |
Applied page size. |
Call:
curl -sS "https://api.voxmith.com/dashboard/api/raw-logs" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"time_range":"all","page":1,"page_size":1,"exclude_io":false}'Ask Voxmith
POST /dashboard/api/run-spotlight-query
Runs an open-ended investigation from a natural-language question.
Best for: Questions that the deterministic intent, violation, conversation, and event endpoints cannot answer. Keep limit as small as possible.
Request:
| Field | Required | Default | Description |
|---|---|---|---|
question or query |
Yes | None | Natural-language investigation question. question is preferred. |
time_range |
No | 1w |
Default window the AskAI tool loop should use when choosing read-only analytics calls. |
limit |
No | 100, max 500 |
Default row/conversation limit for the AskAI tool loop. |
response_format |
No | Prose | Set to json when a report builder needs a machine-readable final answer. |
response_schema |
With response_format: json |
None | JSON object template, up to 4096 bytes, that guides the final answer's keys and value types. |
Response schema:
Output transport: text/event-stream. Decode SSE events. The final answer is sent in a chunk event as {"text": string}; completion metadata is sent in a done event. By default text is prose. With response_format: "json", text contains one compact JSON object synthesized from the template after Spotlight chooses and runs its read-only MCP tools.
SSE event payloads:
| Field | Type | Description |
|---|---|---|
event: tool_start |
{tool:string, stage:string} |
Emitted before a read-only internal tool call starts. |
event: tool_result |
{tool:string, ok:boolean, summary?:string, error?:string, evidence_ids?:object<string,string[]>} |
Emitted after an internal tool call finishes. |
event: chunk |
{text:string} |
Final answer text: prose by default, or a compact JSON object string when response_format: "json". Currently emitted as one final answer chunk. |
event: done |
{tool_count:integer, conversation_count:integer, total_checked:integer, total_relevant:integer, has_more:boolean, links:{label:string,url:string}[], conversation_ids:string[]} |
Completion metadata and openable evidence links. |
Call:
curl -N -sS "https://api.voxmith.com/dashboard/api/run-spotlight-query" \
-H "x-api-key: $VOXMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Find users who were frustrated because email drafting failed","time_range":"1w","limit":25}'Metadata filters
{
"metadata_filters": [
{
"source": "event_metadata | conversation_metadata | user_metadata | user_id",
"key": "metadata_key_optional_for_user_id",
"values": ["value-a", "value-b"]
}
]
}Next steps
- Authentication: create and use a Voxmith API key.
- Intents: understand the intent data returned by these APIs.
- Violations: review the violation model and workflow.