---
title: "Analytics"
description: "Every operation in this group: what it accepts, what it returns and the errors it can answer with."
url: "https://openemail.uk/docs/api/reference/analytics"
area: "API"
category: "Reference"
---

# Analytics

Every operation in this group: what it accepts, what it returns and the errors it can answer with.

## Operations

The numbers behind the Analytics page of the app: how mail arrives in the mailbox, and what became of the mail the workspace sent.

### `GET /analytics/mailbox`

Read how mail arrives

How mail arrives, as the Analytics page of the app shows it, for a window of 30 days up to now unless `from` and `to` say otherwise: conversations per day or per `grain` bucket and per hour of the day, the addresses they arrived at, the senders who wrote most, how many wait on a reply for 1, 3, 7 days or more, and the folders. A key or an app limited to particular addresses counts only the mail that arrived at them, and `address` narrows everything to one address.

Requires the `threads:read` scope.

- Scopes: `threads:read`.

**Query parameters**

- `from` (`string`, format `date-time`): The start of the window, ISO 8601 with a zone. Defaults to 30 days before `to`.
- `to` (`string`, format `date-time`): The end of the window. Defaults to now.
- `offsetMinutes` (`integer`, at least -840, at most 840, default `0`): Minutes east of UTC to cut days and hours in, from -840 to 840. Pass the reader’s offset so a day breaks where theirs does.
- `grain` (`string`, one of `"minute"`, `"hour"`, `"day"`, default `"day"`): How wide one bucket of `days` and `series` is.
- `address` (`string`, 3 to 320 characters): Count only the mail delivered to this address. One the key does not reach counts nothing.

**Returns**

- `200` `MailboxInsights`: The numbers for the window.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`analytics.mailbox()`](https://openemail.uk/docs/sdk/reference/analytics#mailbox); CLI [`openemail analytics mailbox`](https://openemail.uk/docs/cli/reference/analytics#analytics-mailbox); MCP [`getMailboxInsights`](https://openemail.uk/docs/mcp/tools/analytics#getMailboxInsights).

### `GET /analytics/sending`

Read what became of sent mail

What the workspace sent inside a window and what became of it, as the Analytics page of the app shows it: delivered, failed, bounced and complained, per day or per `grain` bucket, with the statuses, the sources, the senders and the addresses suppressed. The window is `days`, 30 by default and at most 365, or `minutes`, which wins, and it starts at the beginning of its oldest bucket. A key or an app limited to particular addresses counts only the mail sent from them.

Requires the `emails:read` scope.

- Scopes: `emails:read`.

**Query parameters**

- `days` (`integer`, at least 1, at most 365, default `30`): Window length in days.
- `minutes` (`integer`, at least 1, at most 525600): Window length in minutes, which wins over `days`.
- `grain` (`string`, one of `"minute"`, `"hour"`, `"day"`, default `"day"`): How wide one bucket of `days` is.
- `offsetMinutes` (`integer`, at least -840, at most 840, default `0`): Minutes east of UTC to cut the buckets in, from -840 to 840.
- `address` (`string`, 3 to 320 characters): Count only the mail sent from this address. One the key does not reach counts nothing.

**Returns**

- `200` `SendingAnalytics`: The numbers for the window.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`analytics.sending()`](https://openemail.uk/docs/sdk/reference/analytics#sending); CLI [`openemail analytics sending`](https://openemail.uk/docs/cli/reference/analytics#analytics-sending); MCP [`getSendingAnalytics`](https://openemail.uk/docs/mcp/tools/analytics#getSendingAnalytics).

### Objects

#### `MailboxInsights`

`object`

- `object` (`string`, required, one of `"mailbox_insights"`)
- `from` (`string`, required, format `date-time`)
- `to` (`string`, required, format `date-time`)
- `grain` (`string`, required, one of `"minute"`, `"hour"`, `"day"`, default `"day"`)
- `offsetMinutes` (`integer`, required)
- `scanned` (`integer`, required): Conversations that arrived inside the window.
- `days` (`object[]`, required)
  - `day` (`string`, required): The bucket: `YYYY-MM-DD`, `YYYY-MM-DDTHH` or `YYYY-MM-DDTHH:MM` by `grain`.
  - `count` (`integer`, required)
- `hours` (`object[]`, required)
  - `hour` (`integer`, required): The hour of the day, 0 to 23, in `offsetMinutes`.
  - `count` (`integer`, required)
- `addresses` (`object[]`, required)
  - `address` (`string`, required): The address the mail arrived at.
  - `count` (`integer`, required)
- `senders` (`object[]`, required): The senders who wrote most, most first.
  - `email` (`string`)
  - `name` (`string`, nullable)
  - `count` (`integer`)
  - `lastAt` (`string`, format `date-time`)
- `senderCount` (`integer`, required): Everyone who wrote inside the window.
- `waiting` (`object[]`, required): Conversations whose last message came from somebody else, by how many days it has waited.
  - `band` (`integer`, required): At least this many days.
  - `count` (`integer`, required)
- `unattributed` (`integer`, required): Mail that recorded no address it arrived at.
- `folders` (`object[]`, required)
  - `label` (`string`)
  - `count` (`integer`)
  - `unread` (`integer`)
- `series` (`object[]`, required): Per bucket counts for the top addresses and senders, so each can be charted.
  - `kind` (`string`)
  - `key` (`string`)
  - `day` (`string`)
  - `count` (`integer`)

#### `SendingAnalytics`

`object`

- `object` (`string`, required, one of `"sending_analytics"`)
- `since` (`string`, required, format `date-time`)
- `until` (`string`, required, format `date-time`)
- `grain` (`string`, required, one of `"minute"`, `"hour"`, `"day"`, default `"day"`)
- `offsetMinutes` (`integer`, required)
- `totals` (`object`, required)
  - `sends` (`integer`)
  - `testSends` (`integer`)
  - `recipients` (`integer`)
  - `delivered` (`integer`)
  - `failed` (`integer`)
  - `bounced` (`integer`)
  - `complained` (`integer`)
  - `uncertain` (`integer`)
  - `pending` (`integer`)
- `days` (`object[]`, required)
  - `day` (`string`)
  - `sent` (`integer`)
  - `delivered` (`integer`)
  - `failed` (`integer`)
  - `bounced` (`integer`)
  - `complained` (`integer`)
- `statuses` (`object[]`, required): Sends by status.
  - `label` (`string`, required): What is counted.
  - `count` (`integer`, required)
- `sources` (`object[]`, required): Sends by where they came from: the app, the API, a broadcast and the rest.
  - `label` (`string`, required): What is counted.
  - `count` (`integer`, required)
- `senders` (`object[]`, required): Sends by the address they went out as.
  - `label` (`string`, required): What is counted.
  - `count` (`integer`, required)
- `suppressed` (`object[]`, required): Addresses that were suppressed, by reason.
  - `label` (`string`, required): What is counted.
  - `count` (`integer`, required)
