Save legal document
Legal
Save legal document
Create or replace the Terms & Conditions or Privacy Policy.
PUT
Save legal document
Overview
Writes a legal document in place. There is no create/delete pair here — the slug set is fixed, so this either writes the first revision of a document or replaces the existing one.Authentication
Bearer admin token. SUPER or MODERATOR only; FINANCE is read-only on this surface.Request body
| Field | Type | Notes |
|---|---|---|
title | string | 1–200 chars |
bodyHtml | string | 1–200,000 chars. Sanitized before storage — see below. |
effectiveAt | string | ISO-8601. Shown to users as “Last updated”. |
isPublished | boolean | false keeps it out of the public endpoints |
Sanitizing
bodyHtml is run through a fixed allowlist before it is written, so the stored value is always safe and readers never have to sanitize:
- Kept:
h1–h4,p,ul/ol/li,strong/b,em/i,u,a,br,hr,blockquote, and table tags. - Stripped:
<script>(and its contents),<style>,<iframe>,<img>, event handlers such asonclick,style/class/idattributes, and anyjavascript:ordata:URL. - Forced: every
<a>getsrel="noopener noreferrer". - Link schemes are limited to
http,https,mailto,tel.
400 VALIDATION_FAILED rather than saving an empty page.
Versioning
version auto-increments only when the title or bodyHtml actually changed. Toggling isPublished or correcting effectiveAt deliberately does not bump it, so the number stays meaningful as a “has the wording changed?” signal.
Response — 200 OK
The saved document, in the same shape as the get endpoint.
Errors
| Status | Code | When |
|---|---|---|
400 | VALIDATION_FAILED | Bad slug, missing/over-length field, or a body left empty by sanitizing |
403 | FORBIDDEN | Caller is not SUPER or MODERATOR |
Audit
Alegal.saved audit row is written on success, recording the title, resulting version and publish state. The body itself is not stored in the audit log — it is far too large.
Seeding
A fresh environment is seeded with placeholder copy viapnpm seed:legal, which runs on every deploy. That seed is insert-only: once a document exists it is never touched again, so a deploy can never overwrite copy published through this endpoint.