Workspace

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.

NumberCountsAt
CreatedConversations createdTheir creation
ResolvedConversations that are resolved now, once eachTheir current resolution; a reopen takes it back, a later resolution counts it again
ReopenedChanges out of resolvedThe change
Assigned (per agent)Conversations given to the agent, once per agentThe latest time they were given it
First response, median and p90The first reply's delayThe reply
Resolution, median and p90Creation to the current resolutionThe resolution
MessagesReplies 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 agentThe latest time
Time to first assignment, median and p90Creation to the conversation's first assignee, under that agentThe first assignment
Average open load (per agent)Open and pending conversations held, from hourly samples, over the hours sampledEach hour
Reopened resolutionsResolutions later reopened, counted back in the hour of the resolution they took backThat resolution
One touchResolved conversations with exactly one reply from a person before the resolutionThe resolution
Replies per resolutionReplies from people before each resolution, over the resolutionsThe resolution
Repeat contactResolved conversations whose contact opened another conversation within 7 daysThe resolution
Missed website chatA 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 pageThe resolution
SLA met, breachedA first response or resolution within the target of the SLA policy that applies then, or notThe first response, the resolution
Online, occupiedAgents online and the open conversations they hold, sampled every 15 minutesEach 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"

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_breached once per conversation and target, with kind, policy_id, policy_name and due_at: an automation trigger (condition sla.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.

ParameterMeaning
report_metriccreated, 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_toThe window, YYYY-MM-DD, both days included
report_tzThe report's time zone; empty uses the workspace's, else UTC
report_inbox_id, report_team_id, report_agent_id, report_tag_idCounted under this inbox, team, agent or tag; for satisfaction numbers the tag is the conversation's current tags
report_weekday, report_hourOne heatmap cell: 1 = Monday to 7 = Sunday, hour 0 to 23
report_bot_id, report_attr_id, report_policy_id, report_channelA bot, a category value, an SLA policy, a channel kind (for satisfaction numbers, the survey's channel)
report_ratingA list such as 4,5, with csat_responses only
report_age, report_waiting, report_slaWith 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.csv URL and the HTTP request header Authorization set to Bearer and your key; a scheduled refresh uses the same header. The JSON endpoints work the same way (Web › JSON) with points or rows expanded into a table.
  • Metabase reads databases, not HTTP APIs: load the files into a database it reads (a nightly fetch of table.csv and timeseries.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 points into 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].