---
title: "Fetch Email Broadcast Stats"
method: GET
path: "/emails/broadcasts/{broadcast_id}/stats"
tags: ["Emails::Broadcast"]
---

# Fetch Email Broadcast Stats

`GET /emails/broadcasts/{broadcast_id}/stats`

## Request

- Base URL: `https://myworkspace.myclickfunnels.com/api/v2`
- URL: `https://myworkspace.myclickfunnels.com/api/v2/emails/broadcasts/{broadcast_id}/stats`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Authorization code: `https://accounts.myclickfunnels.com/oauth/authorize`
    - Token URL: `https://accounts.myclickfunnels.com/oauth/token`
- TypeScript: <https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/docs/emails/broadcasts/:broadcast_id/stats/get.ts> (a function with typed inputs; its response is checked against the schema)

Delivery progress, engagement and revenue for one email broadcast, the same numbers as
the broadcast's page in the ClickFunnels dashboard.

The numbers cover the broadcast's send window, returned as `timerange`: from when
sending began until two weeks after it completed, or until now while it has not
completed, capped at 90 days after sending began. A broadcast that has not started
sending reports the last 90 days, with every number zero. There are no timerange parameters;
the `timerange_start` and `timerange_end` parameters of the funnel and page stats
endpoints are refused with a 422 rather than silently ignored.

Counts are unique contacts, except `opened` and `clicked`, which count every event.
Rates are whole percentages (0-100) of the audience (`progress.total`), rounded to the
nearest integer, so a share under 0.5% reads 0 next to a non-zero count; the counts are
authoritative. `click_to_open_rate` is unique clicks over unique opens. Revenue is
attributed to the broadcast when the buyer reached the order through one of its links,
summed across every send of the broadcast. Only live-mode transactions in the workspace
currency are counted (a workspace with no currency set has nothing to filter on, so
`currency` is `null` and every currency is summed); test-mode orders are excluded.

`progress.total` is the audience size recorded when the broadcast sent, summed over every
send of the broadcast, and is `null` before the first send has run. Stats are cached for a
few minutes while a broadcast is sending and longer once it has completed.

The split-test variants and the winner are on the broadcast record itself
(`GET /api/v2/emails/broadcasts/{id}`). Add `expand[]=variants` for each variant's numbers:
recipients, bounces, unique clicks, unsubscribes and spam complaints, reported separately for
the split test and for the winner's send to the rest of the audience, so variants are
compared on the test alone. Only the open pixel identifies a variant, so these are derived
from the record of which contacts were sent which variant. That record is removed 30 days
after the broadcast completes, and from then on `test` and `winner_send` are `null`; read
them once the two-week stats window has closed and within 30 days of completion. Expanding variants can take a
few seconds on a large broadcast the first time; the result is cached like the other numbers.

## Path parameters

- `broadcast_id` string, required

## Query parameters

- `expand[]` string[]

## Response `200`

OK

