Статистика: звіти та експорт
Statistics API повертає агреговані звіти трекера — метрики × групування × фільтри за період. Це ті ж дані, що показує Конструктор звітів в кабінеті. Підходить для BI-систем, регулярних вивантажень та зовнішніх дашбордів.
Ключі метрик, групувань та фільтруваних полів зібрані в статті Статистика: довідник полів. Отримання токена, загальний формат відповідей та помилок — в головній статті розділу.
Скоупи
| Скоуп | Доступ | В дефолті PAT |
|---|---|---|
api:stats |
POST /api/stats/query — звіти |
так |
api:stats:export |
POST /api/stats/export/csv — вивантаження CSV |
так |
api:stats:meta |
GET /api/stats/meta/* — довідники |
так |
Усі операції вимагають права запиту статистики — воно є у всіх ролей. BUYER бачить тільки свою статистику, TEAM_LEAD — статистику команди з урахуванням налаштувань доступу до ресурсів, TEAM_OWNER та TECH — команду, ADMIN — все.
Ендпойнти
Базовий префікс — /api/stats. Тіло запитів — JSON, відповіді — application/json (для експорту — text/csv).
| Метод | Шлях | Скоуп | Призначення |
|---|---|---|---|
POST |
/api/stats/query |
api:stats |
Звіт: метрики × групування + фільтри, з пагінацією |
POST |
/api/stats/export/csv |
api:stats:export |
Та ж вибірка в CSV (без пагінації, до 100 000 рядків) |
GET |
/api/stats/meta/metrics |
api:stats:meta |
Каталог метрик |
GET |
/api/stats/meta/groups |
api:stats:meta |
Каталог групувань |
GET |
/api/stats/meta/filters |
api:stats:meta |
Список фільтруваних полів |
GET |
/api/stats/meta/distinct?field=&q=&limit= |
api:stats:meta |
Підказки значень поля (autocomplete) |
GET |
/api/stats/meta/os-versions?q=&limit= |
api:stats:meta |
Підказки версій ОС |
Для
/api/stats/**діє окремий ліміт частоти — 3 запити на секунду з одного IP (burst 10). Понад ліміт шлюз відповідає429.
POST /api/stats/query
Тіло запиту (StatsQueryDto):
{
"time": {
"preset": "last7", // АБО from/to
"from": "2026-05-01 00:00:00",
"to": "2026-05-20 23:59:59",
"timezone": "UTC"
},
"groups": ["day", "cmp_campaign"],
"metrics": ["clicks", "cpa_accept", "revenue", "roi"],
"filters": [
{ "field": "user_country", "op": "in", "value": ["US", "CA"] },
{ "field": "cmp_offer", "op": "eq", "value": "65f0…" }
],
"pagination": { "page": 1, "limit": 100 },
"sort": { "field": "clicks", "order": "desc" },
"attributionWindow": { "hours": 24, "eventType": "click" }
}
Поля запиту
| Поле | Тип | Обов'язково | Опис |
|---|---|---|---|
time |
TimeRangeDto |
так | Часовий інтервал звіту |
groups |
string[] |
ні | Ключі групувань (див. довідник). Порожній масив — агрегат «всього» |
metrics |
string[] |
ні | Ключі метрик (див. довідник). За замовчуванням ["clicks"] |
filters |
FieldFilterDto[] |
ні | Фільтри по полях (див. нижче) |
pagination |
{ page, limit } |
ні | page ≥ 1, 1 ≤ limit ≤ 100000 (за замовчуванням 100) |
sort |
{ field, order } |
ні | order ∈ {asc, desc}; field — ключ метрики або групування з запиту |
attributionWindow |
{ hours, eventType } |
ні | Вікно атрибуції для Push-метрик: 1 ≤ hours ≤ 720, eventType ∈ {click, view} |
time (TimeRangeDto)
| Поле | Опис |
|---|---|
preset |
один з пресетів нижче; має пріоритет над from/to |
from |
'YYYY-MM-DD' або 'YYYY-MM-DD HH:mm:ss' (роздільник — пробіл або T). Без мілісекунд і без суфікса таймзони (Z, +03:00) — такий формат поверне помилку валідації |
to |
те ж; необов'язковий, якщо задано from |
timezone |
IANA-таймзона (Europe/Moscow), за замовчуванням UTC. Межі інтервалу та групування за часом обчислюються в ній |
Потрібно передати або preset, або from (опціонально з to).
| Пресет | Період |
|---|---|
today |
сьогодні з 00:00 до поточного моменту |
yesterday |
повні попередні доби |
last7 |
останні 7 днів, включаючи сьогодні |
last30 |
останні 30 днів |
thisWeek |
з понеділка поточного тижня |
prevWeek |
попередній повний тиждень (Пн–Нд) |
thisMonth |
з 1-го числа поточного місяця |
prevMonth |
попередній повний місяць |
filters[] (FieldFilterDto)
Кожен фільтр — { "field", "op", "value" }. Поле повинно входити в список GET /api/stats/meta/filters.
Оператор op |
Семантика | Тип value |
|---|---|---|
eq |
дорівнює | рядок/число |
neq |
не дорівнює | рядок/число |
in |
значення зі списку | масив |
not_in |
значення немає у списку | масив |
gt / gte |
більше / більше або дорівнює | число |
lt / lte |
менше / менше або дорівнює | число |
between |
в діапазоні | [min, max] — масив з 2 елементів |
like |
підрядок без урахування регістру (ClickHouse ILIKE) |
рядок з % |
Серверні фільтри. Поля cmp_team та cmp_user завжди перевизначаються сервером відповідно до ролі власника токена: задане клієнтом значення cmp_team ігнорується, а cmp_user перетинається з дозволеним набором користувачів. Обмежити звіт чужими даними через API неможливо.
Правила
groupsтаmetricsприймають тільки ключі з довідників; невідомий ключ — помилка422.- Якщо у групування є «name»-варіант (
cmp_campaign↔cmp_campaign_name), він додається в рядки автоматично — передавати його окремо не потрібно. attributionWindowвпливає тільки на метрики Push Attribution (push_postclick_*); без нього ці метрики повернуть нулі.- Метрики LTV/Cohort (
ltv_*,ftds,registrations…) використовуються разом з групуваннямиcohort_*,reg_cohort_*,lifetime_days*. - Для
queryрекомендуєтьсяlimit ≤ 10 000; для повного вивантаження використовуйте CSV.
Приклад відповіді
{
"data": {
"rows": [
{
"day": "2026-05-13T00:00:00+00:00",
"cmp_campaign": "65f0…",
"cmp_campaign_name": "Brand A — RU",
"clicks": 18432,
"cpa_accept": 122,
"revenue": 2840.55,
"roi": 0.36
}
],
"total": { "clicks": 18432, "cpa_accept": 122, "revenue": 2840.55 },
"page": 1,
"limit": 100,
"rowCount": 1
},
"traceId": "01HX…"
}
rows — рядки звіту (ключі групувань + метрики), total — підсумок по всій вибірці без урахування пагінації, rowCount — кількість рядків на поточній сторінці. Частки (roi, click_to_dep тощо) приходять як числа в діапазоні 0..1, гроші — в USD.
POST /api/stats/export/csv
Те ж тіло StatsQueryDto. Відповідь — text/csv; charset=utf-8, ім'я файлу stats-report-YYYY-MM-DD.csv. Пагінація ігнорується, вивантаження обмежене 100 000 рядків.
curl -X POST 'https://adset.pro/api/stats/export/csv' \
-H 'Authorization: Bearer pat_…' \
-H 'Content-Type: application/json' \
--data-binary @query.json -o report.csv
Довідники GET /api/stats/meta/*
Довідники — живе джерело ключів: якщо в платформі з'явилася нова метрика, вона відразу є в meta/metrics. Відповіді мають вигляд { "data": [ … ], "traceId" }; кешуйте їх на стороні інтеграції.
meta/metrics
{
"key": "roi",
"type": "calculated",
"title": "ROI",
"group": "Finance",
"format": "percent",
"dependencies": ["revenue", "cost"],
"table": "events"
}
type — direct (прямий агрегат) або calculated (обчислюється з dependencies); format — підказка для форматування: ceil (ціле), finance (гроші), percent (частка 0..1), number; table — таблиця ClickHouse, в якій метрика існує.
meta/groups
{ "key": "cmp_campaign", "title": "Campaign", "group": "Campaign", "tables": ["events", "events_push", "events_push_attributed"] }
tables — в яких таблицях групування валідне; групування та метрики в одному запиті повинні перетинатися хоча б по одній таблиці.
meta/filters
{ "field": "user_country", "type": "list", "group": "Traffic", "name": "Country" }
meta/distinct
Підказки значень поля: GET /api/stats/meta/distinct?field=user_country&q=us&limit=20. Поле повинно входити в meta/filters.
{
"data": [
{ "label": "US", "value": "US" },
{ "label": "Australia", "value": "AU" }
],
"traceId": "01HX…"
}
Для сутностей (cmp_campaign, cmp_offer, cmp_cpa…) value — це ObjectId, label — ім'я. Цей же ендпойнт зручно використовувати, щоб знайти id для фільтра за назвою.
meta/os-versions
Те ж, що distinct?field=user_os_ver, але з додатковою нормалізацією версій ОС.
Приклади
Звіт по дням та кампаніям за минулий тиждень
curl -X POST 'https://adset.pro/api/stats/query' \
-H 'Authorization: Bearer pat_…' \
-H 'Content-Type: application/json' \
-d '{
"time": { "preset": "prevWeek", "timezone": "Europe/Moscow" },
"groups": ["day", "cmp_campaign"],
"metrics": ["clicks", "cpa_accept", "revenue", "roi"],
"filters": [
{ "field": "user_country", "op": "in", "value": ["US","CA","GB"] }
],
"pagination": { "page": 1, "limit": 50 },
"sort": { "field": "revenue", "order": "desc" }
}'
Підказки по країнам
curl -G 'https://adset.pro/api/stats/meta/distinct' \
-H 'Authorization: Bearer pat_…' \
--data-urlencode 'field=user_country' \
--data-urlencode 'q=u' \
--data-urlencode 'limit=10'
LTV-когорта по тижнях
curl -X POST 'https://adset.pro/api/stats/query' \
-H 'Authorization: Bearer pat_…' \
-H 'Content-Type: application/json' \
-d '{
"time": { "preset": "last30" },
"groups": ["cohort_week", "lifetime_days"],
"metrics": ["ftds", "ltv_d0", "ltv_d1_7", "ltv_d8_30", "ltv_total", "ltv_per_ftd"],
"pagination": { "page": 1, "limit": 1000 }
}'
Push Attribution з вікном 48 годин
curl -X POST 'https://adset.pro/api/stats/query' \
-H 'Authorization: Bearer pat_…' \
-H 'Content-Type: application/json' \
-d '{
"time": { "preset": "last7" },
"groups": ["day", "event_push_id"],
"metrics": ["push_views", "push_clicks", "push_postclick_accepts", "push_click_to_accept_rate"],
"attributionWindow": { "hours": 48, "eventType": "click" }
}'
Експорт CSV
curl -X POST 'https://adset.pro/api/stats/export/csv' \
-H 'Authorization: Bearer pat_…' \
-H 'Content-Type: application/json' \
--data-binary @query.json -o report.csv
Помилки
| HTTP | Коли |
|---|---|
400 time is required |
не передано time |
400 time.preset or time.from/time.to required |
в time немає ні preset, ні from |
422 validationError |
невірний формат дати, невідомий op, метрика або групування; деталі — в details[] |
403 forbidden + Insufficient OAuth scope. Required: api:stats… |
у токена немає потрібного скоупа (наприклад, PAT без api:stats:export викликає CSV) |
429 |
перевищено ліміт 3 запити/с на /api/stats/** |
Загальний формат помилок та коди 401/403 описані в головній статті розділу.
Пов'язані статті
- Статистика: довідник полів — всі ключі фільтрів, групувань та метрик
- Довідник метрик — що означає кожна метрика та як її читати
- MCP-сервіс Adset — ті ж звіти через LLM-клієнти
