Stats
Trends
Ticket volume: created versus resolved over time, the channel split, the breakdowns the
Overview tab reuses, and the hour-of-week arrival heatmap.
GET
/api/{tenant:minlength(2)}/v{version:apiVersion}/stats/trends
- Authorisation
- Minimum role: USER
Request arguments
| Name |
Type |
Source |
| group_ids | Int32[] | Query |
| timeframe | ENUM dashboard_kpi_timeframe | |
| from | DateTime | |
| to | DateTime | |
| compare | Boolean | |
Request body example
Response
- Status
- 200 (OK)
- Type
- DTO_stats_trends
- Wrapper
- DTO_response_wrap
- Other statuses
- 400 (BadRequest), 403 (Forbidden)
Response body example
DTO_stats_trends
| Name | Type | ReadOnly | Description |
| channel_series | DTO_stats_series[] | | Tickets per bucket per channel, ready to stack. |
| channels | DTO_stats_term[] | | Channels |
| priorities | DTO_stats_term[] | | Priorities |
| statuses | DTO_stats_term[] | | Statuses |
| tags | DTO_stats_term[] | | Tags |
| languages | DTO_stats_term[] | | Languages |
| groups | DTO_stats_term[] | | Groups |
| period | DTO_stats_period | | Period |
| created_total | DTO_stats_metric | | Tickets created in the window. |
| resolved_total | DTO_stats_metric | | Times a ticket entered a closed status in the window. Independent of created_total: a
backlog-clearing week resolves more than it takes in, and that is the point of the card. |
| open_now | Int32 | | Open tickets right now, across all non-closed statuses. Not window-scoped. |
| volume_series | DTO_stats_series[] | | Created and resolved, one point per bucket. |
| hour_weekday_matrix | List`1[] | | Average new tickets per hour of the week, [weekday 0=Monday][hour 0-23], folded from the
hourly histogram in the workspace time zone. |
| busiest_slot_label | String | | English fallback label of the busiest cell ("Tue 10:00"), or null when there is no data.
The frontend renders the weekday/hour pair below with its own localized weekday names. |
| busiest_slot_weekday | Int32 (nullable) | | Busiest cell's weekday, 0=Monday - same row order as the matrix. Null when no data. |
| busiest_slot_hour | Int32 (nullable) | | Busiest cell's hour, 0-23, workspace time zone. Null when no data. |
| busiest_slot_average | Double (nullable) | | Average new tickets in that cell. |
DTO_stats_series
| Name | Type | ReadOnly | Description |
| key | String | | Stable key the frontend maps to a colour and a translated label. |
| label | String | | Server-side fallback label, used when the key is dynamic (a group or status name). |
| points | DTO_stats_point[] | | Points |
DTO_stats_point
| Name | Type | ReadOnly | Description |
| label | String | | Short human label for the axis ("Jul 20", "10:00", "Jul 2026"). |
| date | DateTime | | Start of the bucket, workspace-local. |
| value | Double (nullable) | | Null means "no data in this bucket", which a chart draws as a gap, not a zero. |
DTO_stats_term
| Name | Type | ReadOnly | Description |
| id | Int32 | | Entity id when the term refers to one (group, status, mailbox); 0 otherwise. |
| key | String | | Stable key for terms that are enums rather than entities ("EMAIL", "CHAT_BOT"). |
| label | String | | Label |
| count | Int32 | | How many tickets fell into this term. |
| previous_count | Int32 (nullable) | | The term's own count in the comparison window. Null when not comparing. |
| value | Double (nullable) | | A secondary metric where the card shows one (average seconds, a percentage). |
DTO_stats_period
| Name | Type | ReadOnly | Description |
| from | DateTime | | First day of the window, workspace-local. |
| to | DateTime | | Last day of the window, workspace-local. |
| previous_from | DateTime (nullable) | | First day of the comparison window. Null when not comparing. |
| previous_to | DateTime (nullable) | | Last day of the comparison window. Null when not comparing. |
| time_zone | String | | IANA id of the zone every bucket and boundary was cut in. |
| granularity | String | | "hour", "day" or "month" - the width of one point in every series below. |
| timeframe | ENUM dashboard_kpi_timeframe | | Which preset produced this window (CUSTOM when from/to were supplied). |
| compare | Boolean | | True when the previous-period figures are populated. |
DTO_stats_metric
| Name | Type | ReadOnly | Description |
| current | Double (nullable) | | Current |
| previous | Double (nullable) | | The same figure over the previous window. Null when not comparing, or when there is no history. |
ENUM dashboard_kpi_timeframe
| Value | Name | Description |
| 0 | UNKNOWN | UNKNOWN |
| 1 | TODAY | TODAY |
| 2 | YESTERDAY | YESTERDAY |
| 3 | THIS_WEEK | THIS_WEEK |
| 4 | LAST_4_WEEKS | LAST_4_WEEKS |
| 5 | LAST_12_WEEKS | LAST_12_WEEKS |
| 6 | ALL_TIME | ALL_TIME |
| 7 | CUSTOM | Stats only: the caller supplies from and to instead. Resolving this without dates is
an error, so the shared GetTimeFrame() extension deliberately refuses it. |
| 8 | LAST_12_MONTHS | LAST_12_MONTHS |
Generated Aug 4, 2026 18:37