Statistics
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 |
curl "https://app.anymail.watch/api/v1/campaigns/3f2b1c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/stats" \
-H "Authorization: Bearer $ANYMAIL_TOKEN"
const res = await fetch("https://app.anymail.watch/api/v1/campaigns/3f2b1c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/stats", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.ANYMAIL_TOKEN}`,
},
});
console.log(res.status, await res.text());
import os
import requests
response = requests.request(
"GET",
"https://app.anymail.watch/api/v1/campaigns/3f2b1c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/stats",
headers={
"Authorization": f"Bearer {os.environ['ANYMAIL_TOKEN']}",
},
)
print(response.status_code, response.text)
Response 200
{
"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.