Get the legal

Embed
Preview of the card
<a href="https://forumulate.com/reference/forumulate-api-legalpublic-get"><img src="https://forumulate.com/reference/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/8042f004-e3d9-445f-b7a4-b6c1f86836e6/pages/4ee9baa9-4041-4b4f-999c-02a697dd336b/social-card.svg?v=3e7ae33eec8b" alt="Get the legal" width="600" height="315"></a>
GEThttps://forumulate.com/api/public/orgs/{orgId}/legal/{kind}

The current published text of one document by its role — terms, privacy, cookies. Fetch by role rather than by id, so the footer keeps working after a new edition replaces the old one. ?locale=<code> serves its translation twin in one of the space's declared languages; locale names the language served and locales lists the declared ones.

Parameters
orgIdstringpathrequired
kindstringpathrequired
localestringquery
forumulate-versionstringheader
API version negotiation. Send forumulate-version: 2026-12-01 on every request from a new integration; it is optional only so that integrations written before versioning keep working. Each version includes everything before it:
Code samples
cURL
curl -X GET "https://forumulate.com/api/public/orgs/{orgId}/legal/{kind}?locale=" \
  -H "forumulate-version: <value>"
TypeScript
const res = await fetch('https://forumulate.com/api/public/orgs/{orgId}/legal/{kind}?locale=', {
  method: 'GET',
  headers: {
    'forumulate-version': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://forumulate.com/api/public/orgs/{orgId}/legal/{kind}?locale=",
    headers={
    "forumulate-version": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://forumulate.com/api/public/orgs/{orgId}/legal/{kind}?locale=", nil)
	req.Header.Set("forumulate-version", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://forumulate.com/api/public/orgs/{orgId}/legal/{kind}?locale=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['forumulate-version: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://forumulate.com/api/public/orgs/{orgId}/legal/{kind}?locale=')
req = Net::HTTP::Get.new(uri)
req['forumulate-version'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://forumulate.com/api/public/orgs/{orgId}/legal/{kind}?locale="))
    .header("forumulate-version", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 Success.
Example
{
  "document": {
    "body": "string",
    "content": {},
    "customization": {
      "customCss": "string",
      "jsonLd": "string",
      "ogDescription": "string",
      "ogTitle": "string",
      "shareImageUrl": "string",
      "theme": {
        "accentColor": "string",
        "bodyFontFamily": "string",
        "changelog": {
          "archive": null,
          "breakingBadge": null,
          "channelBadge": null,
          "closes": null,
          "columnWidth": null,
          "dateFormat": null,
          "datePlacement": null,
          "dateTone": null,
          "entry": null,
          "entryGap": null,
          "facts": null,
          "filters": null,
          "group": null,
          "gutter": null,
          "gutterWidth": null,
          "header": null,
          "indexWidth": null,
          "languages": null,
          "look": null,
          "prose": null,
          "rail": null,
          "release": null,
          "sections": null,
          "showTags": null,
          "stickyDate": null,
          "tagInk": null,
          "tagOverflow": null,
          "tagStyle": null,
          "typeBadge": null,
          "upgradeNotesFirst": null,
          "versionBadge": null,
          "widget": null
        },
        "colorScheme": "dark",
        "components": {
          "apiRef": null,
          "button": null,
          "buttonDark": null,
          "byline": null,
          "caption": null,
          "card": null,
          "code": null,
          "codeDark": null,
          "expandable": null,
          "focus": null,
          "hint": null,
          "image": null,
          "input": null,
          "inputDark": null,
          "kbd": null,
          "link": null,
          "list": null,
          "meta": null,
          "popover": null,
          "preview": null,
          "quote": null,
          "radius": null,
          "scrollbar": null,
          "select": null,
          "selection": null,
          "shadow": null,
          "skeleton": null,
          "spacing": null,
          "stepper": null,
          "syntax": null,
          "syntaxDark": null,
          "syntaxTheme": null,
          "table": null,
          "tabs": null
        },
        "contentWidth": "full",
        "customFontFamily": "string",
        "font": "mono",
        "headingFontFamily": "string",
        "layout": {
          "background": null,
          "canvas": null,
          "floatRoom": null,
          "frame": null,
          "guides": null,
          "gutter": null,
          "heroDecor": null,
          "indexHeader": null,
          "measure": null,
          "widths": null
        },
        "monoFontFamily": "string",
        "motion": {
          "ambient": null,
          "easing": null,
          "enabled": null,
          "header": null,
          "hover": null,
          "keyframes": null,
          "pageCrossfade": null,
          "pageTransition": null,
          "preset": null,
          "respectReducedMotion": null,
          "reveal": null,
          "scroll": null,
          "speed": null,
          "targets": null
        },
        "palette": {
          "background": null,
          "danger": null,
          "footer_background": null,
          "footer_primary": null,
          "header_background": null,
          "header_primary": null,
          "heading": null,
          "highlight": null,
          "info": null,
          "ink": null,
          "line": null,
          "love": null,
          "muted": null,
          "paper": null,
          "primary": null,
          "quaternary": null,
          "secondary": null,
          "success": null,
          "surface": null,
          "tertiary": null,
          "tint": null,
          "warning": null
        },
        "paletteDark": {
          "background": null,
          "danger": null,
          "footer_background": null,
          "footer_primary": null,
          "header_background": null,
          "header_primary": null,
          "heading": null,
          "highlight": null,
          "info": null,
          "ink": null,
          "line": null,
          "love": null,
          "muted": null,
          "paper": null,
          "primary": null,
          "quaternary": null,
          "secondary": null,
          "success": null,
          "surface": null,
          "tertiary": null,
          "tint": null,
          "warning": null
        },
        "post": {},
        "primaryColor": "string",
        "typography": {
          "baseSize": null,
          "bodyWrap": null,
          "features": null,
          "fluid": null,
          "headingTransform": null,
          "headingWrap": null,
          "levels": null,
          "numerals": null,
          "opticalSizing": null,
          "rhythm": null,
          "scale": null,
          "ui": null,
          "variation": null
        }
      },
      "twitterCard": "summary"
    },
    "description": "string",
    "fields": {},
    "group": {
      "description": null,
      "icon": null,
      "id": "string",
      "name": "string",
      "order": "string",
      "slug": "string",
      "translations": {}
    },
    "kind": "string",
    "onThisPage": "always",
    "pageId": "string",
    "required": true,
    "seoDescription": "string",
    "spaceId": "string",
    "title": "string",
    "upcoming": {
      "changeNote": null,
      "effectiveAt": "string",
      "version": 0
    },
    "updatedAt": "string",
    "version": 0
  },
  "locale": "string",
  "locales": [
    {
      "available": true,
      "code": "string",
      "isDefault": true,
      "label": "string"
    }
  ]
}
Schema
documentobjectrequired
Show child parameters
bodystringrequired
contentrequired
customizationobjectrequired
Show child parameters
customCssstring
jsonLdstring
ogDescriptionstring
ogTitlestring
shareImageUrlstring
themeobject
twitterCardstring
summary | summary_large_image
descriptionstringrequired
fieldsobjectrequired
groupPublicLegalGrouprequired
Show child parameters
descriptionstringrequired
iconstringrequired
idstringrequired
namestringrequired
orderstringrequired
slugstringrequired
translationsobject
kindstringrequired
onThisPagestringrequired
always | auto | never
pageIdstringrequired
requiredbooleanrequired
seoDescriptionstringrequired
spaceIdstringrequired
titlestringrequired
upcomingobjectrequired
Show child parameters
changeNotestringrequired
effectiveAtstringrequired
versionnumberrequired
updatedAtstringrequired
versionnumberrequired
localestringrequired
localesReleaseLocaleLink[]required
Show child parameters
availablebooleanrequired
codestringrequired
isDefaultbooleanrequired
labelstringrequired
400 The request could not be understood — a malformed header, path or query value (request.malformed). A value that was understood but is not acceptable is a 422 validation.failed.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
Stable, machine-readable error code, e.g. rbac.forbidden.
messagestringrequired
Human-readable explanation.
detailsobject
Field-level validation problems, keyed by field path (422 only).
docsstring
Where the vocabulary or format this error is about is published — an absolute URL, or an API route such as GET /space-types/{type}/presets. Present on errors over a controlled list, so the answer to "what am I allowed to send?" is in the error itself.
reasonstring
Why a credential was refused, as one stable word, where one status has several causes — e.g. an external_jwt redeem answers iat_too_old, iat_in_future, bad_signature, bad_issuer, bad_audience, expired and more. Branch on this, not on message.
slugsstring[]
The exact slugs that collided, on a slug-conflict 409 — space.slug_taken, page.slug_taken, collection.slug_taken, site.slug_taken or badge.slug_taken.
conflictobject
On a 409 from a content entry field write (PATCH …/entries/{entryId}/fields) whose If-Match was stale.
Show child parameters
etagstringrequired
The entry's current fields etag.
opsarrayrequired
The field operations since your If-Match that touch a path your own operations touch. Empty: none did — retry the batch unchanged under etag. null: the history no longer reaches your tag — re-read the entry first.
requestIdstring
The id of this request — the same value as the x-request-id and x-forumulate-request-id response headers. Quote it in a bug report: it is the only thing that finds your exact request in our logs. It is in the body because that is the part that survives — an SDK that throws the parsed body, a serverless log that keeps the body and drops the headers, a ticket with the JSON pasted in.
404 No such thing — one of the ids in the path does not resolve, or resolves to something this caller may not see (*.not_found).
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
Stable, machine-readable error code, e.g. rbac.forbidden.
messagestringrequired
Human-readable explanation.
detailsobject
Field-level validation problems, keyed by field path (422 only).
docsstring
Where the vocabulary or format this error is about is published — an absolute URL, or an API route such as GET /space-types/{type}/presets. Present on errors over a controlled list, so the answer to "what am I allowed to send?" is in the error itself.
reasonstring
Why a credential was refused, as one stable word, where one status has several causes — e.g. an external_jwt redeem answers iat_too_old, iat_in_future, bad_signature, bad_issuer, bad_audience, expired and more. Branch on this, not on message.
slugsstring[]
The exact slugs that collided, on a slug-conflict 409 — space.slug_taken, page.slug_taken, collection.slug_taken, site.slug_taken or badge.slug_taken.
conflictobject
On a 409 from a content entry field write (PATCH …/entries/{entryId}/fields) whose If-Match was stale.
Show child parameters
etagstringrequired
The entry's current fields etag.
opsarrayrequired
The field operations since your If-Match that touch a path your own operations touch. Empty: none did — retry the batch unchanged under etag. null: the history no longer reaches your tag — re-read the entry first.
requestIdstring
The id of this request — the same value as the x-request-id and x-forumulate-request-id response headers. Quote it in a bug report: it is the only thing that finds your exact request in our logs. It is in the body because that is the part that survives — an SDK that throws the parsed body, a serverless log that keeps the body and drops the headers, a ticket with the JSON pasted in.
429 Rate limited — see the RateLimit-* headers.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
Stable, machine-readable error code, e.g. rbac.forbidden.
messagestringrequired
Human-readable explanation.
detailsobject
Field-level validation problems, keyed by field path (422 only).
docsstring
Where the vocabulary or format this error is about is published — an absolute URL, or an API route such as GET /space-types/{type}/presets. Present on errors over a controlled list, so the answer to "what am I allowed to send?" is in the error itself.
reasonstring
Why a credential was refused, as one stable word, where one status has several causes — e.g. an external_jwt redeem answers iat_too_old, iat_in_future, bad_signature, bad_issuer, bad_audience, expired and more. Branch on this, not on message.
slugsstring[]
The exact slugs that collided, on a slug-conflict 409 — space.slug_taken, page.slug_taken, collection.slug_taken, site.slug_taken or badge.slug_taken.
conflictobject
On a 409 from a content entry field write (PATCH …/entries/{entryId}/fields) whose If-Match was stale.
Show child parameters
etagstringrequired
The entry's current fields etag.
opsarrayrequired
The field operations since your If-Match that touch a path your own operations touch. Empty: none did — retry the batch unchanged under etag. null: the history no longer reaches your tag — re-read the entry first.
requestIdstring
The id of this request — the same value as the x-request-id and x-forumulate-request-id response headers. Quote it in a bug report: it is the only thing that finds your exact request in our logs. It is in the body because that is the part that survives — an SDK that throws the parsed body, a serverless log that keeps the body and drops the headers, a ticket with the JSON pasted in.
default Error — the stable { error: { code, message } } envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
Stable, machine-readable error code, e.g. rbac.forbidden.
messagestringrequired
Human-readable explanation.
detailsobject
Field-level validation problems, keyed by field path (422 only).
docsstring
Where the vocabulary or format this error is about is published — an absolute URL, or an API route such as GET /space-types/{type}/presets. Present on errors over a controlled list, so the answer to "what am I allowed to send?" is in the error itself.
reasonstring
Why a credential was refused, as one stable word, where one status has several causes — e.g. an external_jwt redeem answers iat_too_old, iat_in_future, bad_signature, bad_issuer, bad_audience, expired and more. Branch on this, not on message.
slugsstring[]
The exact slugs that collided, on a slug-conflict 409 — space.slug_taken, page.slug_taken, collection.slug_taken, site.slug_taken or badge.slug_taken.
conflictobject
On a 409 from a content entry field write (PATCH …/entries/{entryId}/fields) whose If-Match was stale.
Show child parameters
etagstringrequired
The entry's current fields etag.
opsarrayrequired
The field operations since your If-Match that touch a path your own operations touch. Empty: none did — retry the batch unchanged under etag. null: the history no longer reaches your tag — re-read the entry first.
requestIdstring
The id of this request — the same value as the x-request-id and x-forumulate-request-id response headers. Quote it in a bug report: it is the only thing that finds your exact request in our logs. It is in the body because that is the part that survives — an SDK that throws the parsed body, a serverless log that keeps the body and drops the headers, a ticket with the JSON pasted in.
The Forumulate teamUpdated