---
title: "Broadcast statistics"
description: "How the broadcast performed: copies sent, delivered, bounced, reported as spam and failed, and how many people opened, clicked and unsubscribed, as totals and as a series cut to `grain`."
url: "https://openemail.uk/docs/api/broadcasts/stats"
area: "API"
category: "Mailbox"
---

# Broadcast statistics

How the broadcast performed: copies sent, delivered, bounced, reported as spam and failed, and how many people opened, clicked and unsubscribed, as totals and as a series cut to `grain`.

`GET /broadcasts/{id}/stats`

## GET /broadcasts/{id}/stats

How the broadcast performed: copies sent, delivered, bounced, reported as spam and failed, and how many people opened, clicked and unsubscribed, as totals and as a series cut to `grain`.

## Parameters

- `id` (string, required): In the path. A `brd_` id from `POST /broadcasts` or `GET /broadcasts`.
- `grain` (string): Bucket width of the series: `minute`, `hour` or `day`. Defaults to `hour`.
- `offsetMinutes` (integer): Minutes east of UTC to cut the buckets in, from -840 to 840. Defaults to 0. Pass `-new Date().getTimezoneOffset()` for the local zone.

## Example

Needs `emails:read`.

**curl**

```
curl "$OE/broadcasts/brd_5a8c1e3f7b2d94a06c8e1f3b/stats?grain=day" -H "$AUTH"
```

**Response**

```
{
  "object": "broadcast_stats",
  "broadcastId": "brd_5a8c1e3f7b2d94a06c8e1f3b",
  "grain": "day",
  "totals": {
    "recipients": 412,
    "pending": 0,
    "sent": 410,
    "delivered": 404,
    "bounced": 4,
    "complained": 1,
    "failed": 2,
    "opened": 187,
    "clicked": 52,
    "unsubscribed": 3,
    "opens": 296,
    "clicks": 71
  },
  "series": [
    { "bucket": "2026-09-23", "delivered": 404, "opened": 161, "clicked": 45, "unsubscribed": 3 },
    { "bucket": "2026-09-24", "delivered": 0, "opened": 26, "clicked": 7, "unsubscribed": 0 }
  ]
}
```

> `opened`, `clicked` and `unsubscribed` count people, while `opens` and `clicks` count events. `pending` counts the copies still queued, scheduled or sending, and `failed` the copies that failed or were cancelled.

> `series` is sparse and oldest first: one bucket per `grain` in which something happened. It counts each person once, at the first time it happened to them, so it adds up to the totals.

> `bucket` is `YYYY-MM-DD`, `YYYY-MM-DDTHH` or `YYYY-MM-DDTHH:MM`, in the offset asked for.

## Refusals

| Status | Code | When |
| --- | --- | --- |
| 400 | `invalid_cursor` | On the recipients list, a `cursor` that list did not hand out. |
| 403 | `insufficient_scope` | The key does not hold `emails:read`. |
| 404 | `broadcast_not_found` | The id names no broadcast in this workspace, or the key is limited to particular addresses or domains and the broadcast was sent from one it does not hold. |
| 404 | `recipient_not_found` | On `GET /broadcasts/{id}/recipients/{emailId}`, an `emailId` that is not a copy of this broadcast. |
