Skip to content

Пуші ​

Методи для пуш-сповіщень: завести пуш, змінити тексти й розклад, дізнатися розмір аудиторії, надіслати одразу, наклонувати й прибрати в архів. Як влаштовані пуші, типи, розклад і фільтр, див. розділ «Пуш-сповіщення».

МетодАдресаЩо робить
GET/pwa_pushesСписок пушів
GET/pwa_pushes/{id}Один пуш
POST/pwa_pushesСтворити пуш
PUT/pwa_pushes/{id}Змінити, увімкнути, вимкнути, повернути з архіву
GET/pwa_pushes/{id}/audienceСкільки підписників отримає пуш
POST/pwa_pushes/{id}/sendНадіслати зараз
POST/pwa_pushes/{id}/cloneКлонувати
DELETE/pwa_pushes/{id}Прибрати в архів
POST/pwa_pushes/previewПоказати, як текст із варіантами прийде підписнику
POST/pwa_pushes/uniqueizeПереписати текст у варіанти за допомогою AI

Замініть ВАШ_КЛЮЧ і panel.example.com на свої.

Список пушів ​

GET/pwa_pushes

Пуші ваших команд, нещодавно змінені зверху. Архівні не показуються.

ПараметрЩо фільтрує
searchЧастина назви
typemanual, scheduled або triggered
statusactive або inactive
team_idКоманда
pwa_idПуші, які дійдуть до підписників цього PWA
archived1 - разом з архівними
page, per_pageСторінка та її розмір (за замовчуванням 100)
bash
curl "https://panel.example.com/api/pwa_pushes?status=active&pwa_id=WZAX" \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json"
php
<?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_pushes', ['query' => ['status' => 'active', 'pwa_id' => 'WZAX']]);
$pushes = json_decode($response->getBody(), true)['data']['pwa_pushes'];

foreach ($pushes as $push) {
    echo "{$push['name']}: надіслано {$push['sent_count']}, кліків {$push['clicked_count']}\n";
}
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

response = requests.get(f"{API}/pwa_pushes", headers=HEADERS, params={"status": "active", "pwa_id": "WZAX"}, timeout=30)
pushes = response.json()["data"]["pwa_pushes"]

for push in pushes:
    print(push["name"], "надіслано", push["sent_count"], "кліків", push["clicked_count"])
js
// 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({ status: 'active', pwa_id: 'WZAX' });
const response = await fetch(`${API}/pwa_pushes?${params}`, {
  method: 'GET',
  headers,
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

for (const push of data.pwa_pushes) {
  console.log(push.name, 'надіслано', push.sent_count, 'кліків', push.clicked_count);
}
Відповідь
json
{
  "data": {
    "meta": { "current_page": 1, "per_page": 100, "last_page": 1, "total": 1 },
    "pwa_pushes": [
      {
        "id": "WZAX",
        "name": "Evening reminder",
        "type": "scheduled",
        "status": "active",
        "default_lang": "en",
        "config": {
          "messages": {
            "en": { "title": "{Hey|Hi}, your plan for today is ready", "body": "Just 15 minutes - start now", "url": null, "icon": null }
          },
          "schedule": { "slots": [ { "days": [1, 2, 3, 4, 5], "time": "19:00" } ] },
          "filter": { "pwa_ids": ["WZAX"], "countries": ["US"], "statuses": ["installed"] }
        },
        "sent_count": 1250,
        "failed_count": 14,
        "clicked_count": 96,
        "archived": false,
        "last_run_at": "2026-10-05T19:00:00.000000Z",
        "team": { "id": "WQby", "name": "Team A" },
        "created_at": "05 Oct 2026 14:23",
        "updated_at": "05 Oct 2026 14:23"
      }
    ]
  }
}

Лічильники за весь час: sent_count - доставлено, failed_count - не доставлено, clicked_count - кліків. last_run_at - коли пуш надсилався востаннє; на відміну від решти дат він приходить у форматі ISO 8601.

Помилки
КодmessageКоли
422The selected type is invalid.type не з manual, scheduled, triggered
422The selected status is invalid.status не active і не inactive

Один пуш ​

GET/pwa_pushes/{id}

Той самий об'єкт, що в списку, у data.pwa_push.

bash
curl https://panel.example.com/api/pwa_pushes/WZAX \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json"
php
<?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,
]);

