---
title: "Get campaign stats"
method: GET
path: "/v1/loyalty/campaigns/{id}/stats"
tags: ["Loyalty"]
---

# Get campaign stats

`GET /v1/loyalty/campaigns/{id}/stats`

## Request

- Base URL: `https://api.prod.keyban.io`
- URL: `https://api.prod.keyban.io/v1/loyalty/campaigns/{id}/stats`
- Auth: API key in header `X-Api-Key`

Aggregated outcome of a campaign once it has started sending: a per-status delivery tally (sent, failed, excluded by frequency cap or opt-out) and a revenue-free conversion proxy (recipients notified, recipients who then visited within the conversion window, and the resulting rate). Computed live from the per-recipient deliveries and visits, so the figures keep moving until the conversion window closes; the campaign is then transitioned to finished by an hourly sweeper (so up to ~1h after the window ends). All zero for a campaign that has not started sending.

## Path parameters

- `id` string, uuid, required

## Response `200`

Campaign stats computed successfully

- CampaignStatsDto
  - `sent` integer, required: Notifications accepted by a wallet platform, counted per delivered channel. A recipient reachable on both wallets counts twice.
  - `failed` integer, required: Notifications a wallet platform rejected, counted per failed channel. Retriable per recipient.
  - `excludedFrequencyCap` integer, required: Deliveries skipped because the loyalty card had already reached the rolling per-card notification cap.
  - `excludedOptOut` integer, required: Deliveries skipped because the customer has no marketing opt-in (GDPR consent missing or withdrawn).
  - `excludedNoCard` integer, required: Deliveries skipped because the recipient has no wallet card on the targeted channel (no Apple pass, or Google card never added). Not a failure — the channel was simply unreachable.
  - `notified` integer, required: Distinct recipients (loyalty cards) reached by at least one accepted notification. This is the conversion denominator.
  - `activated` integer, required: Distinct notified recipients who recorded at least one visit within the conversion window after being notified. Proxy signal: a visit correlated in time, NOT proven causation and with no revenue attribution.
  - `conversionRate` number, required: activated / notified, as a fraction in [0, 1]. 0 when no recipient was notified.
  - `revenueCents` integer, required: Revenue attributed to the campaign, in cents of `currency`: sum of indexer order prices placed by notified recipients, deduplicated per order. Uses the SAME conversion window as `activated` — anchored on each recipient's earliest `sent_at` — so both metrics cover the identical period. Time-correlated attribution, NOT proven causation. 0 when no order matches or no indexer data is available for the networks involved.
  - `currency` 'EUR' | 'USD', required: ISO 4217 currency of `revenueCents`, read from the application LoyaltySettings (defaults to EUR when the application has none). A single currency per application: order prices from every targeted network are summed under this one currency.

---

[API](https://skmtc.dev/keyban/apis/keyban-rest-apis.md) · [All operations](https://skmtc.dev/keyban/apis/keyban-rest-apis/llms.txt) · [OpenAPI document](https://skmtc.dev/keyban/apis/keyban-rest-apis/revisions/0bb79a1da961?raw)
