Reports
How Kommio counts its report numbers, how inbox, team and agent filters combine, business-hours durations, the backlog, quality, SLA, staffing, channel and category reports, satisfaction drivers, opening the conversations behind a number, saved views, CSV and Excel exports, scheduled emails and the Reports API for BI tools.
Last updated
The Reports page (permission reports:read) shows volume, speed and satisfaction for a window of days: a live strip, tiles against the previous period, the backlog now, created and resolved per day, first response time per day, a breakdown by agent, team, inbox or tag, the weekday and hour heatmap, quality and missed website chats, SLA attainment, staffing, the channel mix, category trends, assignment, satisfaction and agent bots. Everything but the live strip and the backlog is read from hourly rollups, or from daily rollups for a window of 60 days or more in the workspace's own time zone, so the page stays fast on large workspaces and a year is one request.
What each number counts
A report covers whole local days in one time zone: the one the request names, else the workspace's, else UTC. The page says which zone it uses. A workspace whose own zone is offset by a half or quarter hour (India, Nepal, parts of Australia) gets exact local days too.
| Number | Counts | At |
|---|---|---|
| Created | Conversations created | Their creation |
| Resolved | Conversations that are resolved now, once each | Their current resolution; a reopen takes it back, a later resolution counts it again |
| Reopened | Changes out of resolved | The change |
| Assigned (per agent) | Conversations given to the agent, once per agent | The latest time they were given it |
| First response, median and p90 | The first reply's delay | The reply |
| Resolution, median and p90 | Creation to the current resolution | The resolution |
| Messages | Replies in and out (the sender gets outgoing ones) | The message |
| Reassigned away (per agent) | Open conversations taken from the agent, to another agent or back to the queue, once per conversation and agent | The latest time |
| Time to first assignment, median and p90 | Creation to the conversation's first assignee, under that agent | The first assignment |
| Average open load (per agent) | Open and pending conversations held, from hourly samples, over the hours sampled | Each hour |
| Reopened resolutions | Resolutions later reopened, counted back in the hour of the resolution they took back | That resolution |
| One touch | Resolved conversations with exactly one reply from a person before the resolution | The resolution |
| Replies per resolution | Replies from people before each resolution, over the resolutions | The resolution |
| Repeat contact | Resolved conversations whose contact opened another conversation within 7 days | The resolution |
| Missed website chat | A website chat resolved or closed with no reply from a person and not resolved by a bot, with the wait until the visitor left the page | The resolution |
| SLA met, breached | A first response or resolution within the target of the SLA policy that applies then, or not | The first response, the resolution |
| Online, occupied | Agents online and the open conversations they hold, sampled every 15 minutes | Each sample |
Each observation counts under the inbox, team and agent (the assignee; the replying agent for first responses and messages sent) and the tags the conversation had when it was counted. Medians and p90 are estimated from a histogram and are accurate to about ±20%, which is plenty to see a trend and never hides a slow tail the way an average does. What goes with a resolution (one touch, the replies, a missed chat, a repeat contact, SLA met or breached) is counted with it, and a reopen takes it all back with the resolution.
Filters and scope
The inbox, team and agent filters combine: "the Billing inbox, grouped by agent" or "Dana in the Billing inbox" are both answered from the rollups. The tag breakdown, category trends and the rows per SLA policy cover the whole workspace and cannot be combined with filters; the page says so.
Reports follow the viewer's role. Someone whose role sees only their teams, their inboxes or their assigned conversations sees the numbers of those conversations, and does not get the tag breakdown, the agent bots, category trends or the per-policy and per-agent staffing rows, which span the workspace. Administrators and Supervisors see everything. API keys and apps read what the person who made them may see now (below).
A link can open the page with a window and filters, for example /reports?from=2026-09-01&to=2026-09-30&inbox=3&team=2&agent=9, or a saved view with /reports?view=12.
# the Billing inbox (3), grouped by agent, in Lisbon days
curl "$KOMMIO_URL/reports/table?dimension=agent&inbox_id=3&from=2026-09-01&to=2026-09-30&tz=Europe/Lisbon" \
-H "Authorization: Bearer $KOMMIO_KEY"
# tiles, series and heatmap for one agent in one inbox
curl "$KOMMIO_URL/reports/overview?inbox_id=3&agent_id=9&from=2026-09-01&to=2026-09-30" \
-H "Authorization: Bearer $KOMMIO_KEY"const { data } = await api.GET("/reports/overview", {
params: { query: { from: "2026-09-01", to: "2026-09-30", inbox_id: 3, agent_id: 9 } },
});
console.log(data.tiles.first_response_median_ms, data.tiles.first_response_bh_median_ms);Business hours
The Wall clock / Business hours switch changes the first response and resolution tiles, the first response chart and the breakdown's columns. A business-hours duration counts only the open time between the two moments, in the inbox's own hours or else the workspace's, with holidays and date exceptions, in that schedule's time zone. Without business hours set, both are the same, and the page says so. A duration is computed when it is counted, so changing the hours later affects what is counted afterwards, or what a rebuild recounts.
Response 200 OK
GET /reports/overview?from=2026-09-01&to=2026-09-30
{ "tz": "Europe/Lisbon", "business_hours": true, "scoped": false, "rebuild_needed": false,
"tiles": { "created": 1840, "resolved": 1712,
"first_response_median_ms": 1260000, "first_response_bh_median_ms": 540000,
"resolution_median_ms": 20520000, "resolution_bh_median_ms": 9360000 },
"previous": { "created": 1702, "resolved": 1655, "first_response_median_ms": 1380000, "first_response_bh_median_ms": 600000,
"resolution_median_ms": 21600000, "resolution_bh_median_ms": 9900000 } }Shortened: the response also carries the remaining tiles, series (one entry per day), heatmap (one per weekday and hour) and live (the strip at the top of the page); the API reference has every field.
Backlog now
The card under the tiles (GET /reports/backlog) counts the open and pending conversations you may see, within the filters, at this moment: by age since creation (under 1 hour, 1 to 4 hours, 4 to 24 hours, 1 to 3 days, 3 to 7 days, over 7 days) and by who they wait on, the team (open and the customer wrote last) or the customer. It names the customer who has waited longest for an answer. Every cell opens its conversations.
Quality and missed website chats
GET /reports/quality, against the previous period: the reopen rate (reopened resolutions over resolved plus reopened, so the two together are every resolution made in the window), one-touch resolution, replies per resolution and repeat contact (another conversation from the same contact within 7 days, so the last week of a window is still filling). Reopens are counted from the release that introduced them; older history has no reopen trace.
A missed website chat is a chat resolved or closed without a reply from a person and not resolved by a bot. Its wait runs from its start to the moment the visitor left the page, else to the resolution; the report shows the website chats resolved, the missed rate and the median and p90 wait.
SLA policies and attainment
Settings › SLA policies (settings:manage; GET/POST /sla/policies, PUT and DELETE /sla/policies/{id}, PUT /sla/policies/order) holds the workspace's policies: a name, a first response target and a resolution target in minutes (either may be absent), counted in wall clock or in the inbox's business hours, for some inboxes and priorities or all of them. The first enabled policy in order that matches a conversation's inbox and priority applies.
- Attainment (
GET /reports/sla): each first response and each resolution counts as met or breached under the policy that applied at that moment, as the share within target, per day and per policy. A reopen takes the resolution's outcome back; a rebuild applies the policies as they are now to the stored history. - Past due now: open conversations past a target and still waiting, and those due within the hour, counted from each conversation's own SLA clock at this moment.
- Breaches: once a conversation passes a target while still waiting, Kommio publishes
conversation.sla_breachedonce per conversation and target, withkind,policy_id,policy_nameanddue_at: an automation trigger (conditionsla.kind) and a webhook event.
A new or changed policy applies to a conversation when it next changes. The first response clock stops at the first reply or at a resolution without one; the resolution clock does not start again on a reopen. Not yet: a next-response target, pausing while pending or snoozed.
curl -X POST "$KOMMIO_URL/sla/policies" -H "Authorization: Bearer $KOMMIO_KEY" -H "Content-Type: application/json" -d '{
"name": "Urgent in Billing", "enabled": true,
"first_response_minutes": 15, "resolution_minutes": 480, "business_hours": true,
"inbox_ids": [3], "priorities": ["urgent", "high"]
}'
# attainment per day and per policy, September
curl "$KOMMIO_URL/reports/sla?from=2026-09-01&to=2026-09-30" -H "Authorization: Bearer $KOMMIO_KEY"Staffing
GET /reports/staffing. Every 15 minutes, while the workspace's agents use the app, Kommio records who is online (Online or Busy with the app connected) and the open conversations each holds. From the samples: hours online (agent-hours) and agents online on average, occupancy (the share of online time holding at least one open conversation; Kommio cannot tell typing from waiting, so "handling" means holding an open conversation), concurrent chats, and a weekday × hour heatmap of conversations created, agents online and conversations per agent-hour, which shows the hours with too few people. Presence follows the agent filter, else the team filter, else the workspace.
Channel mix
GET /reports/channels: conversations created, resolved and the first response time per channel kind (email, web chat, WhatsApp, Messenger, Instagram, Telegram, SMS, Slack, API), within the filters and your scope. Each count opens its conversations.
Category trends
The workspace's category attribute is the setting reports.category_attribute, else the conversation attribute with the key category when there is one. Creation counts a conversation under the value it has now (a later change moves it); a resolution counts under the value it has then. GET /reports/categories lists the top values by conversations created (top, default 8) with their daily series, resolutions and median resolution time, and flags a spike: a day with at least 5 conversations and more than the mean of the 14 days before plus three standard deviations. Like tags, values are the whole workspace's and take no filters. When the attribute is marked as personal data, a role that sees it masked gets masked labels and one that sees it hidden gets no values.
Assignment
Reports › Assignment (GET /reports/assignment) shows, per agent and in total, conversations assigned, reassigned away (to another agent or back to the queue, once per conversation and agent), the time to first assignment (median and p90) and the average open load, with the load held per day as a chart. How conversations are assigned is in the automation guide.
Satisfaction drivers
The Customer satisfaction section breaks satisfaction down by agent, team, inbox, tag or the channel the survey went out on, over time, and every number opens the responses behind it in a panel beside the page: the score opens the responses rated 4 or 5, a rating's bar the responses with that rating, a day that day's, a breakdown row that row's. The panel lists each rating with its comment, conversation and channel, newest first, can be limited to responses with a comment and searched, and opens the same conversations in the inbox.
Comments are customer free text. The personal data in them (email addresses, phone numbers, card numbers and IBANs, street addresses) follows the reader's field grants as the same data does in its own fields: shown, masked, or replaced by a placeholder such as [card number], and listed in _redacted. A search matches what the reader sees.
# low ratings with a comment, in the Billing inbox, newest first
curl "$KOMMIO_URL/reports/csat/responses?from=2026-09-01&to=2026-09-30&inbox_id=3&rating=1,2&with_comment=true" \
-H "Authorization: Bearer $KOMMIO_KEY"There is no personal alert on a low rating yet; the csat.submitted automation trigger, with the rating as a condition, can tag or assign the conversation or post a webhook.
The conversations behind a number
Every number that counts conversations opens the inbox on exactly those conversations: the tiles, a day of a chart, a heatmap cell, the breakdown's cells, every quality, SLA, backlog, channel, category and assignment number. The list shows a "From Reports" chip naming the number and its total, with a way back. It holds every status: Resolved lists conversations that are resolved now, while Created and First response may list ones that are open again. Numbers that count something else (messages, ratings, surveys, bot sessions) open the conversations they were counted in, and the list says how many of those its conversations hold.
The same list is available on GET /conversations with the report_* parameters; the response then carries total, which equals the report's number as long as the caller can still see those conversations.
| Parameter | Meaning |
|---|---|
report_metric | created, first_response, resolved, assigned, first_assignment, reassigned, messages, messages_in, messages_out, csat_sent, csat_responses, bot_handled, bot_resolved, bot_handoff, reopened, one_touch, repeat_contact, missed_chat, sla_first_response_met, sla_first_response_breached, sla_resolution_met, sla_resolution_breached; of now, without a window: backlog and sla_breached_now |
report_from, report_to | The window, YYYY-MM-DD, both days included |
report_tz | The report's time zone; empty uses the workspace's, else UTC |
report_inbox_id, report_team_id, report_agent_id, report_tag_id | Counted under this inbox, team, agent or tag; for satisfaction numbers the tag is the conversation's current tags |
report_weekday, report_hour | One heatmap cell: 1 = Monday to 7 = Sunday, hour 0 to 23 |
report_bot_id, report_attr_id, report_policy_id, report_channel | A bot, a category value, an SLA policy, a channel kind (for satisfaction numbers, the survey's channel) |
report_rating | A list such as 4,5, with csat_responses only |
report_age, report_waiting, report_sla | With backlog: lt1h, 1to4h, 4to24h, 1to3d, 3to7d or gt7d, and us or customer; with sla_breached_now: first_response or resolution |
# the conversations Dana resolved in September, in the Billing inbox
curl "$KOMMIO_URL/conversations?report_metric=resolved&report_from=2026-09-01&report_to=2026-09-30&report_agent_id=9&report_inbox_id=3" \
-H "Authorization: Bearer $KOMMIO_KEY"
# everything waiting on the team for more than a day, right now
curl "$KOMMIO_URL/conversations?report_metric=backlog&report_age=1to3d&report_waiting=us" -H "Authorization: Bearer $KOMMIO_KEY"Other list parameters narrow the result further.
Saved views
Save view keeps the page as it is (the report, the range preset or custom days, the inbox, team and agent filters, the breakdown's grouping, wall clock or business hours) as a named view, private to you or shared with the workspace by someone holding reports:share (Administrator and Supervisor by default). Each person pins up to 20 views to their own Reports sidebar; a view opens with /reports?view=<id>, and the page says when it was changed since it was saved, with Save changes or Save as new view. A view holds filters, never numbers or a scope: whoever opens a shared view sees it within their own scope, so a Viewer opening an administrator's view sees the Viewer's numbers. Changes to shared views are audited. API: /reports/views, /reports/views/{id}, /duplicate and /pin.
Exports: CSV and Excel
Export downloads the breakdown or the per-day series as CSV or Excel, for what the page shows, with the same rows and numbers as the table (durations in seconds), streamed as they are written: GET /reports/table.csv or .xlsx, GET /reports/timeseries.csv or .xlsx (interval day, week or month) and GET /reports/views/{id}/table.csv or .xlsx for a saved view. Every text cell a spreadsheet could take for a formula starts with an apostrophe, in both formats.
The breakdown file's columns: the dimension's name, created, assigned, resolved, messages_sent, first_response_median_seconds, resolution_median_seconds, first_response_business_hours_median_seconds, resolution_business_hours_median_seconds, csat_responses, csat_score_percent and <dimension>_id. The time series file's: period, created, resolved, reopened, assigned, messages_in, messages_out, and for first response and resolution the count and the median and p90 in seconds, wall clock and business hours. Columns are only ever added.
The Reports API for BI tools
Every report endpoint is read-only JSON, CSV or Excel over HTTP with the same filters as the page, so Power BI, Looker Studio, Metabase, a spreadsheet or a script can read it. Create an API key under Settings › API keys with the reports:read permission only and send it as Authorization: Bearer. A key reads what the person who created it may see in Reports, checked on every request: a key made by an administrator reads the whole workspace; one made by a Viewer reads their teams' numbers and gets no tag or bot breakdown. When that person leaves, is disabled or loses reports:read, the key is refused with 403. Keys read shared saved views but cannot save views or schedule emails.
# every tile per ISO week for the Billing inbox
curl "$KOMMIO_URL/reports/timeseries?from=2026-09-01&to=2026-09-30&interval=week&inbox_id=3" -H "Authorization: Bearer $KOMMIO_KEY"
# the agent breakdown as a spreadsheet
curl -o agents.xlsx "$KOMMIO_URL/reports/table.xlsx?from=2026-09-01&to=2026-09-30&dimension=agent" -H "Authorization: Bearer $KOMMIO_KEY"- Power BI: Get data › Web › Advanced with the
timeseries.csvURL and the HTTP request headerAuthorizationset toBearerand your key; a scheduled refresh uses the same header. The JSON endpoints work the same way (Web › JSON) withpointsorrowsexpanded into a table. - Metabase reads databases, not HTTP APIs: load the files into a database it reads (a nightly fetch of
table.csvandtimeseries.csv), or use a scheduled report email's attachment. - Looker Studio: a community connector that fetches JSON with a request header, or a Google Sheet filled by an Apps Script that calls the API and writes
pointsinto rows.
Never put a key in a URL; tools that only fetch a URL without headers should use a scheduled report email with a CSV attachment, or a small relay you run. from and to span at most 400 days; GET /reports/table pages by limit (up to 1,000) and cursor.
Scheduled report emails
Email me this report schedules a daily summary (the day before) or a weekly one (the seven days before), at a local hour and weekday, in a time zone (the workspace's by default), optionally limited to an inbox, team and agent, or sending a saved view (yours or a shared one) instead. Each person manages only their own, up to ten; Send now sends the last full period at once.
- Each email is prepared with the recipient's permissions at the moment it is sent: someone who no longer holds
reports:read, or is no longer an active member, gets nothing, and the numbers are limited to what their role sees. A view the recipient no longer sees is not sent. - It arrives in the recipient's language: created, resolved, first response and resolution (in business hours too, when they are set) against the previous period, the top ten agents by resolved conversations, and satisfaction (the average against the previous period, the response rate and count, how many were rated 1 or 2; never comment text). It carries no customer data.
- It can attach the breakdown as CSV or Excel. A file over 512 KB is kept for seven days instead and linked, downloadable only by the recipient while they hold
reports:read. - It links to the page with the same window and filters, and to an unsubscribe page that asks before it pauses the schedule; mail clients' one-click unsubscribe pauses it directly.
Schedules belong to a person: they are managed in the app (Reports › Schedule), or through the same endpoints (GET/POST /reports/schedules, PATCH and DELETE /reports/schedules/{id}, POST /reports/schedules/{id}/send) from a signed-in session. API keys and app tokens are refused, because a schedule sends a person's view of the numbers to that person.
After an upgrade
When a release counts something new, Kommio recounts the stored conversations on its own: the rebuild queues itself after the upgrade, at the lowest priority, and the page shows a notice until it has finished, refreshing the numbers then; reports keep answering from the old rows meanwhile. A failed rebuild stays on the notice with Try again. GET /reports/backfill says where it stands, and rebuild_needed in the overview response says the same. Changing the workspace's time zone or its category attribute marks a rebuild too.
Retention
Report data is kept for 400 days, so reports cover about thirteen months. Conversations themselves are not deleted by this.
Read more
Why medians and p90, and how rollups are rebuilt: How Kommio reports are counted. Every metric defined in a sentence: the support metrics glossary.
Every claim on these pages is covered by a test in the repository, and the API reference is generated from the same contract every server serves at /api/openapi. Corrections to [email protected].