Consent Registry, signup and paywall checkboxes, site forms, mailing list.
Consents & legal documents
The platform stores evidence of consent: which document and revision were accepted, when, from which IP/platform, with which checkbox label.
Where to author texts
| Owner | Admin | Public API |
|---|---|---|
| Application | Applications → Legal documents | GET /v1/applications/YOUR_APP_CODE/legal |
| CMS site | CMS Site → Legal documents | GET /v1/sites/YOUR_SITE_CODE/legal |
CMS Documents is for arbitrary landing files/links only — not legal templates.
doc_kind slots: privacy_policy, personal_data_consent, marketing_consent, mobile_apps_terms, terms_cyclone, terms_arken, license_offer, payment_data_consent (apps).
HTML page: GET /v1/legal-documents/{id} (public_url in API response).
Screen matrix
Registration / sign-in (app) — 2 required + 1 optional
| Checkbox | Required | doc_kind |
|---|---|---|
| I accept the User Agreement | yes | one of mobile_apps_terms, terms_cyclone, terms_arken |
| I consent to personal data processing | yes | personal_data_consent |
| I want news and special offers from RaidBoss Studio | no | marketing_consent |
Do not pre-check optional marketing.
POST .../users/register requires consents. Missing required → 400 consents_required.
Document versions (important)
| Situation | What to call | Result |
|---|---|---|
| Auth screen with checkboxes | registerUser + explicit_consent: true | Current Platform versions are stored |
| Silent login without UI | omit explicit_consent | Versions are not upgraded |
| Docs updated in admin | getMyConsents → modal → acceptConsents | New versions after explicit checkboxes |
Take id / version only from getLegalDocument / pending_reconsent — never hardcode. Send version as a string.
needs_reconsent / pending_reconsent cover registration-required kinds only (agreement + personal data), not paywall offer.
Paywall / purchase
| Checkbox | Required | doc_kind |
|---|---|---|
| I accept the License Offer | yes | license_offer |
| I consent to processing data required for payment | no | payment_data_consent |
POST /v1/payments requires consents with license_offer. Separate payment_data_consent is optional (usually covered by the offer).
Site forms (contact / newsletter)
Required: personal_data_consent. Link privacy_policy. Optional marketing: marketing_consent.
POST /v1/sites/{code}/leads.
Client integration checklist
- Before checkboxes:
getLegalDocument(...)for currentid,version, document URL. - After Auth on the checkbox screen:
registerUser({ explicit_consent: true, consents })(Flutter:explicitConsent: true). - After login / app start:
getMyConsents(); ifneeds_reconsent— modal →acceptConsents. - Never send
accepted: true/explicit_consent: truewithout showing checkboxes. - Surface API
error/messageto the user on save failure.
SDK (TypeScript)
import {
createRaidBossClient,
CONSENT_CHECKBOX_LABELS,
} from "@raidboss/platform-sdk";
const terms = await platform.getLegalDocument("mobile_apps_terms");
const pd = await platform.getLegalDocument("personal_data_consent");
await platform.registerUser({
platform: "android",
explicit_consent: true, // checkbox UI; omit for silent sync (no version upgrade)
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,
},
],
});
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: /* checkbox label on screen */,
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': 'I accept the User Agreement',
'accepted': true,
},
{
'document_id': pd['id'].toString(),
'version': pd['version'].toString(),
'checkbox_text': 'I consent to personal data processing',
'accepted': true,
},
],
);
final mine = await platform.getMyConsents();
if (mine['needs_reconsent'] == true) {
await platform.acceptConsents(
sourceScreen: 'reconsent_modal',
consents: [/* document_id, version.toString(), checkbox_text, accepted */],
);
}
Methods: 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
Consent journal
Each acceptance stores: user/email, app or site, doc_kind, version, text content_hash, checkbox label, IP, UA, platform, source (registration / paywall / site_form / newsletter / other with metadata.flow=reconsent for the modal), timestamp.
Admin: user profile → Consents tab; sidebar Mailing — active marketing_consent + CSV export.
Notes
- Server computes
content_hashfrom published body. - Client-sent
versionmust match the published document (string). - Version bump: old acceptances stay in the ledger; the new version is written only with checkboxes (
explicit_consentoracceptConsents), not via silent login.