---
title: "openemail.analytics"
description: "Every method in this namespace: its signature, its parameters, what it returns and an example."
url: "https://openemail.uk/docs/python/reference/analytics"
area: "Python"
category: "Reference"
---

# openemail.analytics

Every method in this namespace: its signature, its parameters, what it returns and an example.

## Methods

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

### `analytics.mailbox()`

Read how mail arrives

```python
def mailbox(
    *,
    from_: datetime | str | None = None,
    to: datetime | str | None = None,
    offset_minutes: int | None = None,
    grain: TrackingGrain | None = None,
    address: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> MailboxInsightsResource
```

Returns how mail arrives, as the Analytics page of the app shows it, for a window that is the last 30 days unless `from_=` and `to=` say otherwise: how many conversations arrived and when, per `grain` bucket in `days` and per hour of the day in `hours`, the addresses they arrived at, the senders who wrote most, how many conversations wait on a reply for 1, 3 or 7 days or more, and the folders.

`days` is sparse: a bucket in which nothing arrived has no entry, so a chart must fill the gaps. `offset_minutes=` shifts the boundaries so days and hours break where the reader's do, and `series` holds the per bucket counts of the top addresses and senders so each can be charted.

A key limited to particular addresses counts only the mail that arrived at them, and `address=` narrows everything to one address. An address the key does not reach counts nothing rather than failing.

Scopes: `threads:read`.

**Parameters**

- `from_` (`datetime | str`): The start of the window, as a `datetime` or an ISO 8601 string. Defaults to 30 days before `to`. The SDK sends it as the `from` query parameter.
- `to` (`datetime | str`): The end of the window, as a `datetime` or an ISO 8601 string. Defaults to now.
- `offset_minutes` (`int`): Minutes east of UTC, from -840 to 840, defaulting to 0. Pass `time.localtime().tm_gmtoff // 60` for the local zone.
- `grain` (`TrackingGrain`): Bucket width: `'minute'`, `'hour'` or `'day'`, defaulting to `'day'`.
- `address` (`str`): Count only the mail delivered to this address.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `OpenEmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`MailboxInsightsResource`, a dict with `object` set to `'mailbox_insights'`, `from`, `to`, `grain`, `offsetMinutes`, `scanned`, `days`, `hours`, `addresses`, `senders`, `senderCount`, `waiting`, `unattributed`, `folders` and `series`.

**Example**

```python
import time

from openemail import openemail

insights = openemail.analytics.mailbox(offset_minutes=time.localtime().tm_gmtoff // 60)

print(f'{insights["scanned"]} conversations from {insights["senderCount"]} senders')

for sender in insights['senders']:
    print(sender['email'], sender['count'])
```

**Notes**

- Read only, so the SDK retries it after a network failure or a retryable status, like any other read.
- A `from_` later than `to` raises a 422 `invalid_parameter`.

Also available in: API [`GET /analytics/mailbox`](https://openemail.uk/docs/api/reference/analytics#get-analytics-mailbox); TypeScript [`analytics.mailbox()`](https://openemail.uk/docs/sdk/reference/analytics#mailbox); Ruby [`analytics.mailbox`](https://openemail.uk/docs/ruby/reference/analytics#mailbox); CLI [`openemail analytics mailbox`](https://openemail.uk/docs/cli/reference/analytics#analytics-mailbox).

### `analytics.sending()`

Read what became of sent mail

```python
def sending(
    *,
    days: int | None = None,
    minutes: int | None = None,
    offset_minutes: int | None = None,
    grain: TrackingGrain | None = None,
    address: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> SendingAnalyticsResource
```

Returns the numbers behind the Analytics page of the app: what the workspace sent inside a window and what became of it. `totals` adds up the sends, recipients and test sends and how many were delivered, failed, bounced, complained about, uncertain or still pending, `days` cuts sent, delivered, failed, bounced and complained to `grain` buckets, and `statuses`, `sources`, `senders` and `suppressed` break the window down.

The window is `days=`, 30 by default and at most 365, or `minutes=`, which wins when both are passed. It ends now, reported as `until`, and starts at the beginning of its oldest bucket, reported as `since`. `offset_minutes=` shifts the bucket boundaries so days break where the reader's do.

A key limited to particular addresses counts only the mail sent from them, and `address=` narrows everything to one address.

Scopes: `emails:read`.

**Parameters**

- `days` (`int`): Window length in days, from 1 to 365, defaulting to 30.
- `minutes` (`int`): Window length in minutes, which wins over `days`.
- `offset_minutes` (`int`): Minutes east of UTC, from -840 to 840, defaulting to 0. Pass `time.localtime().tm_gmtoff // 60` for the local zone.
- `grain` (`TrackingGrain`): Bucket width: `'minute'`, `'hour'` or `'day'`, defaulting to `'day'`.
- `address` (`str`): Count only the mail sent from this address.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `OpenEmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`SendingAnalyticsResource`, a dict with `object` set to `'sending_analytics'`, `since`, `until`, `grain`, `offsetMinutes`, `totals`, `days`, `statuses`, `sources`, `senders` and `suppressed`. `totals` holds `sends`, `testSends`, `recipients`, `delivered`, `failed`, `bounced`, `complained`, `uncertain` and `pending`.

**Example**

```python
from openemail import openemail

analytics = openemail.analytics.sending(days=7)
totals = analytics['totals']

print(f'{totals["delivered"]} of {totals["sends"]} delivered, {totals["bounced"]} bounced')
```

**Notes**

- Read only, so the SDK retries it after a network failure or a retryable status, like any other read.

Also available in: API [`GET /analytics/sending`](https://openemail.uk/docs/api/reference/analytics#get-analytics-sending); TypeScript [`analytics.sending()`](https://openemail.uk/docs/sdk/reference/analytics#sending); Ruby [`analytics.sending`](https://openemail.uk/docs/ruby/reference/analytics#sending); CLI [`openemail analytics sending`](https://openemail.uk/docs/cli/reference/analytics#analytics-sending).