- EmailsBroadcastStatsAttributes: Delivery progress, engagement and revenue for one email broadcast over its send window. Counts are unique contacts unless noted; rates are whole percentages (0-100); money is a decimal string in `currency`.
  - `broadcast` object: The broadcast these stats belong to
    - `id` integer: Broadcast ID
    - `public_id` string, nullable: Broadcast public ID
    - `name` string, nullable: Internal name for the broadcast
  - `currency` string, nullable: ISO 4217 currency code for all monetary values (e.g. USD, EUR). `null` when the workspace has no currency set; `revenue` then sums every currency the broadcast's orders were paid in.
  - `timerange` object: The send window the stats cover
    - `from` string, date-time, nullable: When sending began. For a broadcast that has not started sending, 90 days before `to`; every number is then zero.
    - `to` string, date-time: End of the window, two weeks after sending completed, or now while the broadcast has not completed, capped at 90 days after sending began.
  - `progress` object: How far delivery has got
    - `total` integer, nullable: Audience size recorded when the broadcast sent, summed over every send of the broadcast (a send in the contacts' time zones has one per zone). `null` until the first send has run.
    - `queued` integer: Contacts in batches that have not started sending yet (scheduled, waiting for the split-test winner, paused, or halted by a deliverability health check)
    - `processing` integer: Contacts in batches being sent right now
    - `sent` integer: Contacts the email was sent to
    - `failed` integer: Contacts whose delivery failed
  - `performance` object: Engagement over the send window. Rates are rounded to whole percentages, so a share under 0.5% reads 0 next to a non-zero count; the counts are authoritative.
    - `delivered` integer: Contacts the email was sent to (the same number as `progress.sent`)
    - `bounced` integer: Contacts whose address bounced
    - `opened` integer: Total opens, counting repeat opens by the same contact
    - `unique_opens` integer: Contacts who opened at least once
    - `clicked` integer: Total clicks, counting repeat clicks by the same contact
    - `unique_clicks` integer: Contacts who clicked at least once
    - `unsubscribed` integer: Contacts who unsubscribed from this email
    - `spam_complaints` integer: Contacts who reported this email as spam
    - `open_rate` integer: Unique opens as a whole percentage (0-100) of the audience
    - `click_rate` integer: Unique clicks as a whole percentage (0-100) of the audience
    - `click_to_open_rate` integer: Unique clicks as a whole percentage (0-100) of unique opens
    - `bounce_rate` integer: Bounces as a whole percentage (0-100) of the audience
    - `unsubscribe_rate` integer: Unsubscribes as a whole percentage (0-100) of the audience
  - `revenue` object: Orders attributed to the broadcast, meaning the buyer reached the order through one of its links, summed across every send of the broadcast. Only live-mode transactions in the workspace currency are counted; a workspace with no currency set (`currency` is `null`) has every currency summed.
    - `total` string: Revenue attributed to the broadcast (paid minus refunded), as a decimal string in `currency`
    - `orders_count` integer: Orders with at least one paid transaction attributed to the broadcast
    - `per_recipient` string: Revenue divided by the audience, as a decimal string in `currency`
    - `per_unique_open` string: Revenue divided by unique opens, as a decimal string in `currency`
    - `per_unique_click` string: Revenue divided by unique clicks, as a decimal string in `currency`
  - `variants` object[]: Only with `expand[]=variants`. One entry per split-test variant, in the order the broadcast lists them; empty for a broadcast that is not a split test. Counts are unique contacts over the same window as `performance`. Only contacts found in the record of who was sent which variant are attributed, so the variants add up to at most `performance` (a contact deleted since the send counts there but in no variant). Opens are not split by variant here; each variant's `open_count` is on the broadcast record.
    - `subject` string, nullable: The variant's subject line
    - `preheadline` string, nullable: The variant's preview text
    - `main` boolean: Whether this is the broadcast's main variant
    - `winner` boolean, nullable: Whether this variant won the split test; `null` until the test has closed
    - `test` object, nullable: The split test itself, where each variant went to its own share of the audience. Compare variants on these numbers. `null` once the broadcast's send records are removed, 30 days after it completes.
      - `recipients` integer: Contacts scheduled to get this variant in this phase, including any skipped at send time because they had unsubscribed or were suppressed by then
      - `bounced` integer: Recipients whose address was marked bad
      - `unique_clicks` integer: Recipients who clicked a link
      - `unsubscribed` integer: Recipients who unsubscribed
      - `spam_complaints` integer: Recipients who reported the email as spam
    - `winner_send` object, nullable: The winner's send to the rest of the audience after the test closed. Set only on the winning variant, and `null` on the others, before the test closes, and once the send records are removed (30 days after the broadcast completes).
      - `recipients` integer: Contacts scheduled to get this variant in this phase, including any skipped at send time because they had unsubscribed or were suppressed by then
      - `bounced` integer: Recipients whose address was marked bad
      - `unique_clicks` integer: Recipients who clicked a link
      - `unsubscribed` integer: Recipients who unsubscribed
      - `spam_complaints` integer: Recipients who reported the email as spam

## Other responses

- `401`: Unauthorized
- `403`: Forbidden — the token's scopes don't grant read access to emails. Not retryable.
- `404`: Not Found — broadcast not found
- `422`: Unprocessable Entity — a `timerange_start` or `timerange_end` parameter was given. Broadcast stats always cover the broadcast's own send window (returned as `timerange`), so the parameter is refused rather than silently ignored. Remove it and read `timerange` from the response.
- `503`: Service Unavailable — a stats query exceeded the database timeout, or a dependency was briefly unavailable. Retryable; the numbers are cached once a query completes, so a retry shortly after is usually cheap.

## Changes

- **2026-11-03** `511d88b30aea`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/changes/emails/broadcasts/:broadcast_id/stats/get.md)

---

[API](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api.md) - [All operations](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/llms.txt) - [OpenAPI document](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/revisions/511d88b30aea?raw)
