Trust center

Embed
Preview of the card
<a href="https://forumulate.com/guides/trust-center"><img src="https://forumulate.com/guides/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/36aa4df0-1e95-4cef-8ae9-795169441345/pages/69bb1dc7-6b62-40e6-90f5-d12057a907ed/social-card.svg?v=3e7ae33eec8b" alt="Trust center" width="600" height="315"></a>

A Legal space's register (/legal/{org}) grows into a trust center the way Vanta's, Drata's or SafeBase's do: compliance badges over the documents, a library of reports some of which are gated behind an NDA or your approval, a controls catalogue, a sub-processor list procurement tools can poll, a privacy-request form, and a security.txt. All of it is settings on the Legal space's theme, under theme.legal.trust, plus a few queues in the studio. Nothing here is generated: every band draws nothing until you give it something to say, so turning the bands on costs a plain register nothing.

How documents themselves work (pages, editions, acceptance) is in Legal spaces.

The bands

A Legal space's front page is a composed document. Until you edit it, it is generated as the intro band, then compliance, documents, access and status. These bands are offered but never generated, so you place them yourself: subscribe, controls, faq, updates, locations, contacts and dsar.

Band

Reads

Draws

compliance

trust.compliance

Certification and framework badges (SOC 2, ISO 27001, GDPR…)

documents

the space's pages

The register itself

access

trust.access

The document library: public reports, and gated ones with "Request access"

status

your status page

The org's status page's live state (off until trust.status is set)

controls

trust.controls

The security controls catalogue, by category

faq

trust.faq

Security questions and answers

updates

trust.updates + editions

Your security notices, and the newest editions from the register's feed

locations

trust.locations

Where data is hosted

contacts

trust.contacts

Who to contact: security, privacy, DPO

dsar

trust.dsar

The privacy-request form

subscribe

the register's email list

"Get updates" for new editions

Set the bands' content with the space theme:

curl -X PATCH "https://forumulate.com/api/orgs/$ORG/spaces/$LEGAL/theme" \
  -H "Authorization: Bearer $FORUMULATE_TOKEN" -H "Content-Type: application/json" \
  -d '{ "legal": { "trust": {
        "compliance": { "heading": "Compliance", "style": "tiles", "columns": 4,
          "items": [
            { "name": "SOC 2 Type II", "status": "certified", "auditPeriod": "1 Jan – 31 Dec 2026",
              "validUntil": "2027-03-31", "href": "/legal/acme/soc2" },
            { "name": "ISO 27001", "status": "in-progress", "progress": 72 } ] },
        "status": "uptime" } } }'

Like every theme key, a misspelt one is a 422 that names its path.

Compliance badges

trust.compliance: heading, style (tiles or list, unset tiles), columns (2–6 tiles to a row from 640px, unset the grid's own fill), card (a tile's surface: surface flat / outline / raised, radius, pad, shadow), and up to 24 items:

Key

What it does

name

Required. "SOC 2 Type II".

status

certified, compliant or in-progress.

logo

The mark. An image on our CDN; an external one is proxied, never hot-linked.

logoDark

The mark on a dark page (a white wordmark). Unset = logo there too.

href

The report, the certificate, or the page that explains it.

note

One line under the name ("Audited annually by …").

auditPeriod

The period the report covers.

validUntil

YYYY-MM-DD: the day the certificate stops being current.

progress

0–100: how far an in-progress framework has come.

Controls catalogue

trust.controls: heading, style (grid, a card per category, or list, ruled sections), and up to 12 categories, each with name, description and up to 40 items of { name, status, note }. status is passing, monitoring or planned.

The catalogue is what you write. Nothing connects it to a monitoring tool for you; see What you need to set up.

Status

