curl --request GET \
--url https://api.eqho.ai/v2/reports/metrics \
--header 'X-API-KEY: <api-key>' \
--header 'x-org-id: <api-key>'import requests
url = "https://api.eqho.ai/v2/reports/metrics"
headers = {
"X-API-KEY": "<api-key>",
"x-org-id": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>', 'x-org-id': '<api-key>'}};
fetch('https://api.eqho.ai/v2/reports/metrics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.eqho.ai/v2/reports/metrics"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("x-org-id", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"metrics": {},
"filters_applied": {
"created_gte": "2023-11-07T05:31:56Z",
"created_lt": "2023-11-07T05:31:56Z",
"account_id": "<string>",
"time_granularity": "hour",
"group_by_dimension": "campaign",
"campaign_ids": [
"<string>"
],
"agent_ids": [
"<string>"
],
"disposition_level_3": [
"<string>"
],
"conversation_mediums": [
"web_voice"
],
"call_types": [
"outbound"
],
"twilio_statuses": [
"queued"
],
"is_dry_run": true
},
"metadata": {
"generated_at": "2023-11-07T05:31:56Z",
"total_records_analyzed": 123,
"generation_time_ms": 123,
"errors": [
"<string>"
],
"partial_results": false
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Get Metrics
Get analytics metrics with optional granularity and grouping
Available Metrics:
Efficiency:
autonomous_containment_rate- Percentage of conversations resolved without human interventionhuman_transfer_rate- Percentage of conversations transferred to human agentsconversions- Total number of conversions (disposition.conversion=True)conversion_rate- Percentage of conversations that converted (call-based)lead_conversion_rate- Percentage of unique leads that converted (lead-based, useful for outbound sales)contact_rate- Percentage of conversations where contact was made (call-based)lead_contact_rate- Percentage of unique leads contacted (lead-based, useful for outbound sales)
Quality:
average_latency_e2e- End-to-end response latency (total time)average_latency_stt- Speech-to-text processing latencyaverage_latency_ai- AI processing latencyaverage_latency_tts- Text-to-speech processing latency
Volume:
total_conversations- Total number of conversation sessionsunique_leads_contacted- Count of distinct leads contacted (by lead_id)first_time_contacts- Count of leads contacted for the first time (call_count=1)average_conversation_duration- Average length of conversations
Cost:
total_credits_spent- Total credits consumed across all conversations
Conversation Dynamics:
average_user_talk_time- Average seconds the caller spoke per callaverage_agent_talk_time- Average seconds the agent spoke per calluser_to_agent_talk_ratio- Ratio of total user talk-time to total agent talk-time (period-aggregated, not the average of per-call ratios)average_total_silence- Average seconds of silence per call (neither speaker active)average_longest_silence- Average length of the longest single silence per callaverage_silence_frequency- Average count of silences over 3s per minute of conversationaverage_words_per_agent_response- Average word count per non-seeded assistant message
Grouping:
time_granularity- Time bucket for aggregation: hour, day, week, month, yeargroup_by_dimension- Combine time series with dimensional breakdown- Values: campaign, agent, disposition, conversation_medium, call_type
- When used with
time_granularity, each time point includes a breakdown array - Example: Track campaign performance over time in a single query
Filters:
campaign_ids- Filter by specific campaign IDs (comma-separated)agent_ids- Filter by specific agent IDs (comma-separated)disposition_level_3- Filter by level 3 disposition names (comma-separated)conversation_mediums- Filter by channel: telephony, web_voice, sms, chatbot, emailcall_types- Filter by call direction: inbound, outboundtwilio_statuses- Filter by call status (default: all statuses included)- NOTE: For telephony/web_voice, ‘completed’ indicates successful calls
- For chatbot/email/SMS, conversations occur regardless of status
- To get telephony-only metrics, use:
?twilio_statuses=completed&conversation_mediums=telephony
is_dry_run- Filter by dry-run status: true (only dry-runs), false (exclude dry-runs), omit (all calls, default)- NOTE: Some organizations bill dry-run calls, so the default includes all calls for accurate reporting
Examples:
# All metrics
?metrics=autonomous_containment_rate,human_transfer_rate,average_latency_e2e,total_conversations,average_conversation_duration,unique_leads_contacted,first_time_contacts,conversions,conversion_rate,lead_conversion_rate,contact_rate,lead_contact_rate,total_credits_spent
# Lead volume analysis
?metrics=unique_leads_contacted,first_time_contacts&time_granularity=day&created_gte=2024-01-01
# Outbound sales: Compare call-based vs lead-based metrics
?metrics=contact_rate,lead_contact_rate,conversion_rate,lead_conversion_rate&call_types=outbound&time_granularity=day
# Multi-dimensional time series (campaign performance over time)
?metrics=unique_leads_contacted,conversions&time_granularity=day&group_by_dimension=campaign&created_gte=2024-01-01
# Returns time series where each point contains breakdown by campaign
# Campaign comparison over time
?metrics=total_conversations,conversion_rate&time_granularity=week&group_by_dimension=campaign
# See how each campaign performs week-over-week in single response
# Filter by specific level 3 dispositions
?metrics=total_conversations,conversion_rate&disposition_level_3=Interested,Converted&time_granularity=day
# For telephony-only view, explicitly filter:
?metrics=total_conversations&twilio_statuses=completed&conversation_mediums=telephony&is_dry_run=false
# Get all conversations including chatbot:
?metrics=total_conversations&time_granularity=day
# Conversation dynamics dashboard
?metrics=average_user_talk_time,average_agent_talk_time,user_to_agent_talk_ratio,average_silence_frequency&time_granularity=day
curl --request GET \
--url https://api.eqho.ai/v2/reports/metrics \
--header 'X-API-KEY: <api-key>' \
--header 'x-org-id: <api-key>'import requests
url = "https://api.eqho.ai/v2/reports/metrics"
headers = {
"X-API-KEY": "<api-key>",
"x-org-id": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>', 'x-org-id': '<api-key>'}};
fetch('https://api.eqho.ai/v2/reports/metrics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.eqho.ai/v2/reports/metrics"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("x-org-id", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"metrics": {},
"filters_applied": {
"created_gte": "2023-11-07T05:31:56Z",
"created_lt": "2023-11-07T05:31:56Z",
"account_id": "<string>",
"time_granularity": "hour",
"group_by_dimension": "campaign",
"campaign_ids": [
"<string>"
],
"agent_ids": [
"<string>"
],
"disposition_level_3": [
"<string>"
],
"conversation_mediums": [
"web_voice"
],
"call_types": [
"outbound"
],
"twilio_statuses": [
"queued"
],
"is_dry_run": true
},
"metadata": {
"generated_at": "2023-11-07T05:31:56Z",
"total_records_analyzed": 123,
"generation_time_ms": 123,
"errors": [
"<string>"
],
"partial_results": false
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}time_series to build period rows. All buckets intersecting
[created_gte, created_lt) are included, cut in timezone (an IANA name) with
Monday-based weeks. When omitted, timezone defaults to the organization’s
reporting time zone, or UTC if none is configured. An explicit timezone
overrides the organization setting. Each timestamp is the UTC instant the
period starts, e.g. 2026-09-22T04:00:00Z for September 22 in America/New_York.
Missing buckets have value: 0 for counts and totals, value: null for rates
and averages, and breakdown: []. The first bucket can start before
created_gte when the requested range begins partway through a period.
Add breakdown_by=disposition to get disposition counts on each
total_conversations time point:
{
"timestamp": "2026-09-01T00:00:00Z",
"value": 12,
"components": { "not_engaged": 7, "converted": 3 }
}
group_by_dimension=campaign (or another supported dimension) each
breakdown item carries its own counts as well, and the point’s components
sums them:
{
"dimension_value": "campaign-id",
"dimension_label": "Sales",
"value": 12,
"count": 12,
"components": { "not_engaged": 7, "converted": 3 }
}
custom_fields[key]=value filters every metric to conversations whose custom
field holds exactly that string, the same way GET /v1/calls does, so a
drill-down lists the conversations a cell counted. Several pairs must all match.
Helper calls are excluded. Rate denominators remain unchanged; use each rate
point’s denominator for the Dispositioned column. For exact call drill-downs,
GET /v1/calls accepts disposition_contacted and disposition_conversion.
Both accept true or false; omitting a flag applies no filter for that flag.
Requests with more than 30 metric IDs return HTTP 400. Each aggregation uses
the ANALYTICS_MAX_TIME_MS server setting (default: 30000 milliseconds).Authorizations
Your API key for authentication.
Org impersonation via x-org-id. Superadmins may impersonate any org; admins may impersonate their direct sub-organizations. Enter the target organization ID to act as that org.
Query Parameters
Comma-separated list of metric IDs. Call GET /v2/reports/metrics/available to discover the IDs this account can request. Any unknown or not-enabled ID rejects the whole request with 400.
1Show conversations that started on or after this datetime (inclusive). Must be in UTC using ISO 8601 format (e.g., 2025-07-05T00:00:00Z). Defaults to 7 days ago.
Show conversations that started before this datetime (exclusive). Must be in UTC using ISO 8601 format (e.g., 2025-07-05T23:59:59Z). Defaults to now.
Account ID to filter by
Time bucket for aggregation. When omitted, only current values are calculated (no time series).
hour, day, week, month, year Dimension to include WITHIN time series.
campaign, agent, disposition, conversation_medium, call_type Comma-separated list of campaign IDs to filter by
Comma-separated list of agent IDs to filter by
Comma-separated list of level 3 disposition names to filter by
Comma-separated list of conversation mediums to filter by.
web_voice, telephony, sms, email, chatbot, api_text, chat_app, softphone Comma-separated list of call types to filter by.
outbound, inbound Comma-separated list of Twilio call statuses to filter by. When omitted, includes all statuses. Note: For telephony/web_voice, 'completed' typically indicates a successful call, but for chatbot/email/SMS, conversations occur regardless of status.
queued, initiated, ringing, in-progress, completed, busy, failed, no-answer, canceled, voicemail Filter by dry-run status. True=only dry-runs, False=exclude dry-runs, None=include all (default). Note: Some organizations bill dry-run calls, so excluding them may underreport actual usage.
Include trend comparison with previous period (calculates change_value, change_percent, trend direction)
Response
Successful Response
Was this page helpful?