$push = json_decode($api->get('pwa_pushes/WZAX')->getBody(), true)['data']['pwa_push'];

echo "{$push['name']}: {$push['type']}, {$push['status']}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

push = requests.get(f"{API}/pwa_pushes/WZAX", headers=HEADERS, timeout=30).json()["data"]["pwa_push"]

print(push["name"], push["type"], push["status"])
js
// 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_pushes/WZAX`, {
  method: 'GET',
  headers,
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log(data.pwa_push.name, data.pwa_push.type, data.pwa_push.status);
Помилки
КодmessageКоли
404Not foundПуша з таким id немає
403This action is unauthorized.Пуш чужої команди або створений іншим користувачем (для customer)

Створення пуша ​

POST/pwa_pushes

ПолеОбов'язковоЩо це
nameтакНазва пуша в панелі
team_idтакКоманда пуша
typeтакmanual - лише за send, scheduled - за розкладом, triggered - через час після події підписника
default_langтакМова, текст якої отримають підписники без власного перекладу
statusніactive - працює за розкладом і тригерами. За замовчуванням inactive
config.messagesніТексти за мовами: ключ - код мови, усередині title (обов'язковий, до 120 символів), body (до 500), url, icon
config.schedule.slotsніСлоти: days - дні тижня від 1 (пн) до 7 (нд), time - час ГГ:ХХ за UTC. Без слотів пуш scheduled збережеться, але не надішлеться жодного разу
config.schedule.delay_afterніЗатримки після install, registration, deposit: 30m, 2h, 3d; null - тригер вимкнено. Без затримок пуш triggered не надішлеться жодного разу
config.filterніКому надсилати: pwa_ids - PWA, countries - дволітерні коди країн, statuses - installed, registered, deposited

У customer team_id підставляється сам - його команда.

Порожній фільтр означає «усі підписники всіх PWA команди». У pwa_ids можна вказувати лише PWA команди пуша, до яких у вас є доступ, інакше 422. Підписники вимкнених і архівних PWA до аудиторії не потрапляють: їхні застосунки не відкриваються.

У title і body можна писати варіанти тексту - {Hey|Hi} та інші конструкції з розділу «Пуш-сповіщення»: кожен підписник отримає свою комбінацію.

bash
curl -X POST https://panel.example.com/api/pwa_pushes \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Evening reminder",
    "team_id": "WQby",
    "type": "scheduled",
    "default_lang": "en",
    "status": "active",
    "config": {
      "messages": { "en": { "title": "{Hey|Hi}, your plan for today is ready", "body": "Just 15 minutes - start now" } },
      "schedule": { "slots": [ { "days": [1, 2, 3, 4, 5], "time": "19:00" } ] },
      "filter": { "pwa_ids": ["WZAX"], "countries": ["US"], "statuses": ["installed"] }
    }
  }'
php
<?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_pushes', ['json' => [
    'name' => 'Evening reminder',
    'team_id' => 'WQby',
    'type' => 'scheduled',
    'default_lang' => 'en',
    'status' => 'active',
    'config' => [
        'messages' => ['en' => ['title' => '{Hey|Hi}, your plan for today is ready', 'body' => 'Just 15 minutes - start now']],
        'schedule' => ['slots' => [['days' => [1, 2, 3, 4, 5], 'time' => '19:00']]],
        'filter' => ['pwa_ids' => ['WZAX'], 'countries' => ['US'], 'statuses' => ['installed']],
    ],
]]);
$pushId = json_decode($response->getBody(), true)['data']['pwa_push']['id'];

echo "Створено пуш {$pushId}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

