Update the component install

Embed
Preview of the card
<a href="https://forumulate.com/reference/forumulate-api-themecomponent-update"><img src="https://forumulate.com/reference/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/8042f004-e3d9-445f-b7a4-b6c1f86836e6/pages/3b70c0ea-4f9e-4102-a9c0-91f2c4d9b493/social-card.svg?v=3e7ae33eec8b" alt="Update the component install" width="600" height="315"></a>
PATCHhttps://forumulate.com/api/orgs/{orgId}/component-installs/{id}

Edits the component, its organization-wide settings (validated by key against its own declarations), or turns it off everywhere without uninstalling it.

Requires token scope: write (the coarse method gate) for Atlas key (ak_), Personal Access Token (cft_) or OAuth (cfo_) auth — in addition to any catalog scope (GET /pats/scopes) the route’s capability needs. Session/cookie auth is governed by RBAC capabilities instead.

Parameters
orgIdstringpathrequired
idstringpathrequired
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:
Idempotency-Keystringheader
Makes this write safe to retry. Optional — send any unique string (a UUID is ideal) and the first request runs while its response is remembered under that key for 24 hours; an identical retry replays that same status and body instead of acting twice, so a timeout or a 5xx from the edge can be retried without creating a second row. A retry sent while the first request is still in flight is refused with 409. The key is scoped to the method and path, so the same key on a different endpoint is a different request. Error responses of 5xx are never cached — those retries re-run. A key is bound to the BODY it was first used with: reusing it with a different body is a 409 idempotency.key_reused, not a replay, because replaying would tell you a write landed that never ran. Generate one key per request, never per process or per session.
Request body application/json
componentobject
Show child parameters
formatstringrequired
formatVersionnumberrequired
metaobjectrequired
Show child parameters
namestringrequired
slugstringrequired
descriptionstring
authorobjectrequired
versionstringrequired
licensestring
homepagestring
tagsstring[]
spaceTypesstring[]
previewImagesobject[]
cssstring
outletsobject
settingsobject
stringsobject
settingsobject
enabledboolean
{
  "component": {
    "format": "string",
    "formatVersion": 0,
    "meta": {
      "name": "string",
      "slug": "string",
      "description": "string",
      "author": {
        "name": "string",
        "url": "string"
      },
      "version": "string",
      "license": "string",
      "homepage": "string",
      "tags": [
        "string"
      ],
      "spaceTypes": [
        "DOCS"
      ],
      "previewImages": [
        {
          "url": null,
          "alt": null,
          "scheme": null
        }
      ]
    },
    "css": "string",
    "outlets": {},
    "settings": {},
    "strings": {}
  },
  "settings": {},
  "enabled": true
}
Code samples
cURL
curl -X PATCH "https://forumulate.com/api/orgs/{orgId}/component-installs/{id}" \
  -H "forumulate-version: <value>" \
  -H "Idempotency-Key: <value>" \
  -H "Content-Type: application/json" \
  -d '{"component":{"format":"string","formatVersion":0,"meta":{"name":"string","slug":"string","description":"string","author":{"name":"string","url":"string"},"version":"string","license":"string","homepage":"string","tags":["string"],"spaceTypes":["DOCS"],"previewImages":[{"url":null,"alt":null,"scheme":null}]},"css":"string","outlets":{},"settings":{},"strings":{}},"settings":{},"enabled":true}'
