Потоки
Поток - это связка «сплит → PWA» с весом: чем больше вес, тем большую долю трафика сплита получает это PWA. Методы ниже добавляют PWA в сплит, меняют веса и убирают PWA из сплита. Как веса делят трафик, см. раздел «Сплиты и потоки».
| Метод | Адрес | Что делает |
|---|---|---|
| GET | /pwa_flows | Список потоков |
| GET | /pwa_flows/{id} | Один поток |
| POST | /pwa_flows | Добавить PWA в сплит |
| PUT | /pwa_flows/{id} | Изменить вес |
| DELETE | /pwa_flows/{id} | Убрать PWA из сплита |
Замените ВАШ_КЛЮЧ и panel.example.com на свои.
Список потоков
GET/pwa_flows
Потоки ваших команд, недавно изменённые сверху. Архивные не показываются.
| Параметр | Что фильтрует |
|---|---|
owner_split_id | Сплит - потоки только этого сплита |
archived | 1 - только архивные |
page, per_page | Страница и её размер (по умолчанию 100) |
Всегда указывайте owner_split_id
Без owner_split_id в список попадут не только потоки сплитов, но и служебные потоки каждого PWA - по одному на приложение. Их не нужно менять или удалять.
curl "https://panel.example.com/api/pwa_flows?owner_split_id=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_flows', ['query' => ['owner_split_id' => 'WQby']]);
$flows = json_decode($response->getBody(), true)['data']['pwa_flows'];
foreach ($flows as $flow) {
echo "{$flow['pwa']['name']}: вес {$flow['weight']}, {$flow['stat_installs']} установок" . 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_flows", headers=HEADERS, params={"owner_split_id": "WQby"}, timeout=30)
flows = response.json()["data"]["pwa_flows"]
for flow in flows:
print(flow["pwa"]["name"], "вес", flow["weight"], flow["stat_installs"], "установок")// 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_flows?owner_split_id=WQby`, { headers, signal: AbortSignal.timeout(30000) });
const { data } = await response.json();
for (const flow of data.pwa_flows) {
console.log(flow.pwa.name, 'вес', flow.weight, flow.stat_installs, 'установок');
}Ответ (сокращён)
{
"data": {
"meta": { "current_page": 1, "per_page": 100, "last_page": 1, "total": 2 },
"pwa_flows": [
{
"id": "ymqy",
"weight": 70,
"archived": false,
"stat_uniques": 1100,
"stat_installs": 290,
"stat_registrations": 70,
"stat_deposits": 15,
"stat_repeat_deposits": 5,
"team": { "id": "WZAX", "name": "Team A" },
"pwa": { "id": "WZAX", "name": "Promo EN", "active": true, "archived": false },
"created_at": "05 Oct 2026 14:22",
"updated_at": "05 Oct 2026 14:22"
}
]
}
}Счётчики stat_* - за всё время, только по трафику, пришедшему через этот поток.
Ошибки - только общие, см. «Введение в API».
Один поток
GET/pwa_flows/{id}
Поток с его PWA и сплитом (owner_split).
curl https://panel.example.com/api/pwa_flows/ymqy \
-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_flows/ymqy');
$flow = json_decode($response->getBody(), true)['data']['pwa_flow'];
echo "{$flow['pwa']['name']}: вес {$flow['weight']}" . 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_flows/ymqy", headers=HEADERS, timeout=30)
flow = response.json()["data"]["pwa_flow"]
print(flow["pwa"]["name"], "вес", flow["weight"])// 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_flows/ymqy`, { headers, signal: AbortSignal.timeout(30000) });
const { data } = await response.json();
console.log(data.pwa_flow.pwa.name, 'вес', data.pwa_flow.weight);Ответ (сокращён)
{
"data": {
"pwa_flow": {
"id": "ymqy",
"weight": 70,
"pwa": { "id": "WZAX", "name": "Promo EN", "active": true },
"owner_split": { "id": "WQby", "name": "US test", "status": "active" },
"team": { "id": "WZAX", "name": "Team A" }
}
}
}Ошибки
| Код | message | Когда |
|---|---|---|
404 | Not found | Неверный идентификатор |
403 | This action is unauthorized. | Объект принадлежит не вашей команде |
Добавление PWA в сплит
POST/pwa_flows
| Поле | Обязательно | Что это |
|---|---|---|
owner_split_id | да | Сплит, в который добавляете PWA |
pwa_id | да | PWA, которое будет получать трафик. Должно быть в той же команде, что и сплит |
weight | нет | Вес, целое число от 0. По умолчанию 1 |
curl -X POST https://panel.example.com/api/pwa_flows \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"owner_split_id": "WQby", "pwa_id": "WZAX", "weight": 70}'<?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_flows', ['json' => [
'owner_split_id' => 'WQby',
'pwa_id' => 'WZAX',
'weight' => 70,
]]);
$flow = json_decode($response->getBody(), true)['data']['pwa_flow'];
echo "Создан поток {$flow['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_flows", headers=HEADERS, json={
"owner_split_id": "WQby",
"pwa_id": "WZAX",
"weight": 70,
}, timeout=30)
flow = response.json()["data"]["pwa_flow"]
print("Создан поток", flow["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_flows`, {
method: 'POST',
headers,
body: JSON.stringify({
owner_split_id: 'WQby',
pwa_id: 'WZAX',
weight: 70,
}),
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
console.log('Создан поток', data.pwa_flow.id);Ответ - созданный поток в data.pwa_flow. Если weight не передан, в этом ответе его нет - вес равен 1.
Ошибки
| Код | message | Когда |
|---|---|---|
422 | The owner split id field is required. | Не передан owner_split_id или передан несуществующий |
422 | The pwa id field is required. | Не передан pwa_id или передан несуществующий |
422 | You do not have access to this resource | Сплит или PWA, которых вы не видите: customer - только свои |
422 | This resource belongs to another team | PWA из другой команды, не той, что у сплита |
422 | This PWA is already in the split. | У сплита уже есть поток с этим PWA |
422 | The weight field must be at least 0. | weight меньше нуля |
422 | The weight field must be an integer. | weight - не целое число |
Команда потока берётся из сплита, team_id в теле запроса не нужен. Одно PWA добавляется в сплит один раз: повторный запрос ответит 422. Если старый поток с этим PWA удалён (в архиве), добавить PWA снова можно.
Трафик получают только запущенные PWA: если PWA из потока остановлено или в архиве, его доля делится между остальными потоками.
Изменение веса
PUT/pwa_flows/{id}
Меняет только weight (и override_offer). Остальные поля - pwa_id, owner_split_id, team_id и другие - игнорируются: поток нельзя перенести в другой сплит или на другое PWA. Чтобы поменять PWA в сплите, удалите поток и добавьте новый.
curl -X PUT https://panel.example.com/api/pwa_flows/ymqy \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"weight": 50}'<?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_flows/ymqy', ['json' => ['weight' => 50]]);
$flow = json_decode($response->getBody(), true)['data']['pwa_flow'];
echo "Новый вес: {$flow['weight']}" . 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_flows/ymqy", headers=HEADERS, json={"weight": 50}, timeout=30)
flow = response.json()["data"]["pwa_flow"]
print("Новый вес:", flow["weight"])// 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_flows/ymqy`, {
method: 'PUT',
headers,
body: JSON.stringify({ weight: 50 }),
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
console.log('Новый вес:', data.pwa_flow.weight);Ответ - поток после изменения в data.pwa_flow. Новые веса доходят до трафика в течение трёх минут.
Ошибки
| Код | message | Когда |
|---|---|---|
404 | Not found | Неверный идентификатор |
403 | This action is unauthorized. | Объект принадлежит не вашей команде |
422 | The weight field must be an integer. | weight - не целое число |
422 | The weight field must be at least 0. | weight меньше нуля |
Вес 0 вместо удаления
Поток с весом 0 остаётся в сплите, но трафик не получает. Так удобно временно выключить PWA из раздачи, а потом вернуть вес.
Удаление PWA из сплита
DELETE/pwa_flows/{id}
Убирает поток в архив: PWA перестаёт получать трафик этого сплита, статистика потока сохраняется. Архивные потоки видны в списке с archived=1.
curl -X DELETE https://panel.example.com/api/pwa_flows/ymqy \
-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_flows/ymqy');
echo $response->getStatusCode() === 200 ? 'PWA убрано из сплита' . 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_flows/ymqy", headers=HEADERS, timeout=30)
print("PWA убрано из сплита" 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_flows/ymqy`, { method: 'DELETE', headers, signal: AbortSignal.timeout(30000) });
console.log(response.ok ? 'PWA убрано из сплита' : 'Ошибка');Ответ: {"data": true}.
Ошибки
| Код | message | Когда |
|---|---|---|
404 | Not found | Неверный идентификатор |
403 | This action is unauthorized. | Объект принадлежит не вашей команде |