response = requests.post(f"{API}/pwa_pushes", headers=HEADERS, json={
    "name": "Evening reminder",
    "team_id": "WQby",
    "type": "scheduled",
    "default_lang": "en",
    "status": "active",
    "config": {
        "messages": {"en": {"title": "{Hey|Hi}, your plan for today is ready", "body": "Just 15 minutes - start now"}},
        "schedule": {"slots": [{"days": [1, 2, 3, 4, 5], "time": "19:00"}]},
        "filter": {"pwa_ids": ["WZAX"], "countries": ["US"], "statuses": ["installed"]},
    },
}, timeout=30)
push_id = response.json()["data"]["pwa_push"]["id"]

print("Створено пуш", push_id)
js
// 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_pushes`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    name: 'Evening reminder',
    team_id: 'WQby',
    type: 'scheduled',
    default_lang: 'en',
    status: 'active',
    config: {
      messages: { en: { title: '{Hey|Hi}, your plan for today is ready', body: 'Just 15 minutes - start now' } },
      schedule: { slots: [{ days: [1, 2, 3, 4, 5], time: '19:00' }] },
      filter: { pwa_ids: ['WZAX'], countries: ['US'], statuses: ['installed'] },
    },
  }),
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log('Створено пуш', data.pwa_push.id);

Відповідь - створений пуш у data.pwa_push, у тому ж вигляді, що й GET/pwa_pushes/{id}. Пуш зі статусом active почне надсилатися в найближчий відповідний слот або за тригером - без окремого запуску.

Помилки
КодmessageКоли
422The name field is required.Не передано обов'язкове поле - так само для team_id, type, default_lang
422You do not have access to this teamteam_id команди, у якій вас немає
422The selected type is invalid.type не з manual, scheduled, triggered
422Every message needs a title.У тексту якоюсь мовою немає title
422The config.schedule.slots.0.time field must match the format H:i.Час слота не у форматі ГГ:ХХ
422The config.schedule.slots.0.days.0 field must be between 1 and 7.День тижня поза 1-7
422The delay must look like 30m, 2h or 3d.Затримка тригера в іншому форматі
422The selected PWA does not exist.У config.filter.pwa_ids неіснуюче PWA
422You do not have access to this resourceУ config.filter.pwa_ids PWA, до якого у вас немає доступу
422This resource belongs to another teamУ config.filter.pwa_ids PWA іншої команди
422The config.filter.countries.0 field must be 2 characters.Країна не дволітерним кодом

Зміна, увімкнення та вимкнення ​

PUT/pwa_pushes/{id}

Змінює лише передані поля, приймає ті самі поля, що й створення. Зупинити пуш - "status": "inactive", повернути з архіву - "archived": false.

bash
curl -X PUT https://panel.example.com/api/pwa_pushes/WZAX \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"status": "inactive"}'
php
<?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_pushes/WZAX', ['json' => ['status' => 'inactive']]);
$push = json_decode($response->getBody(), true)['data']['pwa_push'];

echo "{$push['name']}: {$push['status']}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

response = requests.put(f"{API}/pwa_pushes/WZAX", headers=HEADERS, json={"status": "inactive"}, timeout=30)
push = response.json()["data"]["pwa_push"]

print(push["name"], push["status"])
js
// 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_pushes/WZAX`, {
  method: 'PUT',
  headers,
  body: JSON.stringify({ status: 'inactive' }),
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log(data.pwa_push.name, data.pwa_push.status);

Відповідь - пуш після зміни в data.pwa_push.

config замінюється повністю

Якщо в запиті є config, він замінює тексти, розклад і фільтр разом: чого немає в запиті, те зітреться. Спершу отримайте пуш, змініть у його config потрібне й надішліть config повністю.

Помилки
КодmessageКоли
422The selected status is invalid.status не active і не inactive
422Every message needs a title.Ті самі перевірки config, що під час створення, включно з PWA в config.filter.pwa_ids
404Not foundПуша з таким id немає
403This action is unauthorized.Пуш чужої команди або створений іншим користувачем (для customer)

Розмір аудиторії ​

GET/pwa_pushes/{id}/audience

Скільки підписників підходить під фільтр пуша просто зараз, без підписників вимкнених і архівних PWA. Зручно перевірити перед надсиланням.

bash
curl https://panel.example.com/api/pwa_pushes/WZAX/audience \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json"
php
<?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,
]);

$count = json_decode($api->get('pwa_pushes/WZAX/audience')->getBody(), true)['data']['count'];

