Consent Registry, чекбоксы регистрации и пейвола, формы сайта, рассылка.

Согласия и юридические документы

Платформа фиксирует доказательство согласия: какой документ и какая редакция приняты, когда, с какого IP/платформы, с каким текстом чекбокса.

Где создавать тексты

ВладелецАдминкаПубличное API
ПриложениеПриложения → «Юридические документы»GET /v1/applications/YOUR_APP_CODE/legal
CMS СайтCMS Сайт → «Юридические документы»GET /v1/sites/YOUR_SITE_CODE/legal

Раздел CMS «Документы» — только произвольные файлы/ссылки для лендинга, не юр. шаблоны.

Слоты doc_kind: privacy_policy, personal_data_consent, marketing_consent, mobile_apps_terms, terms_cyclone, terms_arken, license_offer, payment_data_consent (последний — для приложений).

HTML-страница: GET /v1/legal-documents/{id} (поле public_url в ответе API).

Матрица экранов

Регистрация / вход (приложение) — 2 обязательных + 1 опциональный

ЧекбоксRequireddoc_kind
Я принимаю Пользовательское соглашениедаодин из: mobile_apps_terms, terms_cyclone, terms_arken
Я даю согласие на обработку персональных данныхдаpersonal_data_consent
Я хочу получать новости, обновления и специальные предложения RaidBoss Studioнетmarketing_consent

Опциональный маркетинг не pre-check.

POST /v1/applications/{code}/users/register требует массив consents. Без обязательных → 400 consents_required.

Версии документов (важно)

СитуацияЧто делатьРезультат
Экран auth с галочкамиregisterUser + explicit_consent: trueПишется текущая версия с Platform
Тихий login без UIбез explicit_consent (или не слать «принятие» новых версий)Версии не апгрейдятся
Документы обновились в админкеgetMyConsents → модалка → acceptConsentsНовые версии после явных галочек

id и version бери только из getLegalDocument / pending_reconsent — не хардкодь. version передавай строкой.

needs_reconsent / pending_reconsent касаются только обязательных kinds регистрации (соглашение + персональные данные), не оферты пейвола.

Пейвол / покупка

ЧекбоксRequireddoc_kind
Я принимаю условия Лицензионной офертыдаlicense_offer
Я даю согласие на обработку данных, необходимых для проведения платежанетpayment_data_consent

POST /v1/payments требует consents с license_offer. Отдельное payment_data_consent можно не передавать — обычно покрывается офертой.

Формы сайта (обратная связь / подписка)

Обязательно: personal_data_consent. Рекомендуются ссылки на privacy_policy. Для подписки — опционально marketing_consent.

POST /v1/sites/{code}/leads (или под приложением: .../applications/.../sites/.../leads).

Клиентская интеграция (чеклист)

  1. Перед галочками: getLegalDocument(...) — актуальные id, version, ссылка на текст.
  2. После Auth на экране с галочками: registerUser({ explicit_consent: true, consents }) (Flutter: explicitConsent: true).
  3. После входа / старта: getMyConsents(); если needs_reconsent — модалка → acceptConsents.
  4. Не ставить accepted: true и explicit_consent: true без показанных галочек.
  5. Показывать пользователю error / message из ответа API при ошибке сохранения.

SDK (TypeScript)

import {
  createRaidBossClient,
  CONSENT_CHECKBOX_LABELS,
} from "@raidboss/platform-sdk";

const platform = createRaidBossClient({ /* ... */ });

const terms = await platform.getLegalDocument("mobile_apps_terms");
const pd = await platform.getLegalDocument("personal_data_consent");
const marketing = await platform.getLegalDocument("marketing_consent");

await platform.registerUser({
  platform: "android",
  explicit_consent: true, // экран с галочками; без флага — тихий sync, без апгрейда версий
  consents: [
    {
      document_id: terms.data.id,
      version: String(terms.data.version),
      checkbox_text: CONSENT_CHECKBOX_LABELS.user_agreement,
      accepted: true,
    },
    {
      document_id: pd.data.id,
      version: String(pd.data.version),
      checkbox_text: CONSENT_CHECKBOX_LABELS.personal_data,
      accepted: true,
    },
    {
      document_id: marketing.data.id,
      version: String(marketing.data.version),
      checkbox_text: CONSENT_CHECKBOX_LABELS.marketing,
      accepted: wantMarketing,
    },
  ].filter((c) => c.accepted),
});

const mine = await platform.getMyConsents();
if (mine.data.needs_reconsent) {
  await platform.acceptConsents({
    consents: mine.data.pending_reconsent.map((p) => ({
      document_id: p.document_id,
      version: String(p.published_version),
      checkbox_text: /* текст галочки на экране */,
      accepted: true,
    })),
    source_screen: "reconsent_modal",
  });
}

SDK (Flutter)

final terms = await platform.getLegalDocument('mobile_apps_terms');
final pd = await platform.getLegalDocument('personal_data_consent');

await platform.registerUser(
  platform: 'android',
  explicitConsent: true,
  consents: [
    {
      'document_id': terms['id'].toString(),
      'version': terms['version'].toString(),
      'checkbox_text': 'Я принимаю Пользовательское соглашение',
      'accepted': true,
    },
    {
      'document_id': pd['id'].toString(),
      'version': pd['version'].toString(),
      'checkbox_text': 'Я даю согласие на обработку персональных данных',
      'accepted': true,
    },
  ],
);

final mine = await platform.getMyConsents();
if (mine['needs_reconsent'] == true) {
  // модалка по mine['pending_reconsent'] → галочки
  await platform.acceptConsents(
    sourceScreen: 'reconsent_modal',
    consents: [/* document_id, version.toString(), checkbox_text, accepted */],
  );
}

Методы: listLegalDocuments, getLegalDocument, getMyConsents, acceptConsents, listSiteLegalDocuments, getSiteLegalDocument, submitSiteLead.

HTTP:

POST /v1/applications/YOUR_APP_CODE/users/register
Authorization: Bearer <jwt>
{ "explicit_consent": true, "consents": [ ... ] }

GET  /v1/applications/YOUR_APP_CODE/users/me/consents
POST /v1/applications/YOUR_APP_CODE/users/me/consents

Что хранится в журнале

На каждое принятие: user_id / email, приложение или сайт, doc_kind, версия, content_hash текста, текст чекбокса, IP, UA, платформа, источник (registration / paywall / site_form / newsletter / other с metadata.flow=reconsent для модалки), время.

Админка: карточка пользователя → вкладка Согласия; сайдбар Рассылка — активный marketing_consent + CSV.

Важно

  • Сервер сам считает content_hash по опубликованному тексту — клиенту не доверяем.
  • Версия в consents должна совпадать с опубликованной (строка).
  • Смена версии: старые принятия остаются в журнале; новая — только с галочками (explicit_consent или acceptConsents), не тихим login.