Analytics & Reports API
These read-only endpoints let you pull your account’s activity into your own dashboards and reports: message-event counts, credit consumption, AI spend, and the same charts and insights the in-app dashboard shows. This guide covers:
- Summary — message-volume counters (sent, delivered, read, replied, booked, contacts created, credits).
- Credits — a detailed, paginated ledger of credit usage with totals and breakdowns.
- AI cost — a per-day rollup of AI spend.
- Metric series — a chart-ready time series for one or more metrics, grouped by campaign, channel, AI Agent, or number.
- Conversation outcomes — how conversations ended, by AI-assigned outcome tag.
- Dashboard insights and Dashboard AI insights — the full data behind the in-app dashboard, including AI-written summaries.
- Entity activity — a single contact’s, deal’s, or task’s timeline.
- Aggregated event counts — a legacy, camelCase form of Summary kept for existing integrations.
Every endpoint on this page needs an exact scope, not both: pass at most one of campaign_id (legacy) or agent_id where the endpoint accepts it. Sending both returns 400, and an id that is not on your account returns 404 rather than 403, so other accounts’ ids stay unguessable.
All paths below are relative to the API base URL:
https://api.youraiconnector.com/v1
Every request must be authenticated. See Authentication for the four accepted methods. The examples here use the X-API-Key header (and one query-parameter form for cURL).
Date range
All three endpoints accept the same optional date filters:
| Parameter | Description |
|---|---|
from |
Start of the range, YYYY-MM-DD, inclusive. Defaults to 30 days ago. |
to |
End of the range, YYYY-MM-DD, inclusive. Defaults to today. |
Dates are interpreted in UTC. The range defaults to the last 30 days and is capped at 366 days — a wider range returns 400. from must not be after to.
The truncated flag
The Summary and Credits endpoints cap how many records a single request scans. If your range is busy enough to hit that cap, the response includes "truncated": true. When you see it, the numbers are based on a partial scan — narrow your date range (or page through with a smaller window) to get complete figures.
Note: Cost and token figures are only included for AI calls billed to your own provider API keys. When cost figures are hidden for your account, the response sets "costs_redacted": true and the cost fields are returned as zero.
Message volume summary
Returns aggregated message-event counters for your account, both as range totals and as a per-day series. Every day in the range appears in by_date — quiet days are zero-filled. Optionally filter to a single campaign with campaign_id.
GET /analytics/summary
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. |
to |
No | Range end, YYYY-MM-DD. |
campaign_id |
No | Only count events belonging to this campaign. |
cURL
curl "https://api.youraiconnector.com/v1/analytics/summary?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/summary?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/summary",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"totals": {
"total": 1240,
"sent": 800,
"delivered": 760,
"read": 540,
"replied": 210,
"booked": 35,
"contact_created": 120,
"credits_spent": 412.5,
"credits_recharged": 500
},
"by_date": [
{
"date": "2026-05-01",
"total": 40,
"sent": 25,
"delivered": 24,
"read": 18,
"replied": 7,
"booked": 1,
"contact_created": 4,
"credits_spent": 13.5,
"credits_recharged": 0
}
],
"truncated": false
}
Each entry in by_date has the same counter fields as totals, plus a date.
If you pass a campaign_id that does not belong to your account, the response is 404 with { "success": false, "error": "Campaign not found" }.
Credit usage
Returns credit usage over the range: a paginated list of individual records, plus range totals and breakdowns by reason and by campaign.
GET /analytics/credits
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. |
to |
No | Range end, YYYY-MM-DD. |
campaign_id |
No | Only include usage attributed to this campaign. |
limit |
No | Page size for records, 1–100. Defaults to 50. |
cursor |
No | Pass the previous page’s next_cursor to fetch the next page. |
Adjustments vs. consumption: Balance changes such as bonuses, plan renewals, and corrections are excluded from
totalsand the breakdowns — they are not real consumption. They still appear in therecordslist, flagged with"is_adjustment": true.
Totals and breakdowns appear only on the first page (when no cursor is supplied). On later pages, totals, by_reason, by_reason_cost, and by_campaign are returned as null — only the records array continues. This avoids re-scanning the whole range for every page.
cURL
curl "https://api.youraiconnector.com/v1/analytics/credits?from=2026-05-01&to=2026-05-31&limit=50&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({
from: "2026-05-01",
to: "2026-05-31",
limit: "50",
});
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/credits?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
// To page: pass data.next_cursor as ?cursor on the next request, until it is null.
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/credits",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31", "limit": 50},
)
data = res.json()
# To page: pass data["next_cursor"] as cursor on the next request, until it is None.
Response (first page)
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"totals": {
"credits_used": 412.5,
"cost_usd": 1.284512,
"records": 318
},
"by_reason": {
"AI Message": 380.0,
"Campaign Message": 32.5
},
"by_reason_cost": {
"AI Message": 1.284512,
"Campaign Message": 0
},
"by_campaign": {
"Spring Promo": 250.0,
"Reactivation": 162.5
},
"records": [
{
"id": "rec_abc123",
"amount": 1,
"timestamp": "2026-05-31T14:02:11.000Z",
"reason": "AI Message",
"is_adjustment": false,
"campaign_id": "campaign123",
"campaign_name": "Spring Promo",
"contact_id": "contact456",
"contact_name": "Jane Smith",
"credit_type": "ai",
"custom_keys_used": false,
"description": null,
"cost_usd": 0,
"input_tokens": 0,
"output_tokens": 0,
"cache_read_tokens": 0,
"cache_creation_tokens": 0,
"ai_model": null,
"request_id": null,
"is_test": false
}
],
"next_cursor": "rec_abc123",
"costs_redacted": false,
"truncated": false
}
Field notes:
amount— credits charged for the record. Zero for records billed to your own provider API key.is_adjustment—truefor balance changes (excluded from totals/breakdowns).cost_usd,input_tokens,output_tokens,cache_read_tokens,cache_creation_tokens,ai_model,request_id— populated only on records billed to your own provider API key; zero ornullotherwise.is_test—truefor playground/test runs, which are never billed.next_cursor— the cursor for the next page, ornullwhen there are no more records.
AI cost rollup
Returns the per-day AI spend rollup for your account. This reads pre-aggregated daily totals, so it is fast even over long ranges. Every day in the range appears in days — quiet days are zero-filled.
GET /analytics/ai-cost
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. |
to |
No | Range end, YYYY-MM-DD. |
cURL
curl "https://api.youraiconnector.com/v1/analytics/ai-cost?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/ai-cost?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/ai-cost",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"totals": {
"total_usd": 12.4821,
"byok_usd": 12.4821,
"platform_usd": 0,
"calls": 4210
},
"days": [
{
"date": "2026-05-01",
"total_usd": 0.4012,
"byok_usd": 0.4012,
"platform_usd": 0,
"input_usd": 0.18,
"output_usd": 0.19,
"cache_creation_usd": 0.02,
"cache_read_usd": 0.0112,
"calls": 140,
"by_provider": { "anthropic": 0.4012 }
}
],
"costs_redacted": false
}
Field notes:
byok_usd— spend billed to your own provider API keys.platform_usd— the portion of spend that ran on the platform rather than your own key.input_usd,output_usd,cache_creation_usd,cache_read_usd— the cost components that make uptotal_usd.by_provider— USD spend keyed by AI provider name.- USD figures are only returned to accounts that use their own provider key. For credit-paying accounts every USD field is zero and
costs_redactedistrue(call counts stay visible).
Metric series
Returns one or more metric time series in one call, optionally grouped by up to two dimensions — the endpoint to bind a chart to. A single request can answer “sent and replied per day, per channel, for this campaign” without one call per campaign.
GET /analytics/series
Every response carries a labels array (the time axis, zero-filled across the whole range) and one entry in series per group, each holding one array per requested metric aligned to labels. Series past limit are not dropped — they collapse into other_bucket, computed as the range total minus the returned series, so a rendered chart always adds up to your real numbers; truncated is true whenever that happens.
Where the numbers come from: sent, delivered, read, and replied come from message records, which carry the channel and sending number. booked, contact_created, and credits_spent come from the event stream, which carries no sending number, so those metrics land in the null-number bucket when you group by number.
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. Defaults to 30 days ago. |
to |
No | Range end, YYYY-MM-DD. Defaults to today. |
metrics |
No | Comma-separated list from sent, ai_sent, human_sent, delivered, read, replied, booked, contact_created, credits_spent. Defaults to sent,replied. An unknown metric returns 400. |
group_by |
No | Comma-separated list of up to two dimensions from date, campaign, channel, agent, number. date is accepted but has no effect — every response already carries the time axis. Omit for a single account-wide series. |
granularity |
No | day (default), week, or month. Week buckets start on Monday, month buckets on the 1st. |
limit |
No | How many series to return before the rest collapse into other_bucket, 1–50. Defaults to 12. |
campaign_id |
No | Only count activity belonging to this campaign. Legacy; prefer agent_id. |
agent_id |
No | Only count activity belonging to this AI Agent. |
channel |
No | Only count activity on this channel, for example whatsapp. |
This endpoint’s date range is capped at 92 days (tighter than the 366-day cap used elsewhere on this page).
cURL
curl "https://api.youraiconnector.com/v1/analytics/series?from=2026-05-01&to=2026-05-31&metrics=sent,replied,booked&group_by=campaign,channel&limit=10&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({
from: "2026-05-01",
to: "2026-05-31",
metrics: "sent,replied,booked",
group_by: "campaign,channel",
limit: "10",
});
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/series?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/series",
headers={"X-API-Key": "YOUR_API_KEY"},
params={
"from": "2026-05-01",
"to": "2026-05-31",
"metrics": "sent,replied,booked",
"group_by": "campaign,channel",
"limit": 10,
},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"granularity": "day",
"labels": ["2026-05-01", "2026-05-02"],
"group_by": ["campaign", "channel"],
"metrics": ["sent", "replied", "booked"],
"series": [
{
"key": {
"campaign_id": "campaign123",
"campaign_name": "Spring Promo",
"channel": "whatsapp"
},
"total": 812,
"metrics": {
"sent": [40, 35],
"replied": [12, 9],
"booked": [2, 1]
}
}
],
"other_bucket": {
"series_count": 6,
"total": 340,
"metrics": {
"sent": [18, 20],
"replied": [5, 6],
"booked": [0, 1]
}
},
"truncated": true
}
Field notes:
key— the identity of one series. Only the keys for the requestedgroup_bydimensions are present; a dimension whose value is unknown for a row (a message with no campaign, an event with no channel) comes back asnullrather than being dropped, so series still add up to the totals.other_bucket—nullwhen nothing was collapsed.- This endpoint returns
503with"error_code": "analytics_unavailable"when the reporting database cannot answer for your account, rather than a200full of zeros — a zeroed chart would read as fact.
Conversation outcomes
Returns how conversations ended over a date range: a per-day count for each outcome tag the AI assigned, plus range totals for replies, bookings, handovers to a human, and conversations the AI never classified.
GET /analytics/outcomes
Pass group_by=tag to collapse the time axis and get range totals per tag only — in that mode labels is empty and each tag’s counts array is empty, while total is still populated.
| Parameter | Required | Description |
|---|---|---|
from |
No | Range start, YYYY-MM-DD. Defaults to 30 days ago. |
to |
No | Range end, YYYY-MM-DD. Defaults to today. |
campaign_id |
No | Only count conversations with contacts currently on this campaign. Legacy; prefer agent_id. |
agent_id |
No | Only count outcomes belonging to this AI Agent. |
group_by |
No | date (default) keeps the per-day counts; tag collapses to range totals. |
This endpoint’s date range is capped at 92 days.
cURL
curl "https://api.youraiconnector.com/v1/analytics/outcomes?from=2026-05-01&to=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ from: "2026-05-01", to: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/outcomes?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/outcomes",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"from": "2026-05-01", "to": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"from": "2026-05-01",
"to": "2026-05-31",
"group_by": "date",
"labels": ["2026-05-01", "2026-05-02"],
"by_tag": [
{ "tag": "interested", "total": 84, "counts": [3, 5] },
{ "tag": "not_interested", "total": 40, "counts": [1, 2] },
{ "tag": null, "total": 12, "counts": [0, 1] }
],
"totals": {
"sessions": 260,
"replied": 210,
"booked": 35,
"human_alerted": 18,
"unresolved": 12
}
}
Field notes:
by_tag[].tag—nullfor conversations the AI never assigned an outcome tag to.totals.human_alerted— conversations handed over to a human; this is written on every handover and was not previously surfaced by any endpoint.- Same
503/analytics_unavailableposture as Metric series when the reporting database cannot answer.
Dashboard insights
Returns the full dashboard payload for a date range in one call: a reply-rate heatmap by weekday and hour, the campaign leaderboard, per-channel volume, exact per-connection totals, per-day metric breakdowns (account-wide, per channel, and per number), where contacts are from, inbox response time, and a recent activity feed. This is the richest reporting payload on the API — it powers the in-app dashboard directly.
GET /analytics/dashboard-insights
| Parameter | Required | Description |
|---|---|---|
startDate |
Yes | Range start, YYYY-MM-DD. |
endDate |
Yes | Range end, YYYY-MM-DD. |
campaignId |
No | Only include activity belonging to this campaign (campaign_id also accepted). Legacy; prefer agent_id. |
agent_id |
No | Only include activity belonging to this AI Agent (agentId also accepted). Under an agent scope, the campaign leaderboard is built from that agent’s activity only. |
This endpoint uses startDate/endDate (not from/to) because it shares its implementation with the in-app dashboard. The range is capped at 92 days and is clamped, not rejected, when it is wider.
Null means unavailable, not zero. Several blocks (
numberStats,channelDailySeries,metricDailyBreakdown,contactsByCountry) are computed from the reporting database and come backnullwhen it cannot answer for your account. Do not render anullblock as an empty chart.
cURL
curl "https://api.youraiconnector.com/v1/analytics/dashboard-insights?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ startDate: "2026-05-01", endDate: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/dashboard-insights?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/dashboard-insights",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"startDate": "2026-05-01", "endDate": "2026-05-31"},
)
data = res.json()
Response (abridged — this payload is large; see the API Reference for the full schema)
{
"success": true,
"data": {
"heatmap": {
"buckets": [
{ "weekday": 1, "hour": 9, "sent": 12, "replied": 5, "replyRate": 0.42 }
]
},
"topCampaigns": [
{ "campaignId": "campaign123", "name": "Spring Promo", "sent": 420, "replied": 180, "booked": 22, "replyRate": 0.43, "creditsSpent": 210.5 }
],
"channelVolume": [
{ "channel": "whatsapp", "sent": 800, "received": 540, "lastMessageAt": "2026-05-31T14:02:11.000Z" }
],
"inboxSla": { "medianFirstResponseMs": 92000, "sampleSize": 140 },
"activityFeed": [
{ "id": "evt_1", "kind": "booked", "at": "2026-05-31T14:02:11.000Z", "contactId": "contact456", "contactName": "Jane Smith", "campaignId": "campaign123", "campaignName": "Spring Promo", "label": "Jane Smith booked an appointment" }
],
"numberStats": null,
"channelDailySeries": null,
"metricDailyBreakdown": null,
"contactsByCountry": null,
"ai_human_split": null
}
}
Field notes:
heatmap.buckets[].weekday—0is Sunday through6is Saturday.numberStats,channelDailySeries,metricDailyBreakdown,contactsByCountry,ai_human_split— each independentlynullwhen the reporting database is unavailable for your account; every other block still returns.
Dashboard AI insights
Returns three short, AI-written insights about the account’s messaging over a date range: one win, one thing to watch, and one tip — sentences you can paste straight into a report rather than numbers you still have to interpret. Generated from the account’s own message metrics only.
GET /analytics/dashboard-ai-insights
| Parameter | Required | Description |
|---|---|---|
startDate |
Yes | Range start, YYYY-MM-DD. |
endDate |
Yes | Range end, YYYY-MM-DD. |
This endpoint is account-wide — it takes no campaign or agent scope.
cURL
curl "https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ startDate: "2026-05-01", endDate: "2026-05-31" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/dashboard-ai-insights",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"startDate": "2026-05-01", "endDate": "2026-05-31"},
)
data = res.json()
Response
{
"success": true,
"data": {
"insights": [
{ "tone": "win", "title": "Reply rate is up", "detail": "Your reply rate climbed to 43% this period, up from 36% the period before." },
{ "tone": "watch", "title": "Bookings slowed midweek", "detail": "Wednesday bookings dropped to a third of Monday's, worth a look at your Wednesday follow-up timing." },
{ "tone": "tip", "title": "Re-send to non-repliers", "detail": "212 contacts received a message but never replied — a short follow-up template often recovers 10-15% of them." }
]
}
}
Missing startDate or endDate returns 400.
Entity activity timeline
Returns a single contact’s, deal’s, or task’s activity as one timeline, newest first: what happened and when, across messages, appointments, notes, and status changes. Use it to answer “what has happened with this person” without stitching several list endpoints together.
GET /analytics/entity-activity
| Parameter | Required | Description |
|---|---|---|
entityType |
Yes | contact, deal, or task. |
entityId |
Yes | ID of the record whose timeline to return. |
cURL
curl "https://api.youraiconnector.com/v1/analytics/entity-activity?entityType=contact&entityId=contact456&apiKey=YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ entityType: "contact", entityId: "contact456" });
const res = await fetch(`https://api.youraiconnector.com/v1/analytics/entity-activity?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/analytics/entity-activity",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"entityType": "contact", "entityId": "contact456"},
)
data = res.json()
Response
{
"success": true,
"data": {
"items": [
{
"id": "evt_9",
"kind": "appointment_booked",
"at": "2026-05-31T14:02:11.000Z",
"label": "Booked an appointment for June 3",
"detail": "Consultation call, 30 minutes"
},
{
"id": "evt_8",
"kind": "message_replied",
"at": "2026-05-31T13:58:02.000Z",
"label": "Replied: \"Yes, that time works\""
}
]
}
}
A missing or invalid entityType/entityId returns 400. An entity that does not exist on your account returns 404, so other accounts’ ids stay unguessable.
Aggregated event counts (legacy)
Returns the same aggregated event counts as Message volume summary, but in the camelCase shape (contactCreated rather than contact_created, byDate rather than by_date) some older integrations were built against. Prefer /analytics/summary for new integrations — this endpoint exists only so the in-app dashboard and the API share one implementation.
GET /analytics/aggregate
| Parameter | Required | Description |
|---|---|---|
startDate |
No | Range start, ISO date or date-time. Defaults to the same window /analytics/summary uses. |
endDate |
No | Range end, ISO date or date-time. |
campaignId |
No | Only count events belonging to this campaign (campaign_id also accepted). Legacy; prefer agent_id. |
agent_id |
No | Only count events belonging to this AI Agent (agentId also accepted). |
cURL
curl "https://api.youraiconnector.com/v1/analytics/aggregate?startDate=2026-05-01&endDate=2026-05-31&apiKey=YOUR_API_KEY"
Response
{
"success": true,
"data": {
"from": "2026-05-01",
"to": "2026-05-31",
"total": 1240,
"byAnalyticType": {
"total": 1240,
"sent": 800,
"delivered": 760,
"read": 540,
"replied": 210,
"booked": 35,
"contactCreated": 120,
"creditsSpent": 412.5,
"creditsRecharged": 500
},
"byDate": [
{ "date": "2026-05-01", "byAnalyticType": { "total": 40, "sent": 25, "delivered": 24, "read": 18, "replied": 7, "booked": 1, "contactCreated": 4, "creditsSpent": 13.5, "creditsRecharged": 0 } }
]
}
}
Agency sub-account rollup
Analytics API errors
Analytics endpoints return the standard error envelope:
{
"success": false,
"error": "Date range too large. Maximum is 366 days."
}
On an analytics endpoint, an invalid date format or an out-of-range window returns 400, and an unknown campaign_id or agent_id returns 404. Sending both campaign_id and agent_id on an endpoint that accepts either is also a 400 — pass at most one. The PG-only reporting endpoints (Metric series, Conversation outcomes, Agency rollup) return 503 with "error_code": "analytics_unavailable" rather than a 200 full of zeros when the reporting database cannot answer for your account — retry shortly. The shared codes every endpoint can return — 401, 403 (your plan does not include API access, or, on the agency rollup, your account is not Agency/Dev), 429 (rate limit) and 500 — are listed with retry guidance in Errors & Pagination.
Next steps
- Authentication — the four ways to authenticate a request.
- Errors & Rate Limits — status codes and the 300 req/min limit.
- Campaigns API — the campaigns these figures can be filtered by.