PD Документация ← На главную

Аутентификация

Каждый запрос к API несёт учётные данные в заголовке Authorization. Их три вида.

Секретный API-ключ (pd_…)

Полный доступ к одному приложению с ваших серверов. Создаётся в Приложения → Настройки → API-ключи; открытый текст показывается один раз при создании, далее хранится только хеш.

http
Authorization: ApiKey pd_ВАШ_СЕКРЕТНЫЙ_КЛЮЧ

Работает и в REST API, и в GraphQL:

bash
curl -X POST https://api.pushdata.ru/api/graphql \
  -H "Authorization: ApiKey pd_ВАШ_СЕКРЕТНЫЙ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"query":"{ contacts(appId: \"APP_ID\") { id externalId } }"}'
Безопасность: никогда не встраивайте секретный ключ в клиентский код и не публикуйте его в репозиториях. При утечке немедленно отзовите его (Приложения → Настройки → API-ключи → Отозвать) и создайте новый.

Публичный API-ключ (pk_…)

Можно безопасно встраивать в браузеры и мобильные приложения. Ограничен публичной поверхностью независимо от схемы заголовка:

ЭндпоинтНазначение
POST /api/v1/public/devices, DELETE /api/v1/public/devicesРегистрация / деактивация вызывающего устройства
POST /api/v1/eventsОтчёт о delivered / opened / clicked
GET /api/v1/public/inbox, …/unread_count, POST …/:id/read, POST …/read_allIn-app inbox вызывающего пользователя
GET /api/v1/public/apps/:id/vapidПубличный VAPID-ключ приложения для Web Push
http
Authorization: Public pk_ВАШ_ПУБЛИЧНЫЙ_КЛЮЧ

Эти эндпоинты отвечают на CORS для любого origin. Публичный ключ на любом другом эндпоинте отклоняется с 403 forbidden.

Проверка идентичности

При включённой опции Приложения → Настройки → Проверка идентичности публичный запрос, заявляющий user_id, должен также нести X-Identity-Hash: <hex HMAC-SHA256(user_id, secret)>, вычисленный на вашем сервере с секретом проверки идентичности приложения. Без этого любой владелец публичного ключа мог бы зарегистрировать устройство (или прочитать inbox) под чужим id. Новое приложение создаётся с включённой проверкой: секрет показывается один раз при создании (рядом с API-ключом), в настройках его можно перевыпустить. Официальные клиенты шлют заголовок, как только ваш бэкенд выдаёт хеш: браузерный SDK через identityHash, iOS-пакет через identityHash, Android-клиент через registerDevice(token, userId, identityHash). Пока бэкенд его не выдаёт, регистрируйте устройства без user_id (анонимным устройствам хеш не нужен) или выключите проверку в настройках приложения — там при этом показывается предупреждение (user_id становится публичной информацией).

Роли в организации

Доступ к приложению даёт участие в его организации. owner управляет всем, включая биллинг, участников и удаление; admin дополнительно управляет API-ключами, учётными данными провайдеров и вебхуками; member делает повседневную работу (рассылки, контакты, шаблоны, каналы, сценарии); viewer всё видит и ничего не меняет: любая запись для viewer отклоняется с 403. API-ключи — не участники: секретный ключ действует с полными правами над своим приложением, публичный — только на публичной поверхности SDK.

Сессия дашборда

Панель входит без пароля: одноразовый код на e-mail (requestLoginCodeverifyLoginCode, шесть цифр, 10 минут, пять попыток), VK ID или Яндекс ID (/api/auth/oauth/vk|yandex/start). Первый вход неизвестного адреса создаёт аккаунт и организацию на тарифе Free (пока регистрация открыта; в режиме «по приглашению» аккаунт создаёт только ссылка из раздела Команда, а страница входа об этом предупреждает). VK ID и Яндекс ID привязываются к аккаунту с тем же e-mail: Яндекс подтверждает адрес — привязка сразу; VK ID — после кода на этот адрес (страница входа запросит его сама). Привязанные входы видны в Настройки → Безопасность → Внешние входы, там же их можно отвязать — вход по коду остаётся всегда. Сервер отвечает JWT (7 дней) и ставит его HttpOnly-cookie pd_session (SameSite=Lax, Secure в production); сам дашборд токен в браузере не хранит и аутентифицируется только cookie. Скрипт или CLI могут вместо этого передавать полученный токен как Authorization: Bearer <token>. logout гасит cookie и отзывает сам токен сеанса (его копия перестаёт работать); signOutEverywhereНастройки → Безопасность → «Выйти на всех устройствах» — завершает все сеансы аккаунта сразу. Сессии — для людей; интеграции должны использовать API-ключи.

Аккаунт принадлежит пользователю: exportMyAccountData возвращает всё, что платформа хранит о вошедшем пользователе (профиль без секретов, участие в организациях, внешние входы), а deleteAccount(code) удаляет его — код из письма, отправленного на адрес аккаунта (requestLoginCode для своего e-mail), почта здесь — второй фактор. Организации, которыми пользователь владеет, обрабатываются явно: есть другой владелец — пользователь просто выходит; пользователь единственный участник — организация удаляется с приложениями и данными; есть другие участники, но нет другого владельца — отказ 409 transfer_ownership_first; у организации есть платежи — отказ 409 organization_has_payments (финансовые записи сохраняются). Обе операции — в Настройки → Данные и Удалить аккаунт.

Лимиты запросов

Каждый ответ несёт X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset. Лимиты считаются на приложение (по классу ключа) и на IP для анонимных запросов; 429 rate_limited означает «подождите до момента сброса». У публичного ключа свой бюджет на приложение и IP клиента, так что один посетитель не исчерпает бюджет серверной интеграции, а регистрация устройств по публичному ключу (POST /api/v1/public/devices) сидит в отдельной, более узкой корзине. 503 rate_limiter_unavailable с Retry-After означает, что хранилище лимитера было недоступно и запрос отклонён, а не пропущен: повторите через указанное число секунд.