TypeScript
const res = await fetch('https://forumulate.com/api/orgs/{orgId}/component-installs/{id}', {
  method: 'PATCH',
  headers: {
    'forumulate-version': '<value>',
    'Idempotency-Key': '<value>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"component":{"format":"string","formatVersion":0,"meta":{"name":"string","slug":"string","description":"string","author":{"name":"string","url":"string"},"version":"string","license":"string","homepage":"string","tags":["string"],"spaceTypes":["DOCS"],"previewImages":[{"url":null,"alt":null,"scheme":null}]},"css":"string","outlets":{},"settings":{},"strings":{}},"settings":{},"enabled":true}),
});
const data = await res.json();
Python
import requests

res = requests.request(
    "PATCH",
    "https://forumulate.com/api/orgs/{orgId}/component-installs/{id}",
    headers={
    "forumulate-version": "<value>",
    "Idempotency-Key": "<value>",
    "Content-Type": "application/json",
    },
    json={"component": {"format": "string", "formatVersion": 0, "meta": {"name": "string", "slug": "string", "description": "string", "author": {"name": "string", "url": "string"}, "version": "string", "license": "string", "homepage": "string", "tags": ["string"], "spaceTypes": ["DOCS"], "previewImages": [{"url": None, "alt": None, "scheme": None}]}, "css": "string", "outlets": {}, "settings": {}, "strings": {}}, "settings": {}, "enabled": True},
)
data = res.json()
Go
package main

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

func main() {
	req, _ := http.NewRequest("PATCH", "https://forumulate.com/api/orgs/{orgId}/component-installs/{id}", strings.NewReader(`{"component":{"format":"string","formatVersion":0,"meta":{"name":"string","slug":"string","description":"string","author":{"name":"string","url":"string"},"version":"string","license":"string","homepage":"string","tags":["string"],"spaceTypes":["DOCS"],"previewImages":[{"url":null,"alt":null,"scheme":null}]},"css":"string","outlets":{},"settings":{},"strings":{}},"settings":{},"enabled":true}`))
	req.Header.Set("forumulate-version", "<value>")
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("Content-Type", "application/json")
	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/orgs/{orgId}/component-installs/{id}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['forumulate-version: <value>', 'Idempotency-Key: <value>', 'Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"component":{"format":"string","formatVersion":0,"meta":{"name":"string","slug":"string","description":"string","author":{"name":"string","url":"string"},"version":"string","license":"string","homepage":"string","tags":["string"],"spaceTypes":["DOCS"],"previewImages":[{"url":null,"alt":null,"scheme":null}]},"css":"string","outlets":{},"settings":{},"strings":{}},"settings":{},"enabled":true}');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://forumulate.com/api/orgs/{orgId}/component-installs/{id}')
req = Net::HTTP::Patch.new(uri)
req['forumulate-version'] = '<value>'
req['Idempotency-Key'] = '<value>'
req['Content-Type'] = 'application/json'
req.body = '{"component":{"format":"string","formatVersion":0,"meta":{"name":"string","slug":"string","description":"string","author":{"name":"string","url":"string"},"version":"string","license":"string","homepage":"string","tags":["string"],"spaceTypes":["DOCS"],"previewImages":[{"url":null,"alt":null,"scheme":null}]},"css":"string","outlets":{},"settings":{},"strings":{}},"settings":{},"enabled":true}'
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/orgs/{orgId}/component-installs/{id}"))
    .header("forumulate-version", "<value>")
    .header("Idempotency-Key", "<value>")
    .header("Content-Type", "application/json")
    .method("PATCH", BodyPublishers.ofString("{\"component\":{\"format\":\"string\",\"formatVersion\":0,\"meta\":{\"name\":\"string\",\"slug\":\"string\",\"description\":\"string\",\"author\":{\"name\":\"string\",\"url\":\"string\"},\"version\":\"string\",\"license\":\"string\",\"homepage\":\"string\",\"tags\":[\"string\"],\"spaceTypes\":[\"DOCS\"],\"previewImages\":[{\"url\":null,\"alt\":null,\"scheme\":null}]},\"css\":\"string\",\"outlets\":{},\"settings\":{},\"strings\":{}},\"settings\":{},\"enabled\":true}"))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 Success.
Example
{
  "install": {
    "author": {
      "name": "string",
      "url": "string"
    },
    "component": {
      "css": "string",
      "format": "forumulate.theme-component",
      "formatVersion": 1,
      "meta": {
        "author": {
          "name": null,
          "url": null
        },
        "description": "string",
        "homepage": "string",
        "license": "string",
        "name": "string",
        "previewImages": [
          null
        ],
        "slug": "string",
        "spaceTypes": [
          null
        ],
        "tags": [
          null
        ],
        "version": "string"
      },
      "outlets": {
        "above-main": {},
        "below-main": {},
        "blog-index-above-list": {},
        "blog-post-after": {},
        "blog-post-before": {},
        "blog-post-end": {},
        "careers-above-list": {},
        "category-header": {},
        "changelog-above-list": {},
        "courses-above-list": {},
        "courses-certificate-footer": {},
        "courses-landing-hero-after": {},
        "courses-lesson-above-body": {},
        "courses-lesson-after-body": {},
        "docs-page-footer": {},
        "docs-page-header": {},
        "docs-sidebar-end": {},
        "docs-sidebar-start": {},
        "events-above-list": {},
        "events-card-footer": {},
        "events-page-above-body": {},
        "events-page-after-body": {},
        "events-page-aside": {},
        "faq-above-list": {},
        "footer-after": {},
        "footer-before": {},
        "forum-categories-above": {},
        "forum-index-above-list": {},
        "forum-index-below-list": {},
        "forum-post-after-body": {},
        "forum-post-author-after": {},
        "forum-sidebar-bottom": {},
        "forum-sidebar-top": {},
        "forum-topic-above-title": {},
        "forum-topic-below-first-post": {},
        "forum-topic-below-title": {},
        "forum-topic-bottom": {},
        "forum-topic-row-after-title": {},
        "front-page-bottom": {},
        "front-page-top": {},
        "header-after": {},
        "header-before": {},
        "roadmap-above-board": {},
        "status-above-board": {},
        "user-card": {}
      },
      "settings": {},
      "strings": {}
    },
    "createdAt": "string",
    "description": "string",
    "enabled": true,
    "id": "string",
    "name": "string",
    "placements": [
      {
        "draftOnly": true,
        "id": "string",
        "kind": "site",
        "name": "string"
      }
    ],
    "scripts": [
      "string"
    ],
    "settings": {},
    "slug": "string",
    "source": "authored",
    "sourceRef": "string",
    "updatedAt": "string",
    "version": "string"
  },
  "warnings": [
    "tags: \"Launch Day\" is stored as \"launch-day\""
  ]
}
Schema
installobjectrequired
Show child parameters
authorobjectrequired
Show child parameters
namestringrequired
urlstring
componentobjectrequired
Show child parameters
cssstring
formatstringrequired
forumulate.theme-component
formatVersionnumberrequired
1
metaobjectrequired
outletsobject
settingsobject
stringsobject
createdAtstringrequired
descriptionstringrequired
enabledbooleanrequired
idstringrequired
namestringrequired
placementsComponentPlacement[]required
Show child parameters
draftOnlybooleanrequired
idstringrequired
kindstringrequired
site | space
namestringrequired
scriptsstring[]required
settingsobjectrequired
slugstringrequired
sourcestringrequired
authored | first_party | imported | marketplace | theme
sourceRefstringrequired
updatedAtstringrequired
versionstringrequired
warningsstring[]
Values we ACCEPTED and then rewrote, one sentence each — a slugified tag, a normalised colour, a clamped range, a slug that was taken. Absent when nothing was rewritten, never []. The same sentences are on the X-Field-Warnings response header. If this is present, something you sent is not what is stored; read the resource back rather than assuming your own value.
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.
401 No credential, or one that is expired or revoked (auth.required). Send a Bearer token or the session cookie.
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.
403 Authenticated, and not allowed — always rbac.forbidden, whether what is missing is the capability, the token scope, or a resource the token is pinned away from. The message names the capability and, for a scope refusal, the scopes that would grant it. A refusal because of the PLAN is a 402 with quota.exceeded, not this.
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.
422 The body was understood and a value is unacceptable (validation.failed). error.details names the field paths.
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