---
title: "Reports"
description: "Incident report (volume, MTTA, MTTR by team, severity or month) and on-call report (minutes per user) for a date range, as JSON or CSV."
---

Two reports over an explicit date range, each available as JSON or as a CSV download.

## Authentication

Any IM-eligible role (`admin`, `editor`, `responder`) or an organization-wide API token. Incident Management must be enabled for the organization.

## Date range

Both reports require `from` and `to` as ISO 8601. `from` is inclusive, `to` exclusive, `to` must be after `from`, and the range may span at most 400 days.

## Incident report

`GET /api/im/reports/incidents`

Counts the incidents triggered in the range and their mean time to acknowledge (MTTA) and to resolve (MTTR), in minutes. An incident that was never acknowledged or resolved is left out of that average, it does not count as zero. Test incidents are excluded.

### Query Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `from`, `to` | ISO 8601 | Yes | See [Date range](#date-range). |
| `groupBy` | string | No | `month` (default), `team` or `severity`. Any other value falls back to `month`. |
| `tz` | number | No | Your UTC offset in minutes (e.g. `120`), default `0`. Decides which local month an incident belongs to. |
| `format` | string | No | `csv` returns a CSV file instead of JSON. |

### Example (cURL)

```bash
curl "$BASE_URL/api/im/reports/incidents?from=2026-07-01T00:00:00Z&to=2026-10-01T00:00:00Z&groupBy=severity" \
  -H "Authorization: Bearer $TOKEN"
```

### Response

```json
{
  "from": "2026-07-01T00:00:00.000Z",
  "to": "2026-10-01T00:00:00.000Z",
  "groupBy": "severity",
  "summary": { "count": 27, "mttaMinutes": 6.4, "mttrMinutes": 82.15 },
  "groups": [
    { "groupKey": "sev1", "groupLabel": "sev1", "count": 3, "mttaMinutes": 1.8, "mttrMinutes": 41.5 },
    { "groupKey": "sev3", "groupLabel": "sev3", "count": 24, "mttaMinutes": 7.1, "mttrMinutes": 87.24 }
  ]
}
```

`groupKey` / `groupLabel` per grouping: `team` gives the team ID and team name, `severity` gives `sev1` to `sev4`, `month` gives the UTC instant of the local month start (e.g. `2026-08-31T22:00:00.000Z` for August with `tz=120`) in both fields. Groups without incidents are omitted. Averages are rounded to two decimals and `null` when no incident in the group qualifies.

With `format=csv` the response is `text/csv` with `Content-Disposition: attachment; filename="incidents-report-<date>.csv"` and the columns `<groupBy>,count,mttaMinutes,mttrMinutes`. Month labels are written as `YYYY-MM`, empty averages as empty cells. The summary is not part of the CSV.

## On-call report

`GET /api/im/reports/on-call`

On-call minutes per user inside the range. Shifts that start before `from` or end after `to` only count their part inside the range. Team-level overrides of type `online` (without a schedule) are added on top of the scheduled shifts.

### Query Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `from`, `to` | ISO 8601 | Yes | See [Date range](#date-range). |
| `format` | string | No | `csv` returns a CSV file instead of JSON. |

### Example (cURL)

```bash
curl "$BASE_URL/api/im/reports/on-call?from=2026-09-01T00:00:00Z&to=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer $TOKEN"
```

### Response

```json
{
  "periodStart": "2026-09-01T00:00:00.000Z",
  "periodEnd": "2026-10-01T00:00:00.000Z",
  "users": [
    { "userId": "u_abc123", "userName": "Jana Weber", "minutes": 21600 },
    { "userId": "u_def456", "userName": "Tobias Brandt", "minutes": 21600 }
  ]
}
```

`users` is sorted by `userId`, `minutes` rounded to two decimals. Users without on-call time in the range do not appear.

With `format=csv` the response is `text/csv` with `Content-Disposition: attachment; filename="on-call-report-<date>.csv"` and the columns `userId,userName,minutes,hours`.

## Common errors

- `401 Unauthorized` (`unauthorized`) when not authenticated
- `403 Forbidden` (`customerScopedTokenForbidden`) for a customer-scoped token
- `403 Forbidden` (`imAccessDenied`) when the session has no IM-eligible role
- `403 Forbidden` (`imNotEnabled`) when Incident Management is not enabled for the organization
- `400 Bad Request` (`imReportRangeRequired`) when `from` or `to` is missing or not a valid date
- `400 Bad Request` (`imReportRangeInvalid`) when `from` is not before `to`
- `400 Bad Request` (`imReportRangeTooLarge`) when the range exceeds 400 days
