---
title: Согласия и юридические документы
description: 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 опциональный

| Чекбокс | Required | `doc_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 регистрации (соглашение + персональные данные), не оферты пейвола.

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

| Чекбокс | Required | `doc_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)

```ts
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)

```dart
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:

```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.
