# Statistics

> Source: https://developers.anymail.watch/campaign-stats/

`GET /api/v1/campaigns/{id}/stats` returns the numbers of one campaign in three parts: totals, the funnel from the campaign list and a breakdown by step and A/B variant. No number is computed differently from the app. Totals match the **Stats** tab, the funnel matches the campaign list.

| Method | Path | Action |
|---|---|---|
| `GET` | `/api/v1/campaigns/{id}/stats` | Statistics of a campaign |

```bash
curl "https://app.anymail.watch/api/v1/campaigns/3f2b1c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/stats" \
  -H "Authorization: Bearer $ANYMAIL_TOKEN"
```

**Response `200`**

```json
{
  "campaign_id": "3f2b1c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "totals": {
    "sent": 312,
    "delivered": 305,
    "opened": null,
    "clicked": null,
    "replied": 19,
    "interested": 6,
    "maybe_later": 9,
    "not_interested": 4,
    "autoreplied": 3,
    "bounced": 7,
    "unsubscribed": 2,
    "reply_rate": 0.0609,
    "enrolled": 100,
    "tracking_enabled": false
  },
  "funnel": {
    "contacted": 96,
    "enrolled": 100,
    "contactedPct": 96,
    "delivered": 305,
    "deliveredPct": 98,
    "replyRatio": 0.0609,
    "interested": 6,
    "neutral": 9,
    "negative": 4
  },
  "steps": [
    {
      "position": 1,
      "subject": "Quick question, {{first_name}}",
      "sent": 96,
      "delivered": 93,
      "bounced": 3,
      "replied": 11,
      "interested": 4,
      "maybe_later": 5,
      "opened": null,
      "opened_unique": null,
      "queued": 4,
      "branch": null,
      "variants": [
        { "label": "A", "subject": "Quick question, {{first_name}}", "active": true, "deleted": false, "sent": 48, "delivered": 47, "bounced": 1, "replied": 7, "interested": 3, "maybe_later": 2, "opened": null },
        { "label": "B", "subject": "{{first_name}}, a question about {{company}}", "active": true, "deleted": false, "sent": 48, "delivered": 46, "bounced": 2, "replied": 4, "interested": 1, "maybe_later": 3, "opened": null }
      ]
    }
  ]
}
```

## Totals

| Field | Notes |
|---|---|
| `sent`, `delivered`, `bounced` | Messages. `delivered` is `sent` minus `bounced`. SMTP does not report delivery. |
| `replied` | Replies, without autoresponders. |
| `interested`, `maybe_later`, `not_interested` | Replies by classification. `maybe_later` is the `neutral` class. |
| `autoreplied` | Autoresponders, counted apart from replies. |
| `reply_rate` | `replied / sent` as a fraction from 0 to 1. |
| `enrolled` | People enrolled in the campaign. |
| `opened`, `clicked` | `null` until the tracking domain of the workspace is verified. `null` means not measured. It does not mean zero. |

## Funnel

The funnel mixes two units, as in the app. `contacted` and `enrolled` count people. `delivered` and `replyRatio` count messages.

| Field | Notes |
|---|---|
| `contacted` | People who received at least one message. |
| `contactedPct` | `contacted` as a rounded percentage of `enrolled`. `null` when nobody is enrolled. |
| `deliveredPct` | `delivered` as a rounded percentage of sent messages. |
| `replyRatio` | Replies per sent message, 0 to 1. `null` when nothing was sent. |
| `interested`, `neutral`, `negative` | Replies by classification. |

The funnel keys are in camelCase, unlike the rest of the API. They are the same keys the app uses.

## Steps and variants

`steps` has one row per email step, in order.

| Field | Notes |
|---|---|
| `queued` | Active enrolments that wait for this step. |
| `opened` | Open events for messages of this step, with repeats. `null` without tracking. |
| `opened_unique` | Messages of this step opened at least once, which is the number of people. `null` without tracking. |
| `branch` | `{ "yes": n, "no": n }` when a condition built in the app gates this step, otherwise `null`. |
| `variants` | One row per A/B variant. `deleted: true` marks a variant that was removed after it sent messages, so its history stays visible. |

Unsubscribes have no per step number, because the unsubscribe link is the same on every step.

Treat opens as a weak signal. Apple Mail Privacy Protection opens the tracking pixel without a person.

**Errors:** `404` with `Campaign not found.`, including a campaign from another workspace and an id that is not a UUID.

## Related

- [Campaigns](/campaigns/)
- [Steps and variants](/campaign-steps/)
- [Replies](/replies/)
