---
title: "Get business report summary"
method: GET
path: "/reports/summary"
tags: ["Reports"]
---

# Get business report summary

`GET /reports/summary`

## Request

- Base URL: `https://api.privy.com/v1`
- URL: `https://api.privy.com/v1/reports/summary`
- Auth: HTTP bearer

The business-level performance rollup for a period: signups, new
subscribers, attributed revenue and orders, engagement rates, and
business-wide order and revenue totals for context. Pass
`compare=previous_period` to add previous-period values and typed
change deltas to every metric.

`attributed_revenue` and `attributed_orders` credit the email and SMS
messages Privy sent, under the same last-touch rule as the rest of
Privy's reporting: an order counts when the contact's most recent
engagement in the 7 days before it was an email open, an email click, or
an SMS click. Orders credited to a display signup are excluded, and
every figure here is dated by when the crediting message was **sent**,
not by when the order or the engagement happened. A period's attributed
revenue is therefore the revenue driven by messages sent in that period,
and it includes orders placed after the period closed, whenever the
contact engaged later — so the newest days keep filling in for a while
after the fact. The engagement counts and rates use the same send
window: an open in this period on a message sent last month lands in
last month.

The rates each divide by something different. `open_rate` is opens
counted once per contact per campaign, over email deliveries — SMS
messages have no opens. `click_rate` counts clicks the same way but per
channel, over email and SMS deliveries combined. `unsubscribe_rate` is
unsubscribe and opt-out events, not distinct contacts, over those same
combined deliveries. `order_rate` is attributed orders over delivered
messages. `revenue_per_recipient` divides attributed revenue by
**email** sends only. `signup_rate` is display form submissions over
display views, so it measures on-site capture, not messaging. `signups`
counts form submissions on your displays, while `new_subscribers` counts
contacts becoming subscribed to marketing on either channel from any
source, so the two answer different questions and neither is
de-duplicated by contact.

Periods reaching back before the account's reporting boundary
(2026-07-01 for most accounts, earlier where more history was
backfilled) are served whole — comparison period included — from
Privy's historical rollups instead of the live reporting store. The
rate formulas above still hold, but the basis differs: new
subscribers, every by_channel/by_type split, and `totals_context` are
null; attributed orders and revenue include display-credited orders
and are dated by when the attribution was recorded, not by send time —
so `order_rate`'s numerator counts orders its message denominator
never sent, and reads a little high for accounts with display-credited
orders; and days are bucketed in US Eastern time regardless of the
account's time zone. Treat comparisons that straddle the boundary as
approximate, and say so.

**Required scope:** `reports_read`

## Query parameters

- `period` 'last_7_days' | 'last_30_days' | 'last_90_days' | 'this_month' | 'last_month' | 'custom'
- `start_date` string, date
- `end_date` string, date
- `compare` 'previous_period'

## Headers

- `Privy-Account-Id` string

## Response `200`

The business's performance rollup over the resolved period.

