Сплиты
Методы для сплитов: найти нужные, создать, запустить или остановить, задать свои ссылки на предложения и пиксели, наклонировать и убрать в архив. Что такое сплит и как он делит трафик, см. раздел «Сплиты и потоки». Какие PWA входят в сплит и с какими весами, задаётся потоками - см. раздел API «Потоки».
| Метод | Адрес | Что делает |
|---|---|---|
| GET | /pwa_splits | Список сплитов |
| GET | /pwa_splits/{id} | Один сплит с потоками и доменами |
| POST | /pwa_splits | Создать сплит |
| PUT | /pwa_splits/{id} | Изменить, запустить или остановить |
| POST | /pwa_splits/{id}/clone | Клонировать |
| DELETE | /pwa_splits/{id} | Убрать в архив |
Замените ВАШ_КЛЮЧ и panel.example.com на свои.
Список сплитов
GET/pwa_splits
Сплиты ваших команд, новые и недавно изменённые сверху. Архивные не показываются.
| Параметр | Что фильтрует |
|---|---|
search | Часть названия |
domain | Часть домена, привязанного к сплиту |
status | active - только запущенные, inactive - только остановленные |
archived | 1 - только архивные |
team_id | Команда |
page, per_page | Страница и её размер (по умолчанию 100) |
curl "https://panel.example.com/api/pwa_splits?status=active" \
-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('pwa_splits', ['query' => ['status' => 'active']]);
$splits = json_decode($response->getBody(), true)['data']['pwa_splits'];
foreach ($splits as $split) {
echo "{$split['id']} {$split['name']}: {$split['pwa_flows_count']} потоков" . PHP_EOL;
}# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.get(f"{API}/pwa_splits", headers=HEADERS, params={"status": "active"}, timeout=30)
splits = response.json()["data"]["pwa_splits"]
for split in splits:
print(split["id"], split["name"], split["pwa_flows_count"], "потоков")// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const response = await fetch(`${API}/pwa_splits?status=active`, { headers, signal: AbortSignal.timeout(30000) });
const { data } = await response.json();
for (const split of data.pwa_splits) {
console.log(split.id, split.name, split.pwa_flows_count, 'потоков');
}Ответ (сокращён)
{
"data": {
"meta": { "current_page": 1, "per_page": 100, "last_page": 1, "total": 1 },
"pwa_splits": [
{
"id": "WQby",
"name": "US test",
"status": "active",
"archived": false,
"filter_stream_id": null,
"pwa_flows_count": 2,
"domains_count": 1,
"stat_uniques": 1520,
"stat_installs": 410,
"stat_registrations": 96,
"stat_deposits": 21,
"stat_repeat_deposits": 7,
"team": { "id": "WZAX", "name": "Team A" },
"pwa_flows": [
{ "id": "ymqy", "weight": 70, "pwa": { "id": "WZAX", "name": "Promo EN", "active": true } },
{ "id": "Xbpy", "weight": 30, "pwa": { "id": "Lm3T", "name": "Promo EN 2", "active": true } }
],
"domains": [ { "id": "Xk9P", "domain": "spin-us.example" } ],
"created_at": "05 Oct 2026 14:22",
"updated_at": "05 Oct 2026 14:22"
}
]
}
}Счётчики stat_* - сумма по потокам сплита за всё время. У сплита без потоков они приходят как null, а не 0.
Ошибки - только общие, см. «Введение в API».
Один сплит
GET/pwa_splits/{id}
Сплит с доменами, потоками и своими настройками в config.
curl https://panel.example.com/api/pwa_splits/WQby \
-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('pwa_splits/WQby');
$split = json_decode($response->getBody(), true)['data']['pwa_split'];
echo "{$split['name']}: {$split['status']}" . PHP_EOL;# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.get(f"{API}/pwa_splits/WQby", headers=HEADERS, timeout=30)
split = response.json()["data"]["pwa_split"]
print(split["name"], split["status"])// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const response = await fetch(`${API}/pwa_splits/WQby`, { headers, signal: AbortSignal.timeout(30000) });
const { data } = await response.json();
console.log(data.pwa_split.name, data.pwa_split.status);Ответ (сокращён)
{
"data": {
"pwa_split": {
"id": "WQby",
"name": "US test",
"status": "active",
"filter_account_id": null,
"filter_stream_id": null,
"team": { "id": "WZAX", "name": "Team A" },
"domains": [ { "id": "Xk9P", "domain": "spin-us.example" } ],
"pwa_flows": [
{ "id": "ymqy", "weight": 70, "stat_installs": 290, "pwa": { "id": "WZAX", "name": "Promo EN" } },
{ "id": "Xbpy", "weight": 30, "stat_installs": 120, "pwa": { "id": "Lm3T", "name": "Promo EN 2" } }
],
"config": {
"offerLinks": {
"US": [ { "lang": "en", "link": "https://offer.example/?sub1={sub1}" } ]
}
}
}
}
}config у сплита может быть null - тогда работают настройки самих PWA.
Пока AI-расчёт весов включён, в ответе есть ai: shares - текущая доля каждого потока в процентах (по id потока) и learning - true, пока у какого-то потока меньше 100 уникальных визитов. При выключенном AI-расчёте ai равно null.
Ошибки
| Код | message | Когда |
|---|---|---|
404 | Not found | Неверный идентификатор |
403 | This action is unauthorized. | Объект принадлежит не вашей команде |
Создание сплита
POST/pwa_splits
| Поле | Обязательно | Что это |
|---|---|---|
name | да | Название сплита в панели |
team_id | для team_lead и admin | Команда; у customer подставляется сама |
status | нет | active - сразу запустить. По умолчанию сплит создаётся остановленным |
filter_account_id, filter_stream_id | нет | Аккаунт фильтрации и поток в нём - вместо фильтра самих PWA |
config.offerLinks | нет | Свои ссылки на предложения - вместо ссылок самих PWA, формат как у PWA |
config.metrics | нет | Свой пиксель Facebook (facebook.pixelId, facebook.events) и тег Google (google.tagId) |
config.ai | нет | AI-расчёт весов: enabled (true/false) и goal - install, registration или deposit (по умолчанию install) |
curl -X POST https://panel.example.com/api/pwa_splits \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "US test",
"team_id": "WZAX",
"config": {
"offerLinks": { "US": [ { "lang": "en", "link": "https://offer.example/?sub1={sub1}" } ] }
}
}'<?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->post('pwa_splits', ['json' => [
'name' => 'US test',
'team_id' => 'WZAX',
'config' => [
'offerLinks' => ['US' => [['lang' => 'en', 'link' => 'https://offer.example/?sub1={sub1}']]],
],
]]);
$split = json_decode($response->getBody(), true)['data']['pwa_split'];
echo "Создан сплит {$split['id']}" . PHP_EOL;# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.post(f"{API}/pwa_splits", headers=HEADERS, json={
"name": "US test",
"team_id": "WZAX",
"config": {
"offerLinks": {"US": [{"lang": "en", "link": "https://offer.example/?sub1={sub1}"}]},
},
}, timeout=30)
split = response.json()["data"]["pwa_split"]
print("Создан сплит", split["id"])// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const response = await fetch(`${API}/pwa_splits`, {
method: 'POST',
headers,
body: JSON.stringify({
name: 'US test',
team_id: 'WZAX',
config: {
offerLinks: { US: [{ lang: 'en', link: 'https://offer.example/?sub1={sub1}' }] },
},
}),
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
console.log('Создан сплит', data.pwa_split.id);Ответ - созданный сплит в data.pwa_split, в том же виде, что и GET/pwa_splits/{id}: status (inactive, если вы его не передали), team, пустые domains и pwa_flows. Потоки добавляются методами раздела API «Потоки», домены - методами раздела API «Домены».
Ошибки
| Код | message | Когда |
|---|---|---|
422 | The team id field is required. | Не передан team_id (для team_lead и admin) |
422 | You do not have access to this team | team_id - не ваша команда |
422 | The name field is required. | Не передан name |
422 | The selected status is invalid. | status - не active и не inactive |
422 | The offer links country "USA" must be a two-letter code. | Страна в config.offerLinks - не двухбуквенный код |
422 | The link field format is invalid. | Ссылка в config.offerLinks не начинается с http:// или https:// |
422 | The selected resource does not exist | pixelId или tagId - не идентификатор вашего пикселя или тега из раздела API «Пиксели и теги» |
Изменение, запуск и остановка
PUT/pwa_splits/{id}
Меняет только переданные поля. Принимает те же поля, что и создание. team_id здесь передавать не нужно - только если переносите сплит в другую команду.
Запустить сплит:
curl -X PUT https://panel.example.com/api/pwa_splits/WQby \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"status": "active"}'<?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->put('pwa_splits/WQby', ['json' => ['status' => 'active']]);
$split = json_decode($response->getBody(), true)['data']['pwa_split'];
echo "{$split['name']}: {$split['status']}" . PHP_EOL;# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.put(f"{API}/pwa_splits/WQby", headers=HEADERS, json={"status": "active"}, timeout=30)
split = response.json()["data"]["pwa_split"]
print(split["name"], split["status"])// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const response = await fetch(`${API}/pwa_splits/WQby`, {
method: 'PUT',
headers,
body: JSON.stringify({ status: 'active' }),
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
console.log(data.pwa_split.name, data.pwa_split.status);Остановить - то же самое с "status": "inactive". Участники команды получат уведомление, что сплит остановлен.
config заменяется целиком
Если в запросе есть config, он заменяет все настройки сплита: передали только metrics - ссылки на предложения сотрутся. Сначала получите текущий config, поменяйте в нём нужное и отправьте обратно целиком - так же, как у PWA.
Ответ - сплит после изменения в data.pwa_split, с потоками и доменами.
Запуск, остановка и новые настройки доходят до трафика в течение трёх минут.
Ошибки
| Код | message | Когда |
|---|---|---|
404 | Not found | Неверный идентификатор |
403 | This action is unauthorized. | Объект принадлежит не вашей команде |
422 | The selected status is invalid. | status - не active и не inactive |
422 | You do not have access to this team | team_id - не ваша команда |
Ошибки в config - те же, что при создании.
Клонирование
POST/pwa_splits/{id}/clone
Делает одну копию сплита. Тело запроса не нужно.
Копия получает название оригинала с добавкой Clone, его настройки, фильтр и потоки с весами. Домены не копируются, а сама копия создаётся остановленной: переименуйте её, привяжите домены и запустите.
curl -X POST https://panel.example.com/api/pwa_splits/WQby/clone \
-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,
]);
// 1. Копия получает имя «US test Clone»
$response = $api->post('pwa_splits/WQby/clone');
$clone = json_decode($response->getBody(), true)['data']['pwa_split'];
// 2. Переименовываем её
$api->put("pwa_splits/{$clone['id']}", ['json' => ['name' => 'US test 2']]);
echo "Копия {$clone['id']} переименована" . PHP_EOL;# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
# 1. Копия получает имя «US test Clone»
response = requests.post(f"{API}/pwa_splits/WQby/clone", headers=HEADERS, timeout=30)
clone = response.json()["data"]["pwa_split"]
# 2. Переименовываем её
requests.put(f"{API}/pwa_splits/{clone['id']}", headers=HEADERS, json={"name": "US test 2"}, timeout=30)
print("Копия", clone["id"], "переименована")// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
// 1. Копия получает имя «US test Clone»
const cloned = await fetch(`${API}/pwa_splits/WQby/clone`, { method: 'POST', headers, signal: AbortSignal.timeout(30000) });
const clone = (await cloned.json()).data.pwa_split;
// 2. Переименовываем её
await fetch(`${API}/pwa_splits/${clone.id}`, {
method: 'PUT',
headers,
body: JSON.stringify({ name: 'US test 2' }),
signal: AbortSignal.timeout(30000),
});
console.log('Копия', clone.id, 'переименована');Ответ - копия в data.pwa_split, в том же виде, что и GET/pwa_splits/{id}.
Ошибки
| Код | message | Когда |
|---|---|---|
404 | Not found | Неверный идентификатор |
403 | This action is unauthorized. | Объект принадлежит не вашей команде |
Архивирование
DELETE/pwa_splits/{id}
Убирает сплит в архив вместе с его потоками: домены сплита перестают отдавать трафик, статистика сохраняется. Архивные сплиты видны в списке с archived=1.
curl -X DELETE https://panel.example.com/api/pwa_splits/WQby \
-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->delete('pwa_splits/WQby');
echo $response->getStatusCode() === 200 ? 'Сплит в архиве' . PHP_EOL : 'Ошибка' . PHP_EOL;# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}
response = requests.delete(f"{API}/pwa_splits/WQby", headers=HEADERS, timeout=30)
print("Сплит в архиве" if response.ok else "Ошибка")// Node.js 18+, без зависимостей; сохраните как script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };
const response = await fetch(`${API}/pwa_splits/WQby`, { method: 'DELETE', headers, signal: AbortSignal.timeout(30000) });
console.log(response.ok ? 'Сплит в архиве' : 'Ошибка');Ответ: {"data": true}.
Ошибки
| Код | message | Когда |
|---|---|---|
404 | Not found | Неверный идентификатор |
403 | This action is unauthorized. | Объект принадлежит не вашей команде |