echo "Отримають пуш: {$count}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

count = requests.get(f"{API}/pwa_pushes/WZAX/audience", headers=HEADERS, timeout=30).json()["data"]["count"]

print("Отримають пуш:", count)
js
// 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_pushes/WZAX/audience`, {
  method: 'GET',
  headers,
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log('Отримають пуш:', data.count);

Відповідь: {"data": {"count": 1250}}.

Помилки
КодmessageКоли
404Not foundПуша з таким id немає
403This action is unauthorized.Пуш чужої команди або створений іншим користувачем (для customer)

Надіслати зараз ​

POST/pwa_pushes/{id}/send

Одразу ставить пуш на надсилання всій аудиторії з його фільтра.

Це справжня розсилка

Запит надсилає сповіщення реальним підписникам, і скасувати надсилання не можна. Метод спрацьовує за будь-якого статусу й типу пуша, навіть у вимкненого, і не пам'ятає минулих надсилань: кожен виклик шле пуш усім заново, включно з тими, хто вже отримав його за розкладом або тригером. Архівний пуш не надсилається (422). Не більше 10 надсилань на хвилину на користувача. Не викликайте метод у циклі й під час повторів після помилок мережі - спершу перевірте audience і лічильники.

bash
curl -X POST https://panel.example.com/api/pwa_pushes/WZAX/send \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json"
php
<?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,
]);

$queued = json_decode($api->post('pwa_pushes/WZAX/send')->getBody(), true)['data']['queued'];

echo "Поставлено на надсилання: {$queued}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

queued = requests.post(f"{API}/pwa_pushes/WZAX/send", headers=HEADERS, timeout=30).json()["data"]["queued"]

print("Поставлено на надсилання:", queued)
js
// 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_pushes/WZAX/send`, {
  method: 'POST',
  headers,
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log('Поставлено на надсилання:', data.queued);

Відповідь: {"data": {"queued": 1250}} - скільки підписників поставлено на надсилання. Сама доставка йде у фоні, результат з'явиться в sent_count і failed_count.

Помилки
КодmessageКоли
422An archived push cannot be sentПуш в архіві
429Too many requests. Try again in a minute.Більше 10 надсилань за хвилину
404Not foundПуша з таким id немає
403This action is unauthorized.Пуш чужої команди або створений іншим користувачем (для customer)

Клонування ​

POST/pwa_pushes/{id}/clone

Копії пуша, по одній на кожну назву в names. Копія отримує команду, тип, мову й увесь config оригіналу, а створюється вимкненою та з нульовими лічильниками.

bash
curl -X POST https://panel.example.com/api/pwa_pushes/WZAX/clone \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"names": ["Evening reminder DE"]}'
php
<?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_pushes/WZAX/clone', ['json' => ['names' => ['Evening reminder DE']]]);
$clones = json_decode($response->getBody(), true)['data']['clones'];

foreach ($clones as $clone) {
    echo "{$clone['id']} {$clone['name']}" . PHP_EOL;
}
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

response = requests.post(f"{API}/pwa_pushes/WZAX/clone", headers=HEADERS, json={"names": ["Evening reminder DE"]}, timeout=30)
clones = response.json()["data"]["clones"]

for clone in clones:
    print(clone["id"], clone["name"])
js
// 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_pushes/WZAX/clone`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ names: ['Evening reminder DE'] }),
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

for (const clone of data.clones) {
  console.log(clone.id, clone.name);
}
Відповідь
json
{
  "data": {
    "clones": [
      { "id": "WQby", "name": "Evening reminder DE", "type": "scheduled", "status": "inactive", "default_lang": "en" }
    ]
  }
}
Помилки
КодmessageКоли
422The names field is required.Не передано names
404Not foundПуша з таким id немає
403This action is unauthorized.Пуш чужої команди або створений іншим користувачем (для customer)

Архівування ​

DELETE/pwa_pushes/{id}

Прибирає пуш в архів: він більше не надсилається за розкладом і тригерами, історія й лічильники зберігаються. Повернути - PUT з "archived": false.