trust.status: pill (one line), card (a titled box with the link), uptime (the card with the status page's 90-day uptime figure) or none. Unset is none: a register does not start reporting outages by itself.

The band reads your organization's status page only when the organization has exactly one public Status space; with none or several it draws nothing, because a wrong status is worse than none. GET /public/orgs/{orgId}/legal/trust.json answers which status space and which contact space the trust center uses.

Security FAQ, notices, locations, contacts

Key

Shape

trust.faq

heading, up to 40 items of { q, a } (plain text, paragraphs kept), moreHref (an FAQ space to link)

trust.updates

heading, editions (how many of the newest editions to list, 0–20, unset 5), up to 30 notices of { date, title, body, href }

trust.locations

heading, up to 30 items of { name, region, provider, purpose }

trust.contacts

heading, up to 12 items of { role, name, href, note }

Every link in these bands is a /path on your site, an https:// address or mailto:.

The trust words in other languages

The headings and the NDA are yours, so they do not translate themselves. trust.translations holds them per locale (de, pt-BR, up to 20), and the reader's path locale picks one:

{ "legal": { "trust": { "translations": {
  "de": { "complianceHeading": "Zertifizierungen", "accessHeading": "Dokumente",
          "nda": "Mit dem Absenden stimmen Sie zu …" } } } } }

The words you can translate: complianceHeading, accessHeading, controlsHeading, faqHeading, updatesHeading, locationsHeading, contactsHeading, dsarHeading, dsarIntro and nda.

The document library and gated access

trust.access lists up to 24 documents. Each is public (a plain link) or request, and a request document has a gate:

gate

What the reader does

What happens

link (default)

Follows "Request access"

Goes to access.requestHref, else your contact space (when you have exactly one public one)

nda

Fills in name, email, company and ticks the NDA

A link valid for linkDays is emailed at once. The NDA's text is stored with the request, verbatim

approve

Fills in name, email, company and a reason

The request waits in the studio's Access requests queue until you approve or deny it

{ "legal": { "trust": { "access": {
  "heading": "Reports",
  "nda": "By requesting this document you agree to keep it confidential …",
  "linkDays": 14,
  "autoApproveDomains": ["bigcustomer.com"],
  "items": [
    { "title": "Penetration test summary", "access": "public", "href": "/legal/acme/pentest" },
    { "title": "SOC 2 Type II report", "access": "request", "gate": "nda",
      "watermark": true, "pageId": "3f6c…" },
    { "title": "Architecture overview", "access": "request", "gate": "approve",
      "href": "/p/acme/internal/architecture?share=…" } ] } } } }

Key

Default

What it does

requestHref

contact space

Where a link gate sends the reader.

nda

—

The NDA text a nda gate asks the reader to accept (plain text, up to 6000 characters).

linkDays

7

How long an emailed access link works (1–90 days).

autoApproveDomains

none

A requester whose address is at one of these domains is approved at once (the address's own domain, so a lookalike subdomain of another domain does not pass).

items[].watermark

off

Issue a PDF of pageId, with "Issued to name email · date" across every page, instead of sending the reader to href.

items[].pageId

—

The page a watermarked copy is made from, usually in a private space.

What the reader gets is a link to /legal/{org}/access/{token}. The token is stored only as a hash. Each time the link is opened, a view is counted, so the queue shows how often each requester opened it and when they last did (the viewer log). An expired, denied or withdrawn link answers 404. A watermarked item answers with its PDF from GET /public/orgs/{orgId}/trust/access/{token}/document.pdf, which is never kept by a shared cache.

The request call is public, and it never tells you whether an address has asked before:

curl -X POST "https://forumulate.com/api/public/orgs/$ORG/trust/access-requests" \
  -H "Content-Type: application/json" \
  -d '{ "document": "SOC 2 Type II report", "name": "Ada", "email": "ada@bigcustomer.com",
        "company": "BigCustomer", "ndaAccepted": true }'
# → { "ok": true, "status": "granted" }   or "pending" for an approval

document is the item's title. A title whose gate is not nda or approve is refused with a 422. A nda request without ndaAccepted: true is also a 422. When your organization has a CAPTCHA configured, the request must carry captchaToken.

The owner's side:

GET  /orgs/{orgId}/trust/access-requests                 # newest first, with views
POST /orgs/{orgId}/trust/access-requests/{id}/decision   { "decision": "approve" }   # or "deny"

Approving emails the link (the legal.access-link email template); denying closes the request. Every request also fires the legal.access_requested webhook with the document, gate, status, name, email and company. That webhook is how a request reaches your CRM.

Sub-processors as data

A document with a table in its Sub-processors section (the subprocessors slot) publishes that table as rows. The columns are found by their headings (entity, purpose, location, transfer mechanism, added), not by their order:

GET /public/orgs/{orgId}/legal/{kind}/subprocessors
# → { kind, title, version, rows: [...], since: { version, added, removed, changed }, upcoming: {..., effectiveAt} }

The same data is at /legal/{org}/{kind}/subprocessors.json on the reader. A procurement tool can poll that address instead of scraping the page. It is 404 when the document has no such table.

Key

Default

What it does

legal.subprocessors.sortable

on

Click a column heading to sort the table.

legal.subprocessors.changes

summary

"Added since edition 4: …, removed: …" over the table, and the same for an upcoming edition. none hides it.

legal.subprocessors.noticeDays

none

The notice your DPA promises before a change takes effect (0–180). It is stated with the upcoming change, and an upcoming edition that gives less notice is flagged to you in the studio.

Readers who subscribe to the register hear which rows an edition adds or removes.

Privacy requests

trust.dsar turns on the dsar band: a form where anyone can file a privacy request.

Key

Default

What it does

heading

the reader's own words

The band's heading.

intro

—

A sentence over the form (up to 500 characters).

kinds

all four

Which requests it offers: access, delete, correct, opt-out.

POST /public/orgs/{orgId}/trust/privacy-requests
  { "kind": "delete", "name": "Ada", "email": "ada@example.com", "details": "…" }

A kind the form does not offer is refused with a 422 that lists the kinds it does offer. Each request:

  • is due 30 days after it arrives (dueAt, by the database's clock);

  • is mailed to your support address (the legal.privacy-request template), when you have set one;

  • fires the legal.privacy_requested webhook;

  • waits in the studio's Privacy requests queue, sorted by deadline, until you close it as done or declined.

GET  /orgs/{orgId}/trust/privacy-requests
POST /orgs/{orgId}/trust/privacy-requests/{id}/close   { "status": "done" }

Privacy requests are filed with the organization's main trust center.

security.txt

trust.security writes your organization's RFC 9116 file and the "Report a vulnerability" line:

{ "legal": { "trust": { "security": {
  "contact": "mailto:security@acme.com",
  "policy": "/legal/acme/vulnerability-disclosure",
  "encryption": "https://acme.com/pgp.txt",
  "acknowledgments": "/legal/acme/hall-of-fame",
  "hiring": "/jobs/acme/careers",
  "preferredLanguages": "en, de" } } } }

It is served at GET /public/orgs/{orgId}/trust/security.txt, and the Expires date is renewed each time the file is read. Without a contact there is no file (404), because the RFC requires one. The /.well-known/security.txt of an address we host is still Forumulate's own platform file. If you want researchers to reach yours, link the file from your security page.

More than one trust center

The org's main register is its first public Legal space, at /legal/{org}. Any other Legal space is a trust center of its own, at /legal/{org}/s/{space}. It shows that space's documents, its theme, its intro and its bands. Access requests made there name the space (spaceId on the request), so a grant opens that library's document and uses that space's linkDays.

A private Legal space at that address is a members-only trust center. It is opened with the space's share link (?share=…) and kept out of search.

Security questionnaires

The studio's Security questionnaires panel drafts answers to a questionnaire from what you have published: the trust bands, the access library, the hosting locations and your live legal documents. Paste the questions, twenty at a time. Each answer lists the sections it drew on, and a question your material does not cover says "Not covered by our published material." Export the answers as CSV. They are drafts for a person to check.

POST /orgs/{orgId}/trust/questionnaire  { "questions": ["Do you encrypt data at rest?", "…"] }

Policies from the generator

The privacy, cookie and terms documents a trust center lists can be drafted with the policy generator. They are a template, not legal advice: review them with counsel. Forumulate maintains the clauses, reviews them every quarter, and tells you (in the app and by email) with a diff when a clause you published changes, so you can update your policy in one click. See Legal spaces.

Studio controls

In the Legal space's studio:

  • Design: every theme.legal.trust key, with link fields checked as you type and logo fields that upload into the space's library.

  • Access requests: who asked for what, NDA acceptance time, expiry, views; approve or deny.

  • Privacy requests: the requests by deadline; close as done or declined.

  • Security questionnaires: the drafting panel above.

What you need to set up

Feature

What it needs

Until then

Access links, privacy-request alerts

Your organization's mail settings, and a support address (Settings) for the privacy alert.

The request is still recorded and queued in the studio. Without a support address, no alert mail is sent.

The status band

Exactly one public Status space in the organization, and trust.status set.

The band draws nothing.

Security questionnaires

Your own AI provider, connected in Settings (PUT /orgs/{orgId}/ai/provider). AI here is bring-your-own-key, so there is no platform key.

The call answers 409 ai.unavailable with a pointer to where to connect one.

CRM sync (Salesforce, HubSpot)

A webhook receiver on your side for legal.access_requested and legal.privacy_requested. There is no built-in CRM connector.

Requests live in the studio queues only.

Live control monitoring (Vanta, Drata)

There is no built-in connector. Write trust.controls from your own job with a personal access token and the theme PATCH above.

The catalogue shows what you last wrote.

E-signed NDA (DocuSign, Dropbox Sign)

Not built in.

The click-through NDA records the exact text and the time it was accepted.

CAPTCHA on the public forms

Your organization's CAPTCHA settings.

The forms rely on the honeypot field and the per-client rate limits.

In the API

Every operation below is also reachable from the other surfaces without a dedicated command. forumulate api <Operation> calls it from the CLI, the JavaScript SDK has a typed method for each one (the last column names it; the Python and Go clients are generated from the same spec), and an agent reaches the organization-scoped ones through the MCP call_api tool. Where a CLI command or MCP tool exists too, the last column names it. Operation names link to the API reference.

Operation

Request

What it does

Shortcuts

LegalTrust_cookieScan

POST /orgs/{orgId}/trust/cookie-scan

Scan a page for the cookies it and its third-party scripts set

client.legal.trust.cookieScan()

LegalTrust_answerQuestionnaire

POST /orgs/{orgId}/trust/questionnaire

Draft answers to security questionnaire questions from the published trust centre and legal documents

client.legal.trust.answerQuestionnaire()

LegalTrust_commentQueue

GET /orgs/{orgId}/trust/comments

Comments on upcoming legal editions, newest first, for moderation

client.legal.trust.commentQueue()

LegalTrust_moderate

POST /orgs/{orgId}/trust/comments/{id}/moderate

Publish or reject a comment on an upcoming edition, with an optional answer

client.legal.trust.moderate()

LegalTrust_privacyList

GET /orgs/{orgId}/trust/privacy-requests

Privacy requests filed from the legal register, newest first

client.legal.trust.privacyList()

LegalTrust_privacyClose

POST /orgs/{orgId}/trust/privacy-requests/{id}/close

Close a privacy request as done or declined

client.legal.trust.privacyClose()

LegalTrust_list

GET /orgs/{orgId}/trust/access-requests

The trust centre's access requests, newest first, with view counts

client.legal.trust.list()

LegalTrust_decide

POST /orgs/{orgId}/trust/access-requests/{id}/decision

Approve (mails a time-limited link) or deny an access request

client.legal.trust.decide()

Operation

Request

What it does

Shortcuts

PublicLegalTrust_editionComments

GET /public/orgs/{orgId}/trust/editions/{kind}/next/comments

Published comments on a legal document's upcoming edition

client.legal.publicTrust.editionComments()

PublicLegalTrust_comment

POST /public/orgs/{orgId}/trust/editions/{kind}/next/comments

Comment on a legal document's upcoming edition (held for review)

client.legal.publicTrust.comment()

PublicLegalTrust_privacyRequest

POST /public/orgs/{orgId}/trust/privacy-requests

File a privacy request (access, delete, correct, opt-out) with an organization

client.legal.publicTrust.privacyRequest()

PublicLegalTrust_request

POST /public/orgs/{orgId}/trust/access-requests

Request a gated trust-centre document (NDA or approval)

client.legal.publicTrust.request()

PublicLegalTrust_open

GET /public/orgs/{orgId}/trust/access/{token}

Resolve a trust-centre access link to its document

client.legal.publicTrust.open()

PublicLegalTrust_watermarked

GET /public/orgs/{orgId}/trust/access/{token}/document.pdf

Download a gated trust document as a PDF watermarked for its requester

client.legal.publicTrust.watermarked()

PublicLegalTrust_securityTxt

GET /public/orgs/{orgId}/trust/security.txt

An organization's security.txt (RFC 9116)

client.legal.publicTrust.securityTxt()

The Forumulate teamUpdated