- object
  - `data` object
    - `period` ReportPeriod: The resolved date range the report covers, inclusive, in the account's time zone. Every label except `last_month` ends today, so the last day of the range is still in progress: `last_7_days` is the six days before today plus today, `this_month` runs from the 1st through today, and `last_month` is the whole previous calendar month. Custom ranges cannot exceed 366 days.
      - `label` 'last_7_days' | 'last_30_days' | 'last_90_days' | 'this_month' | 'last_month' | 'custom'
      - `start_date` string, date
      - `end_date` string, date
    - `comparison_period` object, nullable: The previous period of the same length, immediately before the report period. Null unless `compare=previous_period`.
      - `start_date` string, date
      - `end_date` string, date
    - `signups` object: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
      - `by_channel` ReportChannelBreakdown, nullable: Current-period split by channel, in the parent metric's unit. Null when the period reaches before the account's reporting boundary — the historical source cannot credit an order to a single message channel; never treat null as zero. Never carries comparison fields, even when the request asked for one — only the parent metric does. On attributed orders and revenue the two legs never double count, because each order is credited to a single message and so to a single channel. On signups they can: the split is built from what each form captured, so a form that took both an email address and a phone number counts in both legs, and the legs need not add up to the signup total.
        - `email` number
        - `sms` number
    - `new_subscribers` object: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
      - `by_source` object, nullable: New subscribers grouped by signup source (`display`, `import`, `api`, `shopify`, …; `unknown` for unattributed). Current period only. Null means unavailable — the period starts before the account's reporting boundary (2026-07-01 for most accounts, earlier where more history was backfilled) or the breakdown could not be computed; an empty object means genuinely zero. Never treat null as zero.
      - `by_channel` object, nullable: New subscribers by channel (`email`, `sms`). Same availability semantics as `by_source`: null means unavailable — never treat null as zero.
    - `signup_rate` ReportSummaryMetric: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
    - `attributed_revenue` object: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
      - `by_channel` ReportChannelBreakdown, nullable: Current-period split by channel, in the parent metric's unit. Null when the period reaches before the account's reporting boundary — the historical source cannot credit an order to a single message channel; never treat null as zero. Never carries comparison fields, even when the request asked for one — only the parent metric does. On attributed orders and revenue the two legs never double count, because each order is credited to a single message and so to a single channel. On signups they can: the split is built from what each form captured, so a form that took both an email address and a phone number counts in both legs, and the legs need not add up to the signup total.
        - `email` number
        - `sms` number
      - `by_type` ReportTypeBreakdown, nullable: Current-period split by message type, in the parent metric's unit. Null when the period reaches before the account's reporting boundary — the historical source does not carry the split; never treat null as zero. Never carries comparison fields, even when the request asked for one — only the parent metric does. `campaign` counts newsletters, the one-time email and SMS sends. `flow` is broader than the flows in `/v1/flows`: it also covers the account's older automations and the follow-up email or SMS a display sends after a signup. The two legs cover every attributed message, so they add up to the parent metric's value.
        - `campaign` number
        - `flow` number
    - `attributed_orders` object: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
      - `by_channel` ReportChannelBreakdown, nullable: Current-period split by channel, in the parent metric's unit. Null when the period reaches before the account's reporting boundary — the historical source cannot credit an order to a single message channel; never treat null as zero. Never carries comparison fields, even when the request asked for one — only the parent metric does. On attributed orders and revenue the two legs never double count, because each order is credited to a single message and so to a single channel. On signups they can: the split is built from what each form captured, so a form that took both an email address and a phone number counts in both legs, and the legs need not add up to the signup total.
        - `email` number
        - `sms` number
      - `by_type` ReportTypeBreakdown, nullable: Current-period split by message type, in the parent metric's unit. Null when the period reaches before the account's reporting boundary — the historical source does not carry the split; never treat null as zero. Never carries comparison fields, even when the request asked for one — only the parent metric does. `campaign` counts newsletters, the one-time email and SMS sends. `flow` is broader than the flows in `/v1/flows`: it also covers the account's older automations and the follow-up email or SMS a display sends after a signup. The two legs cover every attributed message, so they add up to the parent metric's value.
        - `campaign` number
        - `flow` number
    - `order_rate` ReportSummaryMetric: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
    - `average_order_value` ReportSummaryMetric: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
    - `revenue_per_recipient` ReportSummaryMetric: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
    - `open_rate` ReportSummaryMetric: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
    - `click_rate` ReportSummaryMetric: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
    - `unsubscribe_rate` ReportSummaryMetric: A report metric with previous-period comparison fields. `previous_value`, `change` and `change_type` are null unless the request passed `compare=previous_period`. `change_type` says how to read `change`, and the four values are not interchangeable: `relative` is the percent change (one decimal, e.g. 26.5 means +26.5%) and is used for count and money metrics whenever the previous period was non-zero; `percent_point` is the absolute percentage-point delta and is used for every rate metric (never a relative percent, so a small rate move cannot read as a huge swing); `absolute` is the raw delta in the metric's unit, used when the previous period was zero and this one was not; and `not_comparable` means no delta could be computed, with `change` null. Units follow the `ReportMetric` conventions. A null `value` on a rate metric means the period had no volume to divide by, which is how "no data" is distinguished from a real 0% — though not every rate nulls, so a 0 can still mean either.
      - `value` number, nullable
      - `previous_value` number, nullable
      - `change` number, nullable
      - `change_type` 'relative' | 'percent_point' | 'absolute' | 'not_comparable' | 'null', nullable
      - `unit` string: `count`, `percent`, or a lowercased ISO 4217 currency code.
    - `totals_context` object, nullable: Null when the period reaches before the account's reporting boundary; never treat null as zero. Business-wide (not just Privy-attributed) totals over the period, dated by when each order was placed. They are on a different basis from `attributed_revenue`: `total_revenue` is the order total the store charged, tax included, while attributed revenue excludes tax. An attributed share divided out of these will therefore read a little low, and the two are dated differently — treat it as approximate and say so.
      - `total_orders` integer
      - `total_revenue` number

## Other responses

- `401`: Missing or invalid bearer token.
- `403`: `insufficient_scope` when the token lacks the required scope for this endpoint.
- `422`: One or more fields failed validation.
- `429`: Rate limit exceeded. Retry after the specified time.

## Changes

- **2026-11-05** `cf0885e90d5a`: 8 warning
  - added the new `forbidden` enum value to the `error/code` response property for the response status `401`
  - added the new `forbidden` enum value to the `error/code` response property for the response status `403`
  - added the new `forbidden` enum value to the `error/code` response property for the response status `422`
  - added the new `forbidden` enum value to the `error/code` response property for the response status `429`
  - …4 more
- **2026-11-03** `fe500ab59b3b`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/privy/apis/privy-api/changes/reports/summary/get.md)

---

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