bash
curl -X DELETE https://panel.example.com/api/pwa_pushes/WZAX \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json"
php
<?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_pushes/WZAX');

echo 'Пуш в архіві, HTTP ' . $response->getStatusCode() . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

response = requests.delete(f"{API}/pwa_pushes/WZAX", headers=HEADERS, timeout=30)

print("Пуш в архіві, HTTP", response.status_code)
js
// 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_pushes/WZAX`, {
  method: 'DELETE',
  headers,
  signal: AbortSignal.timeout(30000),
});

console.log('Пуш в архіві, HTTP', response.status);

Відповідь: {"data": true}.

Помилки
КодmessageКоли
404Not foundПуша з таким id немає
403This action is unauthorized.Пуш чужої команди або створений іншим користувачем (для customer)

Попередній перегляд тексту ​

POST/pwa_pushes/preview

Збирає з тексту з варіантами одну випадкову комбінацію, як її побачить підписник. Поле text - до 2000 символів. Кожен виклик дає нову комбінацію.

Заголовок і текст пуша можна зібрати одним викликом: замість text передайте title і body (кожне до 2000 символів) - відповідь прийде як {"data": {"title": …, "body": …}}, порожнє поле повернеться порожнім рядком.

bash
curl -X POST https://panel.example.com/api/pwa_pushes/preview \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"text": "{Hey|Hi}, {%RINT=(3,9)} new lessons"}'
php
<?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_pushes/preview', ['json' => ['text' => '{Hey|Hi}, {%RINT=(3,9)} new lessons']]);

echo json_decode($response->getBody(), true)['data']['text'] . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

response = requests.post(f"{API}/pwa_pushes/preview", headers=HEADERS, json={"text": "{Hey|Hi}, {%RINT=(3,9)} new lessons"}, timeout=30)
print(response.json()["data"]["text"])
js
// 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_pushes/preview`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ text: '{Hey|Hi}, {%RINT=(3,9)} new lessons' }),
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log(data.text);

Відповідь: {"data": {"text": "Hey, 7 new lessons"}}.

Помилки
КодmessageКоли
422The text field is required when none of title / body are present.Не передано ні text, ні title / body

Унікалізація з AI ​

POST/pwa_pushes/uniqueize

Переписує звичайну фразу в текст із варіантами, як кнопка Uniqueize with AI у формі пуша. Поля: text - фраза до 2000 символів, lang - код мови (необов'язково).

Працює через AI-провайдера

Метод доступний, лише якщо адміністратор підключив AI-провайдера в налаштуваннях панелі, і кожен виклик витрачає його ліміти. Без провайдера прийде 422 з AI uniqueizer is not configured, якщо провайдер не відповів - 422 з AI uniqueizer is unavailable.

bash
curl -X POST https://panel.example.com/api/pwa_pushes/uniqueize \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"text": "Your plan is ready", "lang": "en"}'
php
<?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' => 60,
]);

$response = $api->post('pwa_pushes/uniqueize', ['json' => ['text' => 'Your plan is ready', 'lang' => 'en']]);
$template = json_decode($response->getBody(), true)['data']['text'];

echo $template . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer ВАШ_КЛЮЧ", "Accept": "application/json"}

response = requests.post(f"{API}/pwa_pushes/uniqueize", headers=HEADERS, json={"text": "Your plan is ready", "lang": "en"}, timeout=60)
template = response.json()["data"]["text"]

print(template)
js
// Node.js 18+, без залежностей; збережіть як script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer ВАШ_КЛЮЧ', Accept: 'application/json', 'Content-Type': 'application/json' };

// AI відповідає довше, ніж зазвичай - тайм-аут 60 секунд
const response = await fetch(`${API}/pwa_pushes/uniqueize`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ text: 'Your plan is ready', lang: 'en' }),
  signal: AbortSignal.timeout(60000),
});
const { data } = await response.json();

console.log(data.text);

Відповідь: {"data": {"text": "{Your|The} plan {is ready|is waiting} {for you|}"}}.

Помилки
КодmessageКоли
422AI uniqueizer is not configuredУ панелі не підключено AI-провайдера
422The text field is required.Не передано text