Контакты
Контакты (они же подписчики) — это люди, которые получают уведомления. Каждый контакт принадлежит одному приложению и идентифицируется вашим собственным externalId. Контактами управляют через REST (/api/v1/contacts, ниже) и GraphQL API (дашборд использует те же операции).
Как связаны контакты и устройства
Устройство, зарегистрированное с user_id: "user-123", принадлежит контакту с externalId = user-123 в том же приложении. Эта единственная связь определяет всё:
target.user_idsв REST-отправке доставляет на устройства этих контактов;- канальные отправки (email / SMS / MAX / in-app) берут адрес из контакта;
- отписки (
updateContactPreference) действуют на каждый канал, включая push; eraseContact(право на забвение) иexportSubscriberDataохватывают устройства контакта.
Используйте один и тот же идентификатор с обеих сторон.
Создание контакта
Дашборд
Откройте Приложения → Контакты → Новый контакт и заполните поля.
REST
POST /api/v1/contacts — идемпотентный upsert по external_id: первый вызов создаёт контакт (201), повторный — обновляет переданные поля (200); поля, которых нет в теле, не трогаются, metadata заменяется целиком. Поля: external_id, name, email, phone, max_user_id, locale, metadata.
curl -X POST https://api.pushdata.ru/api/v1/contacts \
-H "Authorization: ApiKey pd_ВАШ_СЕКРЕТНЫЙ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"external_id":"user-123","email":"user@example.com","name":"Иван Петров","phone":"+79991234567","locale":"ru","metadata":{"plan":"pro"}}'GET /api/v1/contacts/user-123 возвращает контакт, DELETE /api/v1/contacts/user-123 стирает его вместе с устройствами, настройками и inbox (то же, что eraseContact). Заявки из форм Tilda превращаются в контакты приёмником POST /api/v1/integrations/tilda (см. Интеграции); серверные SDK делают всё это методами upsertContact / getContact / deleteContact.
GraphQL
curl -X POST https://api.pushdata.ru/api/graphql \
-H "Authorization: ApiKey pd_ВАШ_СЕКРЕТНЫЙ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation($input: CreateContactInput!) { createContact(input: $input) { id externalId email } }",
"variables": { "input": { "appId": "APP_ID", "externalId": "user-123", "email": "user@example.com", "name": "Иван Петров", "phone": "+79991234567", "locale": "ru" } }
}'Пара (appId, externalId) уникальна: создание уже существующего контакта возвращает ошибку 409 (conflict). Существующий контакт меняется через updateContact(id, input).
Поля контакта
| Поле | Тип | Описание |
|---|---|---|
externalId | string | Id пользователя в вашей системе (обязателен, уникален в приложении) |
name | string | Отображаемое имя |
email | string | Email (нужен для канала Email) |
phone | string | Телефон (нужен для канала SMS); пробелы и дефисы допустимы, перед отправкой номер приводится к цифрам |
maxUserId | string | Id пользователя в мессенджере MAX (нужен для канала MAX); обычно заполняется сам, когда человек открывает бота по ссылке контакта (maxLink) |
locale | string | Предпочитаемый язык; используются шаблоны с подходящим переводом |
metadata | object | Любые дополнительные данные |
Предпочтения (отписка)
mutation {
updateContactPreference(input: { subscriberId: "CONTACT_ID", category: "marketing", channelType: EMAIL, enabled: false }) {
id
}
}Отправка с category: "marketing" пропускает контакты, отключившие эту категорию для канала, на любом пути: API-отправки, отложенные отправки и SEND-шаги воркфлоу. Отправка без категории не фильтруется.
Право на забвение и экспорт данных
mutation { eraseContact(contactId: "CONTACT_ID") { contactDeleted devicesDeleted deliveryLogsScrubbed } }
query { exportSubscriberData(contactId: "CONTACT_ID") }eraseContact доступен только владельцу и необратим: удаляет контакт, его устройства (в том числе связанные только через user_id), предпочтения и in-app сообщения, а журналы доставки и выполнения воркфлоу анонимизирует. exportSubscriberData возвращает всё, что хранится о субъекте, в JSON.
Контакты в воркфлоу
Передайте PushData-id контакта как subscriberId при запуске воркфлоу (в REST — POST /api/v1/workflows/:id/trigger с contact_external_id или contact_id, см. Сценарии):
mutation {
triggerWorkflow(input: {
workflowId: "019c9a99-..."
subscriberId: "019c9359-..."
payload: { orderId: "ORD-001" }
idempotencyKey: "order-ORD-001-placed"
}) {
id
status
}
}Воркер воркфлоу определяет получателя для каждого SEND-шага по типу канала: email для Email, phone для SMS, maxUserId для MAX, сам контакт для in-app и устройства контакта (по externalId) для push. idempotencyKey (необязателен, уникален в рамках воркфлоу) делает повторный запуск безопасным: возвращается уже начатый запуск вместо нового.