Analytics & Reports API
These read-only endpoints let you pull your account’s activity into your own dashboards and reports: message-event counts, credit consumption, AI spend, and the same charts and insights the in-app dashboard shows. This guide covers:
- Summary — message-volume counters (sent, delivered, read, replied, booked, contacts created, credits).
- Credits — a detailed, paginated ledger of credit usage with totals and breakdowns.
- AI cost — a per-day rollup of AI spend.
- Metric series — a chart-ready time series for one or more metrics, grouped by campaign, channel, AI Agent, or number.
- Conversation outcomes — conversations over time, grouped by the contact tags they carry (the closing tags your agent applies).
- Conversation costs: the average credit cost of a conversation the AI handled alone versus one your team stepped into.
- Dashboard insights and Dashboard AI insights — the full data behind the in-app dashboard, including AI-written summaries.
- Entity activity — a single contact’s, deal’s, or task’s timeline.
- Aggregated event counts — a legacy, camelCase form of Summary kept for existing integrations.
Every endpoint on this page needs an exact scope, not both: pass at most one of campaign_id (legacy) or agent_id where the endpoint accepts it. Sending both returns 400, and an id that is not on your account returns 404 rather than 403, so other accounts’ ids stay unguessable.
Only two endpoints filter by contact tag.
tag_ids(withtag_match) is honoured by Dashboard insights and Aggregated event counts — those are the two the in-app dashboard’s All tags filter uses. Summary, Metric series and Conversation outcomes validate the parameter (a malformed id list still returns400) but do not apply it: you get account-wide numbers back, with no error to tell you so. Don’t read an unfiltered total as a tag-filtered one.
All paths below are relative to the API base URL:
https://api.youraiconnector.com/v1
Every request must be authenticated. See Authentication for the four accepted methods. The examples here use the X-API-Key header (and one query-parameter form for cURL).
Date range
All three endpoints accept the same optional date filters:
| Parameter | Description |
|---|---|
from |
Start of the range, YYYY-MM-DD, inclusive. Defaults to 30 days ago. |
to |
End of the range, YYYY-MM-DD, inclusive. Defaults to today. |
Dates are interpreted in UTC. The range defaults to the last 30 days and is capped at 366 days — a wider range returns 400. from must not be after to.
The truncated flag
The Summary and Credits endpoints cap how many records a single request scans. If your range is busy enough to hit that cap, the response includes "truncated": true. When you see it, the numbers are based on a partial scan — narrow your date range (or page through with a smaller window) to get complete figures.
Note: Cost and token figures are only included for AI calls billed to your own provider API keys. When cost figures are hidden for your account, the response sets "costs_redacted": true and the cost fields are returned as zero.
Message volume summary
Returns aggregated message-event counters for your account, both as range totals and as a per-day series. Every day in the range appears in by_date — quiet days are zero-filled. Optionally filter to a single campaign with campaign_id.
GET /analytics/summary
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. |
to |
No | Range end, YYYY-MM-DD. |
campaign_id |
No | Only count events belonging to this campaign. |
cURL
curl "https://api.youraiconnector.com/v1/analytics/summary?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/summary?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/summary",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"totals": {
"total": 1240,
"sent": 800,
"delivered": 760,
"read": 540,
"replied": 210,
"booked": 35,
"contact_created": 120,
"credits_spent": 412.5,
"credits_recharged": 500
},
"by_date": [
{
"date": "2026-05-01",
"total": 40,
"sent": 25,
"delivered": 24,
"read": 18,
"replied": 7,
"booked": 1,
"contact_created": 4,
"credits_spent": 13.5,
"credits_recharged": 0
}
],
"truncated": false
}
Each entry in by_date has the same counter fields as totals, plus a date.
If you pass a campaign_id that does not belong to your account, the response is 404 with { "success": false, "error": "Campaign not found" }.
Credit usage
Returns credit usage over the range: a paginated list of individual records, plus range totals and breakdowns by reason and by campaign.
GET /analytics/credits
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. |
to |
No | Range end, YYYY-MM-DD. |
campaign_id |
No | Only include usage attributed to this campaign. |
limit |
No | Page size for records, 1–100. Defaults to 50. |
cursor |
No | Pass the previous page’s next_cursor to fetch the next page. |
Adjustments vs. consumption: Balance changes such as bonuses, plan renewals, and corrections are excluded from
totalsand the breakdowns — they are not real consumption. They still appear in therecordslist, flagged with"is_adjustment": true.
Totals and breakdowns appear only on the first page (when no cursor is supplied). On later pages, totals, by_reason, by_reason_cost, and by_campaign are returned as null — only the records array continues. This avoids re-scanning the whole range for every page.
cURL
curl "https://api.youraiconnector.com/v1/analytics/credits?from=2026-05-01&to=2026-05-31&limit=50&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({
from: "2026-05-01",
to: "2026-05-31",
limit: "50",
});
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/credits?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
// To page: pass data.next_cursor as ?cursor on the next request, until it is null.
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/credits",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31", "limit": 50},
)
data = res.json()
# To page: pass data["next_cursor"] as cursor on the next request, until it is None.
Response (first page)
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"totals": {
"credits_used": 412.5,
"cost_usd": 1.284512,
"records": 318
},
"by_reason": {
"AI Message": 380.0,
"Campaign Message": 32.5
},
"by_reason_cost": {
"AI Message": 1.284512,
"Campaign Message": 0
},
"by_campaign": {
"Spring Promo": 250.0,
"Reactivation": 162.5
},
"records": [
{
"id": "rec_abc123",
"amount": 1,
"timestamp": "2026-05-31T14:02:11.000Z",
"reason": "AI Message",
"is_adjustment": false,
"campaign_id": "campaign123",
"campaign_name": "Spring Promo",
"contact_id": "contact456",
"contact_name": "Jane Smith",
"credit_type": "ai",
"custom_keys_used": false,
"description": null,
"cost_usd": 0,
"input_tokens": 0,
"output_tokens": 0,
"cache_read_tokens": 0,
"cache_creation_tokens": 0,
"ai_model": null,
"request_id": null,
"is_test": false
}
],
"next_cursor": "rec_abc123",
"costs_redacted": false,
"truncated": false
}
Field notes:
amount— credits charged for the record. Zero for records billed to your own provider API key.is_adjustment—truefor balance changes (excluded from totals/breakdowns).cost_usd,input_tokens,output_tokens,cache_read_tokens,cache_creation_tokens,ai_model,request_id— populated only on records billed to your own provider API key; zero ornullotherwise.is_test—truefor playground/test runs, which are never billed.next_cursor— the cursor for the next page, ornullwhen there are no more records.
Credit balance
GET /users/me/credits — your account’s current credit position in one call: what is left to spend, the monthly allowance, and the auto-recharge and low-credit settings. Credit usage above is a history; this is the balance right now. Team members calling it need billing access; the account owner’s key always has it.
curl "https://api.youraiconnector.com/v1/users/me/credits?apiKey=YOUR_API_KEY"
const res = await fetch("https://api.youraiconnector.com/v1/users/me/credits", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const { balance } = await res.json();
Response (200)
{
"success": true,
"balance": 1837.5,
"monthly_credits": 2000,
"used_this_month": null,
"auto_recharge_enabled": true,
"low_credit_threshold": null
}
| Field | Meaning |
|---|---|
balance |
Credits left to spend — the same number the Credits card shows. |
monthly_credits |
The plan’s monthly allowance, or null when the account has none. |
used_this_month |
Credits spent this month for an allocation (agency sub-) account; null for a regular account — use Credit usage for that. |
auto_recharge_enabled |
Whether auto-recharge is switched on. |
low_credit_threshold |
The balance at which the low-credit webhook fires, or null when the default applies. |
Agencies can pass sub_account_id to read a client account’s balance. Inside an automation, the Check credits step returns the same fields.
AI cost rollup
Returns the per-day AI spend rollup for your account. This reads pre-aggregated daily totals, so it is fast even over long ranges. Every day in the range appears in days — quiet days are zero-filled.
GET /analytics/ai-cost
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. |
to |
No | Range end, YYYY-MM-DD. |
cURL
curl "https://api.youraiconnector.com/v1/analytics/ai-cost?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/ai-cost?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/ai-cost",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"totals": {
"total_usd": 12.4821,
"byok_usd": 12.4821,
"platform_usd": 0,
"calls": 4210
},
"days": [
{
"date": "2026-05-01",
"total_usd": 0.4012,
"byok_usd": 0.4012,
"platform_usd": 0,
"input_usd": 0.18,
"output_usd": 0.19,
"cache_creation_usd": 0.02,
"cache_read_usd": 0.0112,
"calls": 140,
"by_provider": { "anthropic": 0.4012 }
}
],
"costs_redacted": false
}
Field notes:
byok_usd— spend billed to your own provider API keys.platform_usd— the portion of spend that ran on the platform rather than your own key.input_usd,output_usd,cache_creation_usd,cache_read_usd— the cost components that make uptotal_usd.by_provider— USD spend keyed by AI provider name.- USD figures are only returned to accounts that use their own provider key. For credit-paying accounts every USD field is zero and
costs_redactedistrue(call counts stay visible).
Metric series
Returns one or more metric time series in one call, optionally grouped by up to two dimensions — the endpoint to bind a chart to. A single request can answer “sent and replied per day, per channel, for this campaign” without one call per campaign.
GET /analytics/series
Every response carries a labels array (the time axis, zero-filled across the whole range) and one entry in series per group, each holding one array per requested metric aligned to labels. Series past limit are not dropped — they collapse into other_bucket, computed as the range total minus the returned series, so a rendered chart always adds up to your real numbers; truncated is true whenever that happens.
Where the numbers come from: sent, delivered, read, and replied come from message records, which carry the channel and sending number. booked, contact_created, and credits_spent come from the event stream, which carries no sending number, so those metrics land in the null-number bucket when you group by number.
conversations counts the conversations (chat sessions) that started in each bucket, and conversation_credits what those conversations cost, counted exactly like Conversation costs. Divide one by the other per bucket for the average cost per conversation over time. When you group or filter by campaign, agent, channel or number, a conversation counts toward the one its first message belongs to.
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. Defaults to 30 days ago. |
to |
No | Range end, YYYY-MM-DD. Defaults to today. |
metrics |
No | Comma-separated list from sent, ai_sent, human_sent, automated_sent, delivered, read, replied, booked, contact_created, credits_spent, conversations, conversation_credits. Defaults to sent,replied. An unknown metric returns 400. |
group_by |
No | Comma-separated list of up to two dimensions from date, campaign, channel, agent, number. date is accepted but has no effect — every response already carries the time axis. Omit for a single account-wide series. |
granularity |
No | day (default), week, or month. Week buckets start on Monday, month buckets on the 1st. |
limit |
No | How many series to return before the rest collapse into other_bucket, 1–50. Defaults to 12. |
campaign_id |
No | Only count activity belonging to this campaign. Legacy; prefer agent_id. |
agent_id |
No | Only count activity belonging to this AI Agent. |
channel |
No | Only count activity on this channel, for example whatsapp. |
This endpoint’s date range is capped at 92 days (tighter than the 366-day cap used elsewhere on this page).
cURL
curl "https://api.youraiconnector.com/v1/analytics/series?from=2026-05-01&to=2026-05-31&metrics=sent,replied,booked&group_by=campaign,channel&limit=10&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({
from: "2026-05-01",
to: "2026-05-31",
metrics: "sent,replied,booked",
group_by: "campaign,channel",
limit: "10",
});
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/series?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/series",
headers={"X-API-Key": "YOUR_API_KEY"},
params={
"from": "2026-05-01",
"to": "2026-05-31",
"metrics": "sent,replied,booked",
"group_by": "campaign,channel",
"limit": 10,
},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"granularity": "day",
"labels": ["2026-05-01", "2026-05-02"],
"group_by": ["campaign", "channel"],
"metrics": ["sent", "replied", "booked"],
"series": [
{
"key": {
"campaign_id": "campaign123",
"campaign_name": "Spring Promo",
"channel": "whatsapp"
},
"total": 812,
"metrics": {
"sent": [40, 35],
"replied": [12, 9],
"booked": [2, 1]
}
}
],
"other_bucket": {
"series_count": 6,
"total": 340,
"metrics": {
"sent": [18, 20],
"replied": [5, 6],
"booked": [0, 1]
}
},
"truncated": true
}
Field notes:
key— the identity of one series. Only the keys for the requestedgroup_bydimensions are present; a dimension whose value is unknown for a row (a message with no campaign, an event with no channel) comes back asnullrather than being dropped, so series still add up to the totals.other_bucket—nullwhen nothing was collapsed.- This endpoint returns
503with"error_code": "analytics_unavailable"when the reporting database cannot answer for your account, rather than a200full of zeros — a zeroed chart would read as fact.
Conversation outcomes
Returns conversation outcomes over a date range: a per-day count of conversations under each contact tag, plus range totals for replies, bookings, handovers to a human, and conversations whose contact carries no tag.
The tag is a contact tag: the tags your AI Agent applies with its tag tool, auto-tag rules, the API or your team. It is not a per-conversation label. A conversation is counted under the tags its contact carries at the time of the request, so a contact with several tags counts once under each, and a tag removed later drops out of past days too. Give your agent one closing tag per outcome (for example resolved_ai, handoff_asked_for_human) and this endpoint returns containment and handoff reasons over time.
GET /analytics/outcomes
Pass group_by=tag to collapse the time axis and get range totals per tag only — in that mode labels is empty and each tag’s counts array is empty, while total is still populated.
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. Defaults to 30 days ago. |
to |
No | Range end, YYYY-MM-DD. Defaults to today. |
campaign_id |
No | Only count conversations with contacts currently on this campaign. Legacy; prefer agent_id. |
agent_id |
No | Only count outcomes belonging to this AI Agent. |
group_by |
No | date (default) keeps the per-day counts; tag collapses to range totals. |
This endpoint’s date range is capped at 92 days.
cURL
curl "https://api.youraiconnector.com/v1/analytics/outcomes?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/outcomes?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/outcomes",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"group_by": "date",
"labels": ["2026-05-01", "2026-05-02"],
"by_tag": [
{ "tag_id": "tag_8f2k1", "tag": "interested", "total": 84, "counts": [3, 5] },
{ "tag_id": "tag_c91xq", "tag": "not_interested", "total": 40, "counts": [1, 2] },
{ "tag_id": null, "tag": null, "total": 12, "counts": [0, 1] }
],
"totals": {
"sessions": 260,
"replied": 210,
"booked": 35,
"human_alerted": 18,
"unresolved": 12
}
}
Field notes:
by_tag[].tag/by_tag[].tag_id— the contact tag’s name and id; bothnullon the row of conversations whose contact carries no tag. At most 20 tags are returned, highest volume first.totals.sessions— distinct conversations started in the range. It is not the sum ofby_tag[].total: a contact with three tags contributes one conversation to three rows.totals.unresolved— conversations whose contact carries no tag.totals.human_alerted— conversations handed over to a human; this is written on every handover and was not previously surfaced by any endpoint.- Same
503/analytics_unavailableposture as Metric series when the reporting database cannot answer.
Conversation costs
Returns what a conversation costs on average over a date range, split by how it went. This is the number to show a client as return on investment: what a conversation the AI handled alone costs, next to one your team had to step into.
GET /analytics/conversation-costs
| Parameter | Required | Description |
|---|---|---|
from |
No | Start date, YYYY-MM-DD, inclusive. Defaults to 30 days ago. |
to |
No | End date, YYYY-MM-DD, inclusive. Defaults to today. Maximum range 31 days. |
sub_account_id |
No | Agency keys: report on this client account instead of your own. |
curl "https://api.youraiconnector.com/v1/analytics/conversation-costs?from=2026-08-26&to=2026-09-24&apiKey=YOUR_API_KEY"
Response
{
"success": true,
"from": "2026-08-26",
"to": "2026-09-24",
"sessions": 564,
"total_credits": 5957,
"summary": {
"contained": { "sessions": 503, "credits": 5168, "avg_credits": 10.2744 },
"handed_off": { "sessions": 50, "credits": 781, "avg_credits": 15.62 },
"no_ai": { "sessions": 11, "credits": 8, "avg_credits": 0.7273 }
},
"sessions_truncated": false
}
Field notes:
- Counts conversations (chat sessions) that started in the range, with the credits charged inside each conversation’s window, refunds subtracted. Credits spent outside any conversation (daily summaries, monthly fees, automations that were not started by a contact, such as webhook or RSS triggers) are not part of it. Automation runs and AI steps started by a contact count toward that contact’s conversation since September 26, 2026.
contained: the AI replied and nobody from your team had to step in.handed_off: someone sent a message after the AI had replied, or the AI alerted a human.no_ai: the AI never replied (for example chats your team handles with the AI paused).- At most 20,000 conversations are counted;
sessions_truncatedistruewhen the range held more, so narrow it. - Needs the billing permission for team members. Same
503/analytics_unavailableposture as Metric series. - Per contact, the same split is on Get contact cost.
Dashboard insights
Returns the full dashboard payload for a date range in one call: a reply-rate heatmap by weekday and hour, the campaign leaderboard, per-channel volume, exact per-connection totals, per-day metric breakdowns (account-wide, per channel, and per number), where contacts are from, inbox response time, and a recent activity feed. This is the richest reporting payload on the API — it powers the in-app dashboard directly.
GET /analytics/dashboard-insights
| Parameter | Required | Description |
|---|---|---|
startDate |
Yes | Range start, YYYY-MM-DD. |
endDate |
Yes | Range end, YYYY-MM-DD. |
campaignId |
No | Only include activity belonging to this campaign (campaign_id also accepted). Legacy; prefer agent_id. |
agent_id |
No | Only include activity belonging to this AI Agent (agentId also accepted). Under an agent scope, the campaign leaderboard is built from that agent’s activity only. |
tag_ids |
No | Comma-separated tag ids (tagIds also accepted, up to 25). Narrows every block to contacts that currently carry any of these tags — the same “match any” rule the Contacts page filter uses. Combines with campaignId or agent_id. Rows with no contact (account-level credit recharges) fall out of a tag-scoped view, and the conversation_outcomes block comes back null under a tag scope. Returns 400 with error_code: 400 when the tag filter is not available for the account. |
tag_match |
No | How tag_ids combine (tagMatch also accepted): any (default — a contact needs one of the tags) or all (a contact needs every one of them). Ignored when tag_ids is absent; any other value is a 400 when tag_ids is present. |
granularity |
No | Bucket grain for metricDailyBreakdown only: day (default), week (Monday-based, like /analytics/series) or month. Its labels are then the bucket starts, and the block carries granularity back. Every other block is unaffected. |
This endpoint uses startDate/endDate (not from/to) because it shares its implementation with the in-app dashboard. The range is capped at 92 days and is clamped, not rejected, when it is wider.
Null means unavailable, not zero. Several blocks (
numberStats,channelDailySeries,metricDailyBreakdown,contactsByCountry) are computed from the reporting database and come backnullwhen it cannot answer for your account. Do not render anullblock as an empty chart.
cURL
curl "https://api.youraiconnector.com/v1/analytics/dashboard-insights?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ startDate: "2026-05-01", endDate: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/dashboard-insights?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/dashboard-insights",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"startDate": "2026-05-01", "endDate": "2026-05-31"},
)
data = res.json()
Response (abridged — this payload is large; see the API Reference for the full schema)
{
"success": true,
"data": {
"heatmap": {
"buckets": [
{ "weekday": 1, "hour": 9, "sent": 12, "replied": 5, "replyRate": 0.42 }
]
},
"topCampaigns": [
{ "campaignId": "campaign123", "name": "Spring Promo", "sent": 420, "replied": 180, "booked": 22, "replyRate": 0.43, "creditsSpent": 210.5 }
],
"channelVolume": [
{ "channel": "whatsapp", "sent": 800, "received": 540, "lastMessageAt": "2026-05-31T14:02:11.000Z" }
],
"inboxSla": { "medianFirstResponseMs": 92000, "sampleSize": 140 },
"activityFeed": [
{ "id": "evt_1", "kind": "booked", "at": "2026-05-31T14:02:11.000Z", "contactId": "contact456", "contactName": "Jane Smith", "campaignId": "campaign123", "campaignName": "Spring Promo", "label": "Jane Smith booked an appointment" }
],
"numberStats": null,
"channelDailySeries": null,
"metricDailyBreakdown": null,
"contactsByCountry": null,
"ai_human_split": null
}
}
Field notes:
heatmap.buckets[].weekday—0is Sunday through6is Saturday.numberStats,channelDailySeries,metricDailyBreakdown,contactsByCountry,ai_human_split— each independentlynullwhen the reporting database is unavailable for your account; every other block still returns.
Dashboard AI insights
Returns three short, AI-written insights about the account’s messaging over a date range: one win, one thing to watch, and one tip — sentences you can paste straight into a report rather than numbers you still have to interpret. Generated from the account’s own message metrics only.
GET /analytics/dashboard-ai-insights
| Parameter | Required | Description |
|---|---|---|
startDate |
Yes | Range start, YYYY-MM-DD. |
endDate |
Yes | Range end, YYYY-MM-DD. |
This endpoint is account-wide — it takes no campaign or agent scope.
cURL
curl "https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ startDate: "2026-05-01", endDate: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"startDate": "2026-05-01", "endDate": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"data": {
"insights": [
{ "tone": "win", "title": "Reply rate is up", "detail": "Your reply rate climbed to 43% this period, up from 36% the period before." },
{ "tone": "watch", "title": "Bookings slowed midweek", "detail": "Wednesday bookings dropped to a third of Monday's, worth a look at your Wednesday follow-up timing." },
{ "tone": "tip", "title": "Re-send to non-repliers", "detail": "212 contacts received a message but never replied — a short follow-up template often recovers 10-15% of them." }
]
}
}
Missing startDate or endDate returns 400.
Entity activity timeline
Returns a single contact’s, deal’s, or task’s activity as one timeline, newest first: what happened and when, across messages, appointments, notes, and status changes. Use it to answer “what has happened with this person” without stitching several list endpoints together.
GET /analytics/entity-activity
| Parameter | Required | Description |
|---|---|---|
entityType |
Yes | contact, deal, or task. |
entityId |
Yes | ID of the record whose timeline to return. |
cURL
curl "https://api.youraiconnector.com/v1/analytics/entity-activity?entityType=contact&entityId=contact456&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ entityType: "contact", entityId: "contact456" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/entity-activity?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/entity-activity",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"entityType": "contact", "entityId": "contact456"},
)
data = res.json()
Response
{
"success": true,
"data": {
"items": [
{
"id": "evt_9",
"kind": "appointment_booked",
"at": "2026-05-31T14:02:11.000Z",
"label": "Booked an appointment for June 3",
"detail": "Consultation call, 30 minutes"
},
{
"id": "evt_8",
"kind": "message_replied",
"at": "2026-05-31T13:58:02.000Z",
"label": "Replied: \"Yes, that time works\""
}
]
}
}
A missing or invalid entityType/entityId returns 400. An entity that does not exist on your account returns 404, so other accounts’ ids stay unguessable.
Aggregated event counts (legacy)
Returns the same aggregated event counts as Message volume summary, but in the camelCase shape (contactCreated rather than contact_created, byDate rather than by_date) some older integrations were built against. Prefer /analytics/summary for new integrations — this endpoint exists only so the in-app dashboard and the API share one implementation.
GET /analytics/aggregate
| Parameter | Required | Description |
|---|---|---|
startDate |
No | Range start, ISO date or date-time. Defaults to the same window /analytics/summary uses. |
endDate |
No | Range end, ISO date or date-time. |
campaignId |
No | Only count events belonging to this campaign (campaign_id also accepted). Legacy; prefer agent_id. |
agent_id |
No | Only count events belonging to this AI Agent (agentId also accepted). |
tag_ids |
No | Comma-separated tag ids (tagIds also accepted, up to 25). Only count events whose contact currently carries any of these tags. Combines with campaignId or agent_id. Events with no contact (creditsRecharged) are excluded under a tag scope. |
tag_match |
No | How tag_ids combine (tagMatch also accepted): any (default) or all (only contacts carrying every one of the tags). Ignored when tag_ids is absent; any other value is a 400 when tag_ids is present. |
cURL
curl "https://api.youraiconnector.com/v1/analytics/aggregate?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
Response
{
"success": true,
"data": {
"from": "2026-05-01",
"to": "2026-05-31",
"total": 1240,
"byAnalyticType": {
"total": 1240,
"sent": 800,
"delivered": 760,
"read": 540,
"replied": 210,
"booked": 35,
"contactCreated": 120,
"creditsSpent": 412.5,
"creditsRecharged": 500
},
"byDate": [
{ "date": "2026-05-01", "byAnalyticType": { "total": 40, "sent": 25, "delivered": 24, "read": 18, "replied": 7, "booked": 1, "contactCreated": 4, "creditsSpent": 13.5, "creditsRecharged": 0 } }
]
}
}
Agency sub-account rollup
Analytics API errors
Analytics endpoints return the standard error envelope:
{
"success": false,
"error": "Date range too large. Maximum is 366 days."
}
On an analytics endpoint, an invalid date format or an out-of-range window returns 400, and an unknown campaign_id or agent_id returns 404. Sending both campaign_id and agent_id on an endpoint that accepts either is also a 400 — pass at most one. The PG-only reporting endpoints (Metric series, Conversation outcomes, Agency rollup) return 503 with "error_code": "analytics_unavailable" rather than a 200 full of zeros when the reporting database cannot answer for your account — retry shortly. The shared codes every endpoint can return — 401, 403 (your plan does not include API access, or, on the agency rollup, your account is not Agency/Dev), 429 (rate limit) and 500 — are listed with retry guidance in Errors & Pagination.
Next steps
- Authentication — the four ways to authenticate a request.
- Errors & Rate Limits — status codes and the 300 req/min limit.
- AI Agents API — the Agents these figures can be filtered by.