Analytics API Reference
Authentication
All public endpoints require authentication via a product token. Requests must include the token in the X-CM-PRODUCTTOKEN header:
X-CM-PRODUCTTOKEN: <product-token>
You can find your token for the Analytics endpoints by opening your HALO studio, selecting ‘Settings’ at the bottom left, and selecting ‘Account’. You will see this view:
Here, you can click on ‘Create Token’, create a name for your Token, and select the ‘Analytics’ type. Then, you will be given the Token you can use for the API. Please store the token in a secured location.
Base URL
https://api.cm.com/halo
Swagger: https://api.cm.com/halo/analytics/docs
Breaking Changes
The metrics, resources and get_conversation endpoints no longer use the envelope wrapper. Previously, responses were wrapped in:
{
"data": [],
"meta": {
"total_count": 0
},
"pagination": {
"page_size": 0,
"has_next": false,
"has_previous": false,
"next_cursor": null,
"previous_cursor": null
}
}
These endpoints now return the response body directly without the data, meta, and pagination wrapper.
The get_conversations endpoint is not affected by this change — it uses the envelope format with data, meta, and pagination fields.
Analytics v1
GET /analytics/v1/accounts/{account_id}/metrics
Retrieve aggregated conversation metrics for an account within a date range, optionally filtered by profile.
Path Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
UUID |
Yes |
The account ID |
Query Parameters
|
Parameter |
Type |
Required |
Default |
Description |
|---|---|---|---|---|
|
|
ISO 8601 datetime |
No |
30 days ago |
Start of the date range (UTC) |
|
|
ISO 8601 datetime |
No |
Now |
End of the date range (UTC) |
|
|
integer |
No |
— |
Filter metrics to a specific profile. Returns 404 if not found |
Validation
-
start_datemust be beforeend_date. Returns422 Unprocessable Entityif violated. -
If
profile_idis provided, the profile must exist. Returns404 Not Foundotherwise.
Response 200 OK
{
"total_conversations_count": 1520,
"total_average_conversation_duration_seconds": 145,
"total_average_interactions_per_conversation": 6.3,
"average_recognition_rate": 0.87,
"product_metrics": [
{
"product": "support-chat",
"conversations_count": 980,
"average_conversation_duration_seconds": 130,
"average_interactions_per_conversation": 5.8,
"average_recognition_rate": 0.91
}
]
}
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Total number of conversations in the date range |
|
|
integer |
Average conversation duration across all conversations (in seconds) |
|
|
float |
Average number of interactions (messages) per conversation |
|
|
float or null |
Average recognition rate across conversations (0.0–1.0) |
|
|
array or null |
Per-product breakdown (omitted if no products) |
Each entry in product_metrics:
|
Field |
Type |
Description |
|---|---|---|
|
|
string |
Product name |
|
|
integer |
Number of conversations for this product |
|
|
integer |
Average duration for this product (seconds) |
|
|
float |
Average interactions per conversation |
|
|
float or null |
Average recognition rate for this product |
Error Responses
|
Status |
Description |
|---|---|
|
400 |
Invalid query parameters |
|
404 |
Account or profile not found |
|
422 |
|
Analytics v2
GET /analytics/v2/accounts/{account_id}/conversations
List conversations for a profile with filtering, sorting, and pagination. Returns a paginated list of conversation overviews along with available filter options for the current date range.
Path Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
UUID |
Yes |
The account ID |
Query Parameters
|
Parameter |
Type |
Required |
Default |
Description |
|---|---|---|---|---|
|
|
integer |
No |
— |
The profile to list conversations for |
|
|
integer |
No |
— |
Number of days to look back from now. Overrides |
|
|
ISO 8601 datetime |
No |
7 days ago |
Start of the date range (UTC) |
|
|
ISO 8601 datetime |
No |
Now |
End of the date range (UTC) |
|
|
string (CSV) |
No |
— |
Filter by languages (e.g. |
|
|
string (CSV) |
No |
— |
Filter by channels |
|
|
string (CSV) |
No |
— |
Filter by products |
|
|
string (CSV) |
No |
— |
Filter by resolutions |
|
|
string (CSV) |
No |
— |
Filter by feedback values |
|
|
string |
No |
— |
Full-text search within conversation content |
|
|
float |
No |
— |
Minimum recognition rate filter (0–100) |
|
|
float |
No |
— |
Maximum recognition rate filter (0–100) |
|
|
string (CSV) |
No |
— |
Filter by agent IDs (comma-separated integers) |
|
|
string (CSV) |
No |
— |
Filter by tool IDs (comma-separated integers) |
|
|
string (CSV) |
No |
— |
Filter by topic IDs (comma-separated integers, use |
|
|
boolean |
No |
— |
|
|
|
integer |
No |
1000 |
Number of conversations per page (clamped to 1–1000) |
|
|
integer |
No |
0 |
0-based page index |
|
|
string |
No |
|
Sort order: |
|
|
string |
No |
|
Sort field: |
Date Range Behavior
-
If
duration_filter_in_daysis provided, it takes precedence:from_date= now minus N days,until_date= now. -
If neither
duration_filter_in_daysnorfrom_date/until_dateare provided, defaults to the last 7 days. -
If only
from_dateoruntil_dateis provided, the other remains open-ended.
Pagination
This endpoint uses offset-based pagination via page_index and page_size query parameters. The response includes pagination metadata in nested meta and pagination objects:
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Total number of conversations matching the filters |
|
|
integer |
Requested page size |
|
|
boolean |
Whether there is a next page |
|
|
boolean |
Whether there is a previous page |
|
|
string or null |
Reserved for cursor-based pagination (currently |
|
|
string or null |
Reserved for cursor-based pagination (currently |
To iterate through pages, increment page_index and check pagination.has_next.
Response 200 OK
{
"data": [],
"possible_language_filters": ["en", "nl", "de"],
"possible_product_filters": ["support-chat", "sales-chat"],
"possible_channel_filters": ["web", "whatsapp"],
"meta": {
"total_count": 342
},
"pagination": {
"page_size": 100,
"has_next": true,
"has_previous": false,
"next_cursor": null,
"previous_cursor": null
}
}
|
Field |
Type |
Description |
|---|---|---|
|
|
array |
List of |
|
|
string array |
All distinct languages available in the current date range |
|
|
string array |
All distinct products available in the current date range |
|
|
string array |
All distinct channels available in the current date range |
|
|
object |
Response metadata |
|
|
integer |
Total number of conversations matching the filters |
|
|
object |
Pagination details |
|
|
integer |
Requested page size |
|
|
boolean |
Whether there is a next page |
|
|
boolean |
Whether there is a previous page |
|
|
string or null |
Reserved for future cursor-based pagination |
|
|
string or null |
Reserved for future cursor-based pagination |
ConversationOverview Object
Each item in data represents a summary of a single conversation.
|
Field |
Type |
Description |
|---|---|---|
|
|
UUID |
Unique conversation identifier |
|
|
integer or null |
Profile the conversation belongs to |
|
|
datetime or null |
When the conversation record was created |
|
|
datetime or null |
When the first message was exchanged |
|
|
datetime or null |
When the conversation ended |
|
|
string or null |
The first message sent by the user |
|
|
string or null |
Dominant language (2-character ISO code) |
|
|
string or null |
Most common origin/source |
|
|
string or null |
Most common channel (e.g. |
|
|
string or null |
Most common product |
|
|
string or null |
Environment the conversation ran in (e.g. |
|
|
integer |
Number of user messages that were successfully recognized |
|
|
integer |
Total number of user messages |
|
|
float |
Ratio of matched to total items (0.0–1.0) |
|
|
integer array |
IDs of agents that handled the conversation |
|
|
integer array |
IDs of tools that were invoked during the conversation |
|
|
string or null |
Resolution status (see https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Resolutions ) |
|
|
string or null |
AI-generated reasoning for the resolution classification |
|
|
string or null |
AI-generated conversation summary |
|
|
string |
User feedback rating (see https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Feedback) |
|
|
string or null |
Free-text comment left with feedback |
|
|
object or null |
Assigned topic (see https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Topics) |
|
|
object or null |
Assigned subtopic (see https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Subtopics) |
|
|
object or null |
Manual resolution override (see https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Manual-Resolutions) |
|
|
object or null |
Handover metadata if conversation was transferred to a human agent |
|
|
array |
Simplified message list (see https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Messages) |
GET /analytics/v2/accounts/{account_id}/conversations/{conversation_id}
Retrieve a single conversation by ID with full calculated analytics, including detailed message history.
Path Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
UUID |
Yes |
The account ID |
|
|
UUID |
Yes |
The conversation ID |
Response 200 OK
{
"most_common_channel": "web",
"most_common_language": "en",
"most_common_origin": "website",
"most_common_product": "support-chat",
"started": "2025-01-15T10:30:00Z",
"ended": "2025-01-15T10:45:00Z",
"total_user_items": 8,
"num_matched_user_items": 7,
"recognition_rate": 0.875,
"messages": [],
"resolution": "RESOLUTION_SUCCESSFUL",
"resolution_reasoning": "The user's question was answered completely.",
"summary": "User asked about order status and received tracking info.",
"feedback": "FEEDBACK_SATISFIED",
"version": 2,
"visited_agent_ids": [1, 3],
"visited_tool_ids": [2],
"topic": { "id": 5, "name": "Order Status", "definition": "Questions about order tracking and delivery" },
"subtopic": { "id": 12, "name": "Tracking", "definition": "Requests for tracking information" },
"manual_resolution": null
}
|
Field |
Type |
Description |
|---|---|---|
|
|
string or null |
Dominant channel |
|
|
string or null |
Dominant language |
|
|
string or null |
Dominant origin |
|
|
string or null |
Dominant product |
|
|
datetime |
Conversation start time |
|
|
datetime |
Conversation end time |
|
|
integer |
Total number of user messages |
|
|
integer |
Number of recognized user messages |
|
|
float |
Recognition rate (0.0–1.0) |
|
|
array |
Full message history with detailed content (see https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Message-Types) |
|
|
string |
Resolution status |
|
|
string or null |
AI reasoning for resolution |
|
|
string or null |
AI-generated summary |
|
|
string |
User feedback rating |
|
|
integer |
Response format version (currently |
|
|
integer array |
Agent IDs visited |
|
|
integer array |
Tool IDs invoked |
|
|
object or null |
Assigned topic |
|
|
object or null |
Assigned subtopic |
|
|
object or null |
Manual resolution override, if any |
Error Responses
|
Status |
Description |
|---|---|
|
404 |
Conversation not found, or conversation has no items/metadata |
Analytics v1 — Resources
These endpoints return the available agents and tools for an account. They are used to populate filter options in analytics UIs.
Note: For profiles, use the Core API profiles endpoint at
/core/v1/accounts/{account_id}/profiles(permission:HALO.Core_Profiles_Read).
GET /analytics/v1/accounts/{account_id}/agents
Retrieve agents for an account, optionally filtered by profile.
Path Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
UUID |
Yes |
The account ID |
Query Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
integer |
No |
Filter agents by profile ID |
Response 200 OK
[
{ "id": 1, "name": "Sales Agent" },
{ "id": 2, "name": "Support Agent" }
]
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Agent ID |
|
|
string |
Agent name |
Error Responses
|
Status |
Description |
|---|---|
|
400 |
Invalid account ID |
|
404 |
Account not found |
|
500 |
Internal server error |
GET /analytics/v1/accounts/{account_id}/tools
Retrieve tools for an account, optionally filtered by profile.
Permission: HALO.Analytics_API
Path Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
UUID |
Yes |
The account ID |
Query Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
integer |
No |
Filter tools by profile ID |
Response 200 OK
[
{ "id": 1, "name": "Knowledge Search", "description": "Searches the knowledge base" },
{ "id": 2, "name": "Order Lookup", "description": "Looks up order status" }
]
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Tool ID |
|
|
string |
Tool name |
|
|
string |
Tool description |
Error Responses
|
Status |
Description |
|---|---|
|
400 |
Invalid account ID |
|
404 |
Account not found |
|
500 |
Internal server error |
Content Types
Messages
Messages in the conversation list endpoint (ConversationItemSummary) are a simplified view:
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Item ID |
|
|
integer or null |
Profile ID |
|
|
UUID or null |
Interaction ID |
|
|
string or null |
Message role (e.g. |
|
|
string or null |
Sender name |
|
|
string or null |
Plain text content of the message |
|
|
boolean or null |
Whether the message was recognized |
|
|
string or null |
Detected language |
|
|
datetime or null |
Timestamp |
|
|
object or null |
Carousel content (only present if the message contains one) |
|
|
array or null |
Media attachments (images, files) |
|
|
array or null |
Conversation option buttons |
|
|
string or null |
Feedback prompt text |
|
|
array or null |
Structured JSON content |
Messages in the single conversation detail endpoint use the full Message type, which is a tagged union with the following variants: USER, HALO, ASSISTANT, CUSTOMER_SERVICE_AGENT, CUSTOMER_SERVICE_AGENT_INSTRUCTION, and EXTERNAL_HANDOVER. Each variant contains content parts that can be of type text, json, media, buttons, image_carousel, or show_feedback.
Topics
Topics represent the subject matter of a conversation, classified automatically by AI analysis of the conversation content. They form the parent level of a two-level taxonomy representing broad subject areas (e.g. "Billing", "Technical Support", "Account Management").
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Topic ID |
|
|
string |
Human-readable topic name |
|
|
string |
Description of what the topic covers |
Use the topic_ids query parameter in the conversations list endpoint to filter by topic. A value of -1 matches conversations where topic classification is still pending.
Subtopics
Subtopics are child categories within a topic, providing more granular classification. They represent specific subjects within a broader topic area (e.g. under "Billing": "Invoice Dispute", "Payment Method", "Refund Request"). Every classified conversation has a subtopic; the parent topic is derived from the subtopic's position in the taxonomy.
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Subtopic ID |
|
|
string |
Human-readable subtopic name |
|
|
string |
Description of what the subtopic covers |
Resolutions
Resolution indicates the outcome of a conversation. It is determined using the following priority order:
-
External handover — if the conversation was handed over to a human agent, it is automatically classified as
RESOLUTION_HANDOVER. -
Manual resolution — if an analyst has manually overridden the resolution, the manual label takes precedence.
-
AI resolution — if neither of the above apply, the AI-determined resolution is used.
-
Pending — if none of the above are available, the resolution defaults to
RESOLUTION_PENDING.
|
Value |
Description |
|---|---|
|
|
The user's question or request was resolved successfully |
|
|
The conversation was transferred to a human agent |
|
|
The conversation ended without the user's issue being resolved |
|
|
The AI could not confidently determine the outcome |
|
|
Resolution has not yet been classified (e.g. conversation is still ongoing or classification is pending) |
The resolution_reasoning field (string or null) contains the AI's explanation of why it assigned a particular resolution label. This is only present when the resolution was determined by AI.
Manual Resolutions
A manual resolution is an override applied by an analyst or reviewer to correct or adjust the AI-assigned resolution. When a manual resolution is active, it takes precedence over the AI resolution in the priority chain described above.
|
Field |
Type |
Description |
|---|---|---|
|
|
integer |
Manual resolution record ID |
|
|
integer or null |
Profile ID the resolution was applied to |
|
|
UUID |
Conversation this resolution applies to |
|
|
string or null |
Name of the user who applied the override |
|
|
string or null |
The resolution label before the override (null if no prior label existed) |
|
|
string |
The new resolution label applied by the reviewer |
|
|
string or null |
Free-text explanation of why the resolution was changed |
|
|
boolean |
Whether this manual resolution is currently active |
|
|
datetime |
When the manual resolution was created |
|
|
string |
Email of the user who applied the override |
original_label can be any value from the https://cmcom.atlassian.net/wiki/spaces/KCENTER/pages/edit-v2/2925264909#Resolutions section (or null if no prior label existed). new_label is restricted to:
-
RESOLUTION_SUCCESSFUL -
RESOLUTION_UNSUCCESSFUL
Feedback
Feedback represents the end-user's satisfaction rating for a conversation, mapped from a 1–5 numeric score.
|
Value |
Numeric Score |
Description |
|---|---|---|
|
|
5 |
Very satisfied |
|
|
4 |
Satisfied |
|
|
3 |
Neutral |
|
|
2 |
Unsatisfied |
|
|
1 |
Very unsatisfied |
|
|
— |
No feedback provided |
Message Types
The single conversation detail endpoint returns full message objects. Each message is a tagged union with a type field:
|
Type |
Description |
|---|---|
|
|
Message from the end user |
|
|
AI assistant response with full reasoning and metadata |
|
|
Generic assistant message |
|
|
Message from a human customer service agent |
|
|
Instruction message from a customer service agent |
|
|
Handover event with transfer details |
All message types share a common base containing content (array of content parts), timestamp, is_message_before_halo, and interaction_id.