Уведомления
Уведомления — это сообщения, которые доставляются на устройства через push-провайдеры (FCM, APNs, Web Push) или контактам через канал (email, SMS, MAX, in-app, Telegram). Здесь описан REST API (/api/v1) в том виде, в котором его реализует сервер; GraphQL API, которым пользуется дашборд, предоставляет те же операции.
Аутентификация
Есть два вида API-ключей (Приложения → Настройки → API-ключи):
| Ключ | Заголовок | Где может храниться | Операции |
|---|---|---|---|
Секретный pd_… | Authorization: ApiKey pd_… | Только ваши серверы | Всё, что описано ниже |
Публичный pk_… | Authorization: Public pk_… | Браузеры, мобильные приложения | Регистрация устройств, события вовлечённости, inbox, VAPID-ключ (/api/v1/public/*) |
Публичный ключ на секретном эндпоинте получает 403 forbidden.
Отправка уведомления
curl -X POST https://api.pushdata.ru/api/v1/notifications \
-H "Authorization: ApiKey pd_ВАШ_СЕКРЕТНЫЙ_КЛЮЧ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-123-placed" \
-d '{
"title": "Новый заказ",
"body": "Ваш заказ №123 оформлен.",
"target": { "user_ids": ["user-123"] },
"data": { "orderId": "123", "action": "open_order" },
"click_action": "https://shop.example/orders/123"
}'Ответ 201:
{ "id": "0192…", "status": "queued" }status равен queued для немедленной отправки (веерная рассылка выполняется асинхронно) и scheduled, если задан scheduled_at.
Тело запроса
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
title | string | ✓ | Заголовок (≤ 1024 символов) |
body | string | ✓ | Текст (≤ 4096 символов) |
target | object | ✓ | Ровно один из ключей ниже (для канальной отправки — см. следующий раздел) |
target.all | true | Все активные устройства приложения | |
target.device_ids | string | Конкретные id устройств (≤ 10 000) | |
target.user_ids | string | Устройства, зарегистрированные с этими user_id | |
target.tags | string | Устройства, у которых в tags есть любой из этих тегов | |
data | object | Произвольные ключ-значение, ≤ 4 КБ в сериализованном виде. Доставляется как есть; сервер добавляет pushdata_notification_id / pushdata_device_id для трекинга | |
click_action | string | URL / deep link, открываемый по нажатию (deep_link принимается как синоним) | |
icon | string | URL иконки (Android, Web Push) | |
image / image_url | string | URL большого изображения (FCM, Web Push; в APNs передаётся как pushdata_image_url для service extension) | |
badge | number | Счётчик на иконке (iOS) | |
sound | string | Имя звука (по умолчанию "default") | |
scheduled_at | ISO 8601 | Отложенная отправка; до этого момента статус scheduled | |
expires_at | ISO 8601 | TTL push-уведомления: после этого момента не доставляется (APNs expiration, FCM ttl, Web Push TTL) | |
apns_category, actions | Сохраняются внутри data |
template, vars, recurrence* и email_to этим сервером не поддерживаются и отклоняются с 422.
Отправка через канал
Тот же вызов с channel_type уходит не на устройства, а контактам через канал приложения: email, sms, max, in_app — адрес берётся из контакта (email, phone, maxUserId, сам контакт для inbox), telegram — в чат канала. target для канальной отправки описывает контакты: all (все контакты с адресом для этого канала), user_ids (контакты с этими externalId) или contact_ids (PushData-id); device_ids и tags — понятия push, для канала они отклоняются с 422. У Telegram получателя нет — target можно не передавать.
curl -X POST https://api.pushdata.ru/api/v1/notifications \
-H "Authorization: ApiKey pd_ВАШ_СЕКРЕТНЫЙ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"channel_type": "email",
"category": "orders",
"title": "Заказ №123 оформлен",
"body": "Собираем заказ, курьер позвонит перед доставкой.",
"target": { "user_ids": ["user-123"] }
}'| Поле | Тип | Описание |
|---|---|---|
channel_type | push | email | sms | telegram | max | in_app | Без поля — push. Регистр не важен |
channel_id | string | Конкретный канал приложения; без него берётся самый ранний активный канал этого типа. Неизвестный или чужой — 404, выключенный — 400 |
category | string | Категория подписки (≤ 100 символов): контакты, отключившие её для этого канала в настройках, пропускаются |
target.contact_ids | string | PushData-id контактов (≤ 10 000); только для канальных отправок |
title становится темой письма (или первой строкой SMS / сообщения), body — текстом; data доставляется в in-app-сообщении и в вебхуках. У email, SMS, Telegram и MAX нет подтверждения прочтения, поэтому total_delivered для них остаётся 0 (см. ниже).
Идемпотентность
Передавайте необязательный заголовок Idempotency-Key (≤ 255 символов, уникальный в рамках приложения), чтобы повторы были безопасны: повтор с тем же ключом и телом возвращает исходный ответ с Idempotency-Replayed: true; тот же ключ с другим телом — 409 idempotency_conflict. Завершённые ключи хранятся 24 часа.
Квота
Каждый получатель расходует месячный лимит тарифа. Явный список получателей (device_ids; contact_ids или user_ids канальной отправки) больше остатка отклоняется с 402; аудиторная отправка (all, user_ids, tags для push) урезается до остатка при веерной рассылке.
Чтение и отмена
# Одно уведомление со счётчиками (total_targets, total_sent, total_delivered, total_failed, …)
curl https://api.pushdata.ru/api/v1/notifications/0192… -H "Authorization: ApiKey pd_…"
# Отменить запланированное, ожидающее или поставленное в очередь уведомление
curl -X DELETE https://api.pushdata.ru/api/v1/notifications/0192… -H "Authorization: ApiKey pd_…"Поля в snake_case (app_id, click_action, scheduled_at, total_sent, …). Отсутствующий или чужой id — 404.
Счётчики означают одно и то же везде (дашборд, App.stats, аналитика): total_sent — то, что провайдер принял, total_failed — то, что отклонил, доставляемость = total_sent / (total_sent + total_failed). total_delivered — подтверждённые доставки по колбэку устройства (эталонный service worker, iOS/Android SDK или POST /api/v1/track с event: "delivered"); у email, SMS, Telegram, MAX и in-app такого сигнала нет, поэтому для них счётчик остаётся 0 и не является показателем доставки.
Регистрация устройства
Устройство нужно зарегистрировать до того, как оно сможет получать push. Одно и то же тело работает с секретным ключом на /api/v1/devices и с публичным на /api/v1/public/devices:
curl -X POST https://api.pushdata.ru/api/v1/public/devices \
-H "Authorization: Public pk_ВАШ_ПУБЛИЧНЫЙ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"platform": "android",
"token": "fcm-registration-token",
"user_id": "user-123",
"tags": ["beta"],
"timezone": "Europe/Moscow"
}'Ответ 201: { "id": "0192…", "created": true } (created: false, если токен уже был известен и обновлён).
| Поле | Тип | Описание |
|---|---|---|
platform | ios | android | web | Обязательно |
token | string | Токен APNs (64 hex), registration token FCM или URL endpoint Web Push |
user_id | string | Ваш id пользователя (≤ 512). Включает target.user_ids; должен совпадать с externalId контакта для стирания/экспорта и отписок |
tags | string | ≤ 50 тегов для target.tags |
metadata | object | Произвольные данные, ≤ 4 КБ |
timezone | string | Имя IANA |
environment | sandbox | production | Окружение APNs токена |
category | chrome | firefox | safari | edge | opera | Семейство браузера для web-устройства (дашборд группирует по нему) |
web_push_p256dh, web_push_auth | string | Обязательны для web (ключи PushSubscription в base64url) |
Один токен — одно устройство: повторная регистрация под другим user_id переводит устройство новому пользователю (прежний перестаёт получать свои push). При выходе из аккаунта деактивируйте его:
curl -X DELETE https://api.pushdata.ru/api/v1/public/devices \
-H "Authorization: Public pk_…" -H "Content-Type: application/json" \
-d '{ "token": "fcm-registration-token" }'Управление устройствами секретным ключом: GET /api/v1/devices?user_id=&platform=&status=&page=&page_size= (постранично { data, total }, токены никогда не возвращаются), PUT /api/v1/devices/:id ({ "tags": [...] }), DELETE /api/v1/devices/:id, DELETE /api/v1/devices ({ "token": … }).
События вовлечённости
Сообщайте delivered, opened и clicked с устройства. Пара (notification_id, device_id) адресует доставку; оба id есть в payload push-уведомления (pushdata_notification_id, pushdata_device_id).
curl -X POST https://api.pushdata.ru/api/v1/events \
-H "Authorization: Public pk_…" -H "Content-Type: application/json" \
-d '{ "type": "opened", "notification_id": "0192…", "device_id": "0192…" }'Ответ 202 { "accepted": true }. Серверные интеграции могут использовать POST /api/v1/track с секретным ключом и delivery_log_id либо notification_id + device_token.
Формат ошибок
Каждая ошибка — { "error": { "code", "message", "details"? } } с HTTP-статусом.
| Статус | code | Значение |
|---|---|---|
400 | invalid_argument | Некорректное тело, target или id |
401 | unauthorized | Нет или неверный API-ключ |
402 | payment_required | Лимит тарифа исчерпан или подписка просрочена |
403 | forbidden | Публичный ключ на секретной операции |
404 | not_found | Неизвестный или чужой ресурс |
409 | idempotency_conflict, app_inactive | Ключ повторён с другим телом; приложение деактивировано |
411 | length_required | Тело без Content-Length (chunked) — API его не принимает |
413 | payload_too_large | Тело больше 1 МиБ — разбейте запрос |
415 | unsupported_media_type | Тело не application/json |
422 | validation_error | Поле не прошло валидацию или не поддерживается |
429 | rate_limited | Превышен лимит запросов (заголовки X-RateLimit-*) |
500 | internal_error | Внутренняя ошибка сервера |
503 | rate_limiter_unavailable | Хранилище лимитера недоступно — повторите через Retry-After |