Analytics and usage
Who can use this feature?
- An admin on Pro or Plus can create the calling API key. Every route needs
analytics:read, exceptGET /intents, which needsconversations:read. Legacy unscoped keys are refused. - Chat-to-sale reports follow the store's plan: some fields are removed on lower plans. See Plan limits on chat-to-sale.
All routes are GET on the Public API base URL and take no body. Send X-Api-Key on every request. These are reads only; the API cannot change the plan or billing.
| Path | Returns |
|---|---|
/analytics/overview | Conversation totals, AI answer rate, AI reply ratings, FAQ views |
/analytics/ai | AI answer rate, involvement and answer topics |
/analytics/conversations | Conversation totals, response time, team performance, totals by channel |
/analytics/sales | Orders attributed to Chatty, chat-to-sale rate, total store sales |
/analytics/customer-intents | What customers asked about, by intent and phase |
/analytics/satisfaction | Satisfaction survey results |
/analytics/handling | Agent handling and resolution time |
/analytics/campaigns/{id} | Triggers, interactions and add-to-cart events for one campaign |
/analytics/chat-to-sale and 8 sub-views | Chat-to-sale funnel, sales, agents and resolution |
/intents | The store's active intent labels |
/subscription | Current plan and AI reply quota |
/subscription/usage | Current cycle usage and billing history |
Choose a date window
Every /analytics/* route accepts the same window:
| Parameter | Meaning |
|---|---|
from, to | Inclusive days as YYYY-MM-DD. Send both, or neither. They take precedence over range. |
range | today, yesterday, last-3-days, last-7-days, last-30-days (default), last-3-months, this-month or last-month |
- A window is 1–90 days. Longer windows, or
tobeforefrom, return400 VALIDATION_FAILED. - Days are counted in the store's time zone, or UTC if none is set.
- Each report also compares with the window just before it: the same number of days, or the previous month for
this-monthandlast-month. - Money is in the store's currency. Analytics responses do not include a currency code.
curl 'https://app.chatty.net/v1/analytics/overview?from=2026-10-01&to=2026-10-21' \
-H 'X-Api-Key: sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'Response shape
Analytics routes return {"success":true,"data":{...}}. data.updatedAt is when the report was computed. Reports are cached for up to an hour, so a new conversation can take that long to appear.
Check success as well as the status. An unexpected failure while building a report returns HTTP 200 with {"success":false,"error":"..."}. Validation and lookup errors use the usual error.code.
/subscription, /subscription/usage and /intents return {"data":...} without success or updatedAt, and are not cached.
Overview, AI, conversations and sales
These four reports wrap each figure as {current, previous, unit, description}, where previous is the comparison window. They also return a window object:
{
"success": true,
"data": {
"window": {
"from": "2026-09-24T14:22:00.000Z",
"to": "2026-10-22T14:22:00.000Z",
"timeZone": "America/New_York",
"unit": "UTC instants for calendar dates in the shop time zone",
"description": "The time window applied to every analytics value in this response."
},
"conversations": {
"current": {"resolutionRate": 0.82, "totalConversations": 410, "totalHumanConversations": 150, "totalHumanResolvedConversations": 120},
"previous": {"resolutionRate": 0.8, "totalConversations": 380},
"unit": "conversations and percent",
"description": "Conversation totals and resolution rate for the requested time window."
},
"aiAnswerRate": {
"current": {"totalCount": 900, "successCount": 760, "successRate": 0.8444},
"previous": {"totalCount": 850, "successCount": 700, "successRate": 0.8235},
"unit": "answers and proportion from 0 to 1",
"description": "AI knowledge-answer attempts, successful answers, and answer rate for the requested time window."
},
"updatedAt": "2026-10-22T14:22:05.123Z"
}
}The example is an excerpt of /analytics/overview, which also returns satisfaction and faqViews. Chart arrays are left out.
| Route | Figures |
|---|---|
/analytics/overview | conversations, aiAnswerRate, satisfaction, faqViews |
/analytics/ai | answerRate, involvement, topics |
/analytics/conversations | overview, responseTime, teamPerformance, byChannel |
/analytics/sales | attributedOrders, chatToSale, storeSales |
resolutionRateandsuccessRateare proportions from 0 to 1.teamPerformance.value[].resolvedRateis a whole percent from 0 to 100.satisfactionin the overview counts AI reply ratings (great,good,bad), not survey answers. Survey results are on/analytics/satisfaction.topics.valuelists AI answer topics, most frequent first, withtotalandrate.byChannelkeys areonline store,email,facebook,instagramandwhatsapp.attributedOrderscounts orders assisted by Chatty.storeSalescovers every order in the store.
Customer intents
/analytics/customer-intents reports which intents Chatty detected in customer messages. Optional filters, each a comma-separated list:
| Parameter | Values |
|---|---|
phases | pre, purchase, post, cross, junk, customer_type, none |
intents | Intent slugs from GET /intents. Unknown slugs are ignored. |
{
"success": true,
"data": {
"rows": [{"slug": "product_info", "name": "Product information", "phase": "pre", "total": 120, "compareTotal": 100, "percentage": 24.5}],
"junkRows": [{"slug": "marketing_spam", "name": "Marketing spam", "total": 8, "compareTotal": 5, "percentage": 1.6}],
"phases": [{"phase": "pre", "total": 300, "compareTotal": 280, "messages": 250, "compareMessages": 240}],
"labelledMessages": 490,
"compareLabelledMessages": 450,
"noneMessages": 60,
"compareNoneMessages": 55,
"requestMessages": 480,
"compareRequestMessages": 440,
"updatedAt": "2026-10-22T14:22:05.123Z"
}
}rows lists intents most frequent first; junk intents go to junkRows. percentage is the share of labelled messages, with one decimal. Fields starting with compare are for the comparison window.
GET /intents returns the store's active intent labels, so you can show names for the slugs:
{"data":[{"slug":"product_info","name":"Product information","phase":"pre"},{"slug":"order_status","name":"Order status","phase":"post"}]}Satisfaction, handling and campaigns
These reports return sourceData for the requested window and compareData for the comparison window.
| Route | Fields |
|---|---|
/analytics/satisfaction | satisfiedCount (rating 4 or 5), submittedCount, surveyCount, ratedSurveyCount, totalPoints, ratingCounts (counts for ratings 1 to 5) |
/analytics/handling | avgAgentHandlingTime, avgResolutionTime, and chart data for the requested window |
/analytics/campaigns/{id} | triggered, interacted, add_to_cart, always present |
{"success":true,"data":{"sourceData":{"triggered":120,"interacted":30,"add_to_cart":7},"compareData":{"triggered":100,"interacted":25,"add_to_cart":4},"updatedAt":"2026-10-22T14:22:05.123Z"}}A campaign ID from another store returns 404 NOT_FOUND with Campaign not found. Reading satisfaction through the API does not mark survey results as seen in the admin.
Chat-to-sale
| Path | Returns |
|---|---|
/analytics/chat-to-sale | Headline figures; same data as /kpi |
/analytics/chat-to-sale/kpi | Conversations, converted conversations, orders, revenue, resolution, satisfaction, store totals |
/analytics/chat-to-sale/sales | Funnel by stage and topic, a chart, top products |
/analytics/chat-to-sale/sales/spark | The funnel for the last 4 windows of the same length, oldest first |
/analytics/chat-to-sale/agents | Chats and revenue per team member |
/analytics/chat-to-sale/resolution | Conversations by how they were resolved |
/analytics/chat-to-sale/agent-table | Per-member orders, resolution rate and first response time |
/analytics/chat-to-sale/phase-mix | Per-member split of conversations into pre-sale, purchase and post-sale |
/analytics/chat-to-sale/topics | Each member's top two topics |
Most figures are split into ai, human and both. ai means only the AI answered; human means a team member replied. both is the distinct total, so ai plus human can be less than both. Deleted and spam conversations are excluded.
{
"success": true,
"data": {
"current": {
"extensives": {
"conversations": {"ai": 200, "human": 150, "both": 410},
"converted": {"ai": 12, "human": 8, "both": 20},
"orders": {"ai": 13, "human": 9, "both": 22},
"revenue": {"ai": 900.0, "human": 640.5, "both": 1540.5}
},
"resolution": {"auto": 180, "manual": 120},
"csat": {"satisfied": {"ai": 30, "human": 20, "both": 50}, "submitted": {"ai": 40, "human": 30, "both": 70}},
"storeRevenue": 15400.0,
"storeOrders": 220
},
"compare": {},
"updatedAt": "2026-10-22T14:22:05.123Z"
}
}The example is an excerpt of /kpi; compare has the same keys for the comparison window. storeRevenue and storeOrders cover every store order.
/salesfunnel stages are cumulative:Preis every conversation,Purchasehas an assisted order,Posthas a fulfilled order. Refunds are taken out of revenue. The chart is hourly for a one-day window, daily otherwise./resolutionreturns five states in this order:aiResolved,agentResolved,mixResolved,notReplyResolvedandopen, each withcountand asharefrom 0 to 1./agentscredits revenue to the last assigned member. Members no longer in the store are left out./agent-tablesorts members by chats.frtis the median first response time;nullmeans the member never replied.
Plan limits on chat-to-sale
Chatty removes fields the store's plan does not include. There is no error: the field is missing or empty. /kpi, /agents, /resolution and /phase-mix are never limited.
| Plan | Removed |
|---|---|
| Free | Everything listed for Basic, plus orders and revenue in the Purchase and Post stages of /sales and /sales/spark |
| Basic | Topic detail (topics keep only volume), topicProducts, product prices and revenue in topProducts, operations figures in /agent-table, and all of /topics ({"agents":[]}) |
| Pro, Plus | Nothing |
An upgrade applies on the next request, even to cached reports.
Subscription and usage
{
"data": {
"plan": {"id": "pro", "name": "Pro", "interval": "monthly", "isOnTrial": false, "trialEndsAt": null},
"aiQuota": {"used": 420, "limit": 1000, "remaining": 580, "unit": "AI replies in the current billing cycle"}
}
}GET /subscription returns the plan and the AI reply quota for the current billing cycle. remaining never goes below 0. GET /subscription/usage returns currentCycle (startsAt, used, limit, bonusUsed, bonusLimit) and history.value, one row per billing period with periodStart, periodEnd, plan, used, limit, amount and currency. Missing values are null. Both examples are excerpts.
Errors
| HTTP | Code | Meaning |
|---|---|---|
200 | success: false | A report failed to build. Retry later. |
400 | VALIDATION_FAILED | Only one of from/to, an unknown range, a window outside 1–90 days, or an invalid date. |
400 | INVALID_API_VERSION | Invalid X-Api-Version date. |
401 | UNAUTHENTICATED / INVALID_API_KEY | Missing, unknown or revoked key. |
403 | FORBIDDEN | Missing scope, or a legacy key. |
404 | NOT_FOUND | Store or campaign not found. |
429 | RATE_LIMITED | Shared Public API limit reached. |
On MCP, get_shop_analytics reads the intent, satisfaction, campaign, handling and chat-to-sale reports with an API key or OAuth, with the same plan limits. list_intents reads intent labels with an API key. The older tools, such as get_analytics_overview and get_subscription, read the other routes. See the MCP tool reference.
Chatty Help Center