Статистика
Методы для отчётов: та же статистика, что на «Панели» и на странице «Статистика», только в JSON - для своих дашбордов, выгрузок в таблицы и автоматических проверок. Что значат сами показатели, подробно разобрано в разделах «Дашборд и статистика» и «Статистика».
| Метод | Адрес | Что делает |
|---|---|---|
| GET | /stats/dashboard | Сводка за период: итоги, графики, GEO, устройства, топ PWA |
| GET | /stats/funnel | Воронка по дням и результаты сплитов |
| GET | /stats/subs | Разбивка по одной саб-метке (sub_1 … sub_20) |
Замените ВАШ_КЛЮЧ и panel.example.com на свои.
Период
Все три метода требуют период - параметры date_from и date_to:
| Параметр | Обязательно | Что это |
|---|---|---|
date_from | да | Первый день периода, ГГГГ-ММ-ДД |
date_to | да | Последний день периода включительно, не раньше date_from |
- Дни берутся целиком:
date_from=2026-10-01&date_to=2026-10-01- это весь день 1 октября. - Время - по UTC: день начинается в 00:00 UTC, а не по вашему часовому поясу.
- Период - не длиннее месяца:
date_toне может быть позже, чемdate_fromплюс один месяц. Нужна статистика за квартал - запросите по месяцам и сложите (кромеuniqи процентов - их складывать нельзя).
Без дат или с периодом длиннее месяца придёт 422:
{
"data": null,
"message": "The date to field must be a date before or equal to 2026-02-01.",
"errors": { "date_to": ["The date to field must be a date before or equal to 2026-02-01."] }
}Визиты по дате визита, события - по дате события
Визиты, уникальные и вайты считаются по дню, когда был визит. Установки, открытия, регистрации и депозиты - по дню, когда пришло событие. Поэтому на коротком периоде шаг воронки бывает больше 100% от предыдущего: события относятся к визитам, которые были раньше.
Цифры обновляются раз в несколько минут: свежий визит или депозит появится в отчётах с задержкой до 5 минут. Статистика видна только по PWA ваших команд, у admin - по всем.
Сводка
GET/stats/dashboard
Всё, что показывает «Панель», одним запросом. Параметры - только период.
curl "https://panel.example.com/api/stats/dashboard?date_from=2026-09-29&date_to=2026-10-05" \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Accept: application/json"<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$api = new GuzzleHttp\Client([
'base_uri' => 'https://panel.example.com/api/',
'headers' => ['Authorization' => 'Bearer ВАШ_КЛЮЧ', 'Accept' => 'application/json'],
'timeout' => 30,
]);
$response = $api->get('stats/dashboard', ['query' => [
'date_from' => '2026-09-29',
'date_to' => '2026-10-05',
]]);
$metrics = json_decode($response->getBody(), true)['data']['metrics'];
echo "Установки: {$metrics['total_installs']['value']} ({$metrics['total_installs']['trend']}%)\n";
echo "Депозиты: {$metrics['total_deposits']['value']}, CR {$metrics['avg_cr']['value']}%\n";# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.get(f"{API}/stats/dashboard", headers=HEADERS, params={
"date_from": "2026-09-29",
"date_to": "2026-10-05",
}, timeout=30)
metrics = response.json()["data"]["metrics"]
print("Установки:", metrics["total_installs"]["value"], f'({metrics["total_installs"]["trend"]}%)')
print("Депозиты:", metrics["total_deposits"]["value"], f'CR {metrics["avg_cr"]["value"]}%')// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const params = new URLSearchParams({ date_from: '2026-09-29', date_to: '2026-10-05' });
const response = await fetch(`${API}/stats/dashboard?${params}`, {
method: 'GET',
headers,
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
const { metrics } = data;
console.log('Установки:', metrics.total_installs.value, `(${metrics.total_installs.trend}%)`);
console.log('Депозиты:', metrics.total_deposits.value, `CR ${metrics.avg_cr.value}%`);Ответ (сокращён)
{
"data": {
"metrics": {
"previous_period": { "from": "2026-09-22", "to": "2026-09-29" },
"total_visits": { "value": 12480, "trend": 14 },
"total_uniques": { "value": 9870, "trend": 12.2 },
"total_repeats": { "value": 2610, "trend": 21.4 },
"total_whites": { "value": 1310, "trend": -7.7 },
"total_installs": { "value": 2140, "trend": 8.1 },
"total_opens": { "value": 1890, "trend": 11 },
"total_registrations": { "value": 412, "trend": 8.4 },
"total_deposits": {
"value": 96,
"trend": 18.5,
"amounts": [
{ "currency": "USD", "amount": 4820.5 },
{ "currency": "EUR", "amount": 310 }
]
},
"avg_cr": { "value": 4.49, "trend": 6.1 }
},
"chart": [
{ "date": "2026-10-04", "visits": 610, "whites": 60, "installs": 110, "deposits": 4 },
{ "date": "2026-10-05", "visits": 640, "whites": 70, "installs": 120, "deposits": 6 }
],
"geo": [
{ "code": "US", "installs": 1200, "cr": 5.1, "pct": 100 },
{ "code": "DE", "installs": 400, "cr": 3.5, "pct": 33 }
],
"devices": [
{ "name": "Android", "installs": 1900, "pct": 89 },
{ "name": "iOS", "installs": 240, "pct": 11 }
],
"pwas": [
{
"id": "WZAX", "name": "Promo EN", "icon_url": null,
"domains": [{ "id": "K3LP", "domain": "promo-en.example.com" }],
"visits": 12480, "installs": 2140, "cr": 4.5, "status": "active"
}
],
"activity": [
{ "id": "WZAX", "type": "deploy", "msg": "Promo EN is running", "icon_url": null, "time": "2 hours ago" }
]
}
}metrics - итоги за период. У каждого показателя value - значение, trend - изменение в процентах к равному по длине периоду перед ним (его даты - в previous_period). Если в прошлом периоде был ноль, а сейчас что-то есть, trend равен 100.
| Поле | Что это |
|---|---|
total_visits | Все визиты |
total_uniques | Уникальные - первые визиты посетителя на поток |
total_repeats | Повторные: визиты минус уникальные |
total_whites | Визиты, которые фильтр отправил на white-страницу |
total_installs | Установки |
total_opens | Открытия оффера из установленного PWA |
total_registrations | Регистрации из постбеков |
total_deposits | Депозиты; amounts - суммы выплат по каждой валюте отдельно |
avg_cr | Конверсия: депозиты ÷ установки × 100%. trend - изменение к прошлому периоду, по тем же правилам, что у остальных |
chart - те же визиты, вайты, установки и депозиты по дням. День, в котором были только установки или депозиты без визитов, тоже есть - с нулями в visits и whites.
geo - топ-10 стран по установкам: code - код страны (XX - не определилась), cr - депозиты ÷ установки, pct - сколько процентов установок от первой страны в списке.
devices - установки по типам устройств (Android, iOS, Desktop), pct - доля от всех установок.
pwas - топ-10 PWA по установкам за период. status: active - включено, paused - выключено, archived - в архиве. domains - домены PWA (пустой список, если их нет).
activity - десять последних изменённых PWA, без привязки к периоду. Нужна для ленты в панели, в скриптах обычно не пригождается.
Ошибки
| Код | message | Когда |
|---|---|---|
422 | The date from field is required. (and 1 more error) | Не передан период |
422 | The date from field must be a valid date. | Дата не распознана |
422 | The date to field must be a date after or equal to date from. | date_to раньше date_from |
422 | The date to field must be a date before or equal to 2026-02-01. | Период длиннее месяца (в тексте - последний допустимый день) |
Воронка и сплиты
GET/stats/funnel
Воронка Визиты → Уник → Установки → Открытия → Рег → Деп по дням и итогом, плюс результаты сплитов.
| Параметр | Обязательно | Что это |
|---|---|---|
date_from, date_to | да | Период, см. выше |
pwa_id | нет | Только одно PWA. Чужое или несуществующее - 404 |
curl "https://panel.example.com/api/stats/funnel?date_from=2026-09-29&date_to=2026-10-05" \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Accept: application/json"<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$api = new GuzzleHttp\Client([
'base_uri' => 'https://panel.example.com/api/',
'headers' => ['Authorization' => 'Bearer ВАШ_КЛЮЧ', 'Accept' => 'application/json'],
'timeout' => 30,
]);
$response = $api->get('stats/funnel', ['query' => [
'date_from' => '2026-09-29',
'date_to' => '2026-10-05',
]]);
$funnel = json_decode($response->getBody(), true)['data']['funnel'];
foreach ($funnel['rows'] as $day) {
echo "{$day['date']}: {$day['installs']} установок, {$day['deps']} депозитов, CR {$day['cr']}%\n";
}# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.get(f"{API}/stats/funnel", headers=HEADERS, params={
"date_from": "2026-09-29",
"date_to": "2026-10-05",
}, timeout=30)
funnel = response.json()["data"]["funnel"]
for day in funnel["rows"]:
print(day["date"], day["installs"], "установок,", day["deps"], "депозитов, CR", day["cr"])// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const params = new URLSearchParams({ date_from: '2026-09-29', date_to: '2026-10-05' });
const response = await fetch(`${API}/stats/funnel?${params}`, {
method: 'GET',
headers,
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
for (const day of data.funnel.rows) {
console.log(day.date, day.installs, 'установок,', day.deps, 'депозитов, CR', day.cr);
}Ответ (сокращён)
{
"data": {
"funnel": {
"rows": [
{
"date": "2026-10-05",
"visits": 640, "uniq": 590, "uniques": 520, "repeats": 120, "whites": 70,
"installs": 120, "opens": 105, "regs": 24, "deps": 6,
"inst_pct": 20.3, "open_pct": 87.5, "reg_pct": 20, "dep_pct": 25, "cr": 5
}
],
"totals": {
"date": null,
"visits": 1250, "uniq": 1100, "uniques": 1020, "repeats": 230, "whites": 130,
"installs": 230, "opens": 203, "regs": 44, "deps": 10,
"inst_pct": 20.9, "open_pct": 88.3, "reg_pct": 19.1, "dep_pct": 22.7, "cr": 4.3
}
},
"splits": [
{
"id": "Lm3T",
"name": "Split US",
"status": "active",
"visits": 6100, "installs": 1030, "conversions": 44, "cr": 4.3,
"flows": [
{
"flow_id": "Qp8R", "pwa_id": "WZAX", "pwa_name": "Promo EN", "weight": 50,
"visits": 6100, "installs": 1030, "conversions": 44, "cr": 4.3
}
]
}
],
"pwa": null
}
}funnel.rows - по строке на день, новые сверху. funnel.totals - итог за весь период (date - null).
| Поле | Что это |
|---|---|
visits | Все визиты |
uniq | Уникальные люди - сколько разных посетителей пришло |
uniques | Уникальные визиты - первые визиты посетителя на поток. Один человек, прошедший с основного PWA на похожее, - это два uniques, но один uniq |
repeats | Повторные: visits − uniques |
whites | Ушли на white-страницу |
installs, opens, regs, deps | Установки, открытия оффера, регистрации, депозиты |
inst_pct | Установки ÷ uniq |
open_pct | Открытия ÷ установки |
reg_pct | Регистрации ÷ установки |
dep_pct | Депозиты ÷ регистрации |
cr | Депозиты ÷ установки - главная конверсия |
Все проценты - числа от 0 до 100 (на коротком периоде бывает больше, см. выше).
uniq нельзя складывать
totals.uniq пересчитан по всему периоду: человек, приходивший три дня подряд, в нём один раз, а в сумме дней - три. Поэтому totals.uniq меньше суммы uniq по дням, и это правильно. Остальные счётчики складываются как обычно.
splits - все сплиты ваших команд с результатами за период: итог по сплиту и по каждому потоку внутри (flows) - к какому PWA ведёт поток (pwa_id, pwa_name) и его вес (weight). conversions - это депозиты, cr - депозиты ÷ установки. С параметром pwa_id список сплитов пустой: сплит объединяет несколько PWA, и для одного приложения он не считается.
pwa - выбранное PWA (id и name), если передан pwa_id, иначе null.
Ошибки
| Код | message | Когда |
|---|---|---|
422 | The date from field is required. (and 1 more error) | Не передан период |
422 | The date from field must be a valid date. | Дата не распознана |
422 | The date to field must be a date after or equal to date from. | date_to раньше date_from |
422 | The date to field must be a date before or equal to 2026-02-01. | Период длиннее месяца (в тексте - последний допустимый день) |
404 | Not found | pwa_id чужого или несуществующего PWA |
Саб-метки
GET/stats/subs
Какие значения одной саб-метки приносят установки и депозиты: например, какие кампании, креативы или адсеты за sub_1 … sub_20 реально конвертят.
| Параметр | Обязательно | Что это |
|---|---|---|
date_from, date_to | да | Период, см. выше |
slot | да | Номер саб-метки, от 1 до 20 |
limit | нет | Сколько значений вернуть, от 1 до 100, по умолчанию 20 |
search | нет | Только значения, в которых есть эта подстрока (без учёта регистра) |
filters[sub_N] | нет | Сузить по другим меткам: filters[sub_1]=fb-ua-creo1 - только визиты с таким sub_1. Можно несколько |
pwa_id | нет | Только одно PWA: его визиты и его конверсии. Чужое или несуществующее - 404 |
Пример: какие адсеты (sub_2) работают внутри креатива fb-ua-creo1 (sub_1).
curl -G "https://panel.example.com/api/stats/subs" \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Accept: application/json" \
--data-urlencode "date_from=2026-09-29" \
--data-urlencode "date_to=2026-10-05" \
--data-urlencode "slot=2" \
--data-urlencode "filters[sub_1]=fb-ua-creo1"<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$api = new GuzzleHttp\Client([
'base_uri' => 'https://panel.example.com/api/',
'headers' => ['Authorization' => 'Bearer ВАШ_КЛЮЧ', 'Accept' => 'application/json'],
'timeout' => 30,
]);
$response = $api->get('stats/subs', ['query' => [
'date_from' => '2026-09-29',
'date_to' => '2026-10-05',
'slot' => 2,
'filters' => ['sub_1' => 'fb-ua-creo1'],
]]);
$subs = json_decode($response->getBody(), true)['data']['subs'];
foreach ($subs as $sub) {
$value = $sub['value'] ?? '(пусто)';
echo "{$value}: {$sub['installs']} установок, CR {$sub['cr']}%\n";
}# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.get(f"{API}/stats/subs", headers=HEADERS, params={
"date_from": "2026-09-29",
"date_to": "2026-10-05",
"slot": 2,
"filters[sub_1]": "fb-ua-creo1",
}, timeout=30)
subs = response.json()["data"]["subs"]
for sub in subs:
print(sub["value"] or "(пусто)", sub["installs"], "установок, CR", sub["cr"])// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const params = new URLSearchParams({
date_from: '2026-09-29',
date_to: '2026-10-05',
slot: 2,
'filters[sub_1]': 'fb-ua-creo1',
});
const response = await fetch(`${API}/stats/subs?${params}`, {
method: 'GET',
headers,
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
for (const sub of data.subs) {
console.log(sub.value || '(пусто)', sub.installs, 'установок, CR', sub.cr);
}Ответ
{
"data": {
"slot": 2,
"pwa": null,
"subs": [
{ "value": "adset-7", "visits": 5210, "installs": 980, "conversions": 51, "cr": 5.2 },
{ "value": null, "visits": 1200, "installs": 140, "conversions": 3, "cr": 2.1 }
]
}
}Значения отсортированы по установкам, лучшие сверху. value: null - визиты, у которых эта метка не заполнена. conversions - депозиты, cr - депозиты ÷ установки.
Ключ в filters может быть только sub_1 … sub_20.
Ошибки
| Код | message | Когда |
|---|---|---|
422 | The date from field is required. (and 1 more error) | Не передан период |
422 | The date from field must be a valid date. | Дата не распознана |
422 | The date to field must be a date after or equal to date from. | date_to раньше date_from |
422 | The date to field must be a date before or equal to 2026-02-01. | Период длиннее месяца (в тексте - последний допустимый день) |
422 | The slot field is required. | Не передан slot |
422 | The slot field must not be greater than 20. | slot больше 20 |
422 | The limit field must not be greater than 100. | limit больше 100 |
422 | Filter key must be sub_1..sub_20. | Ключ в filters - не sub_1 … sub_20 |
404 | Not found | pwa_id чужого или несуществующего PWA |