# Revenue API

Read what your campaigns and flows earned, and set how purchases are credited to them.

**Project key.** Acts in the project the key belongs to. An all-access key works too — name the project with an `X-Project-Id` header. See [Authentication](https://emailbump.com/docs/api-keys).

## Endpoints

- `GET /v1/revenue`
- `PATCH /v1/revenue/attribution`

Revenue here is what was credited. A purchase goes to the last campaign or automation email the contact clicked within the attribution window or, if they clicked nothing and the project counts opens, the last one they opened. A purchase no email earned isn't counted. The full rules are in [Revenue attribution](/docs/stripe#attribution).

## Read revenue

`GET /v1/revenue` totals what was credited over a date range, per currency, and names the campaigns and flows that earned the most.

**Query parameters**

- `from` — *string*, optional — First day, inclusive, as a UTC date `YYYY-MM-DD`. Defaults to 29 days before `to`, which makes 30 days.
- `to` — *string*, optional — Last day, inclusive, as a UTC date `YYYY-MM-DD`. Defaults to today, and a later date is read as today.
- `stream` — *string*, optional — `marketing` for campaigns or `automation` for flows. Leave it out for both.

One request covers at most 366 days; a `from` further back than that is moved forward to fit. The response's `from` and `to` are the dates actually read. A date in any other format, or any other `stream`, is a `400`.

```bash
curl "https://emailbump.com/api/v1/revenue?from=2026-08-30&to=2026-09-28" \
  -H "Authorization: Bearer ebk_your_key"
```

## Response

```json
{
  "conversions": 4,
  "amount": 300.0,
  "currency": "USD",
  "by_currency": [
    { "currency": "USD", "conversions": 3, "amount": 300.0 },
    { "currency": "EUR", "conversions": 1, "amount": 40.0 }
  ],
  "leaders": [
    { "kind": "campaign", "id": "5a9f3c1e-2d84-4b7f-9e60-a1c3d5e7f902", "name": "Spring sale", "currency": "USD", "conversions": 2, "amount": 198.0 },
    { "kind": "flow", "id": "9b2e7d41-6c3a-4f85-b0d9-3e1a7c5f2b68", "name": "Welcome series", "currency": "USD", "conversions": 1, "amount": 102.0 },
    { "kind": "flow", "id": "e4c8a2f6-1d7b-4a93-8e05-6b9f3c2d1a70", "name": "Abandoned cart", "currency": "EUR", "conversions": 1, "amount": 40.0 }
  ],
  "attribution": { "window_days": 5, "counts_opens": true },
  "from": "2026-08-30",
  "to": "2026-09-28",
  "stream": null
}
```

**Response fields**

- `conversions` — *integer* — Purchases credited in the range, in every currency.
- `amount` — *number* — The total in `currency`. Amounts are in major units — `58.0` is $58 — rounded to cents.
- `currency` — *string | null* — The currency most purchases were in — not the biggest number, since ¥20,000 isn't more than $10,000. `null` when nothing was credited.
- `by_currency` — *array* — Each currency's `currency`, `conversions` and `amount`, most purchases first. Currencies are never added together.
- `leaders` — *array* — The ten campaigns and flows that earned the most — those in the main `currency` first, by amount, then the rest: `kind` (`campaign` or `flow`), `id`, `name`, `currency`, `conversions` and `amount`. One that earned in two currencies has a row for each. `name` is `null` once the campaign or flow has been deleted.
- `attribution` — *object* — The project's rules as they are now: `window_days` and `counts_opens`.
- `from`, `to` — *string* — The dates read, after defaults and limits.
- `stream` — *string | null* — The stream asked for, or `null` for both.

The same revenue is in the dashboard: the Revenue tile and **Top earning emails** on **Analytics**, each campaign's **Metrics** tab, and each send step of a flow.

## Attribution rules

`PATCH /v1/revenue/attribution` sets the window and whether opens count — the same settings as **Settings → Revenue attribution**. A change applies to purchases from then on; revenue already credited stays where it is.

**Body parameters**

- `window_days` — *integer*, optional — How many days before a purchase a click or open can earn it, from 1 to 30. It is 5 until you change it.
- `counts_opens` — *boolean*, optional — Whether an open can earn a purchase when nothing was clicked. On until you change it. Machine opens never count either way.

Send either or both; one you leave out keeps its value. A window outside 1–30 is a `400`, and so is any other field.

```bash
curl -X PATCH https://emailbump.com/api/v1/revenue/attribution \
  -H "Authorization: Bearer ebk_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "window_days": 7, "counts_opens": false }'
```

```json
{
  "attribution_window_days": 7,
  "attribution_counts_opens": false
}
```

## Where revenue comes from

- **Your own events.** Send `POST /v1/events` with a `value` above zero and its `currency`. The response's `attribution` says which email earned it. See the [Events API](/docs/events-api).
- **Stripe.** Connect the project's Stripe account and its payments are recorded as they happen and credited the same way. A subscription's routine renewal is recorded but not credited. See the [Stripe guide](/docs/stripe), or connect it from code with the [Stripe API](/docs/stripe-api).
