API conventions
The things that are true across every endpoint, stated once. Several of these correct earlier pages that made a blanket claim where the truth is per-operation.
The base URL
https://forumulate.com/apiThe OpenAPI document is at https://forumulate.com/api/openapi.json and needs no authentication.
(The spec's own info.description currently says "Download this spec at /openapi.json". That resolves against the host root and redirects. Use the /api/ form.)
curl -sS -A 'my-app/1.0' https://forumulate.com/api/openapi.json -o openapi.jsonIt is a large document — 976 paths and 1,225 operations at the time of writing. Any figure you read in the form "700+ paths" is out of date; count it yourself:
python3 -c "import json;d=json.load(open('openapi.json'));print(len(d['paths']))"User-Agent
Set one. Any identifying string.
Path | Behaviour |
|---|---|
| Accepts any User-Agent, including library defaults. |
| Bot-protected. Some library defaults — |
Two earlier pages contradicted each other on this: one said there is no restriction at all, the other said every default agent is challenged. Neither is right. The table above is.
If you get an HTML body where you expected JSON, that is the WAF and not us.
Authentication
Authorization: Bearer ak_…Three token prefixes, all sent the same way: ak_ (an Atlas-minted key), cft_ (a personal access token) and cfo_ (an OAuth access token). Browser calls use the session cookie instead.
Every operation in the reference states its coarse scope requirement — "Requires token scope: write". That is only half the story; a token needs a catalog scope as well. See API tokens, scopes and capabilities.
Public endpoints need no token
Everything under /public/ is anonymous. If a reference page for a /public/ or /auth/ route shows "Requires authentication" and a Bearer example, that page is stale — the current spec marks 181 of 182 /public/ operations as unsecured, and 240 operations overall.
The one genuine exception at the time of writing is GET /public/orgs/{orgId}/spaces/{spaceId}/forum/embed/resolve, which the spec still marks as secured. It should not be, and that is a bug on our side rather than a requirement on yours.
Organizations
/orgs/{orgId}/… accepts either the organization's uuid or the name in its slug:
GET https://forumulate.com/api/orgs/acme/spaces
GET https://forumulate.com/api/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spacesBoth forms address the same organization. A name that is not yours is a 404, never a 500 and never a 403 — we do not confirm that an organization exists to somebody who is not in it.
A route that needs an organization and cannot work out which one answers tenancy.no_org_context. In practice that means one of two things: the path has no {orgId} and your token is scoped to no organization, or you are calling an organization-level route with a session that belongs to several and named none. Put the organization in the path.
{spaceId} is the same: a uuid, or the space's slug within that organization. It is not decoration on a nested route — a page id further down the path that belongs to a different space is a 404, not a cross-space read.
Slugs
Every addressable thing has a slug, and a slug is unique within its scope: a page's within its space (per version and locale), a space's within its organization, a site's within its organization.
Slugs are normalised on the way in, not rejected. Launch Day is stored as launch-day: lower-cased, every run of non-alphanumeric characters folded to a single -, leading and trailing - trimmed, cut to 80 characters. Unicode letters and digits survive — Überblick is überblick, not berblick.
When we rewrite what you sent, we say so. The response carries an X-Field-Warnings header, and the write doors that answer a body also carry warnings[]:
X-Field-Warnings: tags: "Launch Day" is stored as "launch-day"If you get a 2xx and that header is present, the stored value is not the value you sent. Read it the first time a value "does not save".
A taken slug: onSlugTaken
Both page doors — POST …/collections/{collectionId}/pages and PATCH …/pages/{pageId} — take onSlugTaken, with the same default on each:
Value | |
|---|---|
| Land at the next free name — |
| Refuse with |
The default depends on your version. Leave onSlugTaken out and you get suffix if you state Forumulate-Version: 2026-09-01 or 2026-11-01, or no version at all; from 2026-12-01 you get fail — the safe default, and the one blog posts have always had. A page landing at a URL nobody wrote is worse than a 409 you can act on. Send the value explicitly and the version does not matter.
The two doors used to disagree, create suffixing and update failing, which cost a migration its writes. They now behave identically; fail is there for a pipeline that would rather hear about a collision than work around one.
On a suffix rename, read slug off the response — do not assume the slug you sent:
{
"ok": true,
"slug": "install-2",
"slugChanged": { "asked": "install", "used": "install-2" },
"warnings": ["slug: the slug asked for was taken; read `slug` on the response for the one used"],
}The create door answers the same two keys beside its page/data.
The OpenAPI doors answer page.slug_taken too — POST …/docs/openapi/import with onExisting: "replace", …/openapi/generate and a spec resync — when a generated slug is held by a page in another collection that the spec does not own. The envelope's slugs lists every such page.
A reserved slug is a different refusal: space.slug_reserved and badge.slug_reserved (409) mean the name is one we route on ourselves — api and docs are reserved host names, and a handful of path segments are reserved under a site. Pick another; a suffix will not help.
The other taken-identifier codes follow the same rule — space.slug_taken, collection.slug_taken, site.slug_taken, badge.slug_taken, version.key_taken, name.taken — all 409, all over the identifier rather than the request.
A markdown body (a page body, a section, /docs/import, a sync) also reports what its directive door did not keep — an unknown :::directive, an unknown attribute, an out-of-range ::column{width} — as markdown … lines.
Errors
One shape, everywhere:
{
"error": {
"code": "auth.unauthenticated",
"message": "Authentication required.",
},
}Field | |
|---|---|
| Stable. Branch on this. |
| For a human. May change between releases. |
| Optional. Field-level problems, keyed by path. |
| Optional. A link to the relevant page. |
| Optional. Identifiers the error refers to. |
Common codes: auth.unauthenticated (401), rbac.forbidden (403), not_found (404), validation.failed (422), rate_limited (429).
Bodies are UTF-8
A JSON or form body is read as UTF-8 unless its Content-Type names another charset. Bytes that are not valid UTF-8 — most often Latin-1 text, where ñ is the single byte F1 instead of C3 B1 — are a 400 request.malformed and nothing is written. Nothing is ever stored with the unreadable characters replaced by �.
Unknown body keys
A key we do not recognise is dropped, and the response names what it dropped in an X-Unrecognized-Fields header. The call answers 200.
Check that header the first time a field "does not save". A silently ignored key has cost two customers a day each.
The one surface that refuses instead of dropping is the theme, because a misspelled theme key produces a page that renders and is simply the wrong colour. Those answer 422 with the path named.
The theme routes (PUT/PATCH …/theme, …/theme/draft, …/reader-themes), a site's config and config.theme, and a page's metadata.themePatch all take every documented theme key, including the round-5 keys (for example docs.blocks.prompt.icon, forum.topic.rail[].group, docs.api.titleSize, forum.front.filters.labels). A bad value is a 422 naming the exact path and what it accepts (forum.list.phone.avatarSize: Number must be less than or equal to 48), and an unknown key beside a known one is still a 422 naming it.
Creates: data is the key that is always there
A create answers 201 with the new resource under its collection's own word — page, collection, article, topic — and again under data:
{
"page": { "id": "3f1e0b2c-…", "title": "Installing", "slug": "installing" },
"data": { "id": "3f1e0b2c-…", "title": "Installing", "slug": "installing" },
}data is a mirror, not a new shape. It is the same object, under a second key. Nothing was renamed and nothing was removed, so a client reading response.page is unaffected — and a client wrapping ninety endpoints can read response.data and stop writing a parser per route.
Read data ?? <the named key>. That one line works on every create in the API, including the ones that have no data (below), and it keeps working if a route grows one.
The 201s that carry no data
Most operations that answer 201 declare data. The rest do not, because a 201 is not a promise that something addressable was made. Each of them says which kind of answer it is, in its own 201 description, so you never have to guess. (How many of each there are is counted off the document and stated in the spec's own description — GET /api/openapi.json, the info section. It is not repeated here, because a count typed into a page beside a generated document is a count that goes stale the next time an endpoint is added.)
Kind | What you get | Why no |
|---|---|---|
result | An acknowledgement ( | Nothing addressable was created, so there is nothing to mirror and nothing to |
collection | The whole collection you added to — | There is no single created row to point at; find yours in the array |
bare resource | The resource itself, at the top level, with its own | There is no key beside it to put |
A bare resource is the one kind we would change if we could: keying it as { event: … } would break every caller parsing it today, so it waits for a dated version. POST /scim/v2/Users and POST /scim/v2/Groups will never change — RFC 7644 defines the SCIM response as the resource itself, and a data key there would make us non-conformant with the spec your IdP implements.
Two more keys show up on creates and are never the thing that was made: warnings (values we accepted and then rewrote — see A taken slug) and slugChanged. Neither is ever mirrored into data.
Pagination
Paging is version-negotiated, not per-endpoint. State Forumulate-Version: 2026-09-01 (or later) and every collection-shaped GET answers { <rows>, page } — page carrying limit, hasMore, nextCursor and total. Send no version and you get the pre-envelope shape that route has always answered, which for some is a bare array, along with Deprecation and Sunset headers saying so. limit and cursor are accepted either way; sending a cursor opts into the enveloped shape exactly as stating a version does.
This page used to say that only a handful of lists carried page and that the spec's claim to the contrary was wrong. The spec was right and this page was out of date: the envelope is now declared on every list in the published document, and a walk over that document fails the build if one is added without it. The rule replaced the tally on purpose — a tally of endpoints is wrong the first time somebody adds one.
The exception is a ranking rather than a collection: the reputation leaderboards, ?q= semantic search, and the search-gap and uncovered-thread reports recompute a score per request, so there is no row a cursor could resume after. They honour limit and say so on the operation.
A route that cannot change shape without breaking a caller answers both shapes and lets you choose, so the unversioned answer differs from route to route: some were a bare array, some had paging keys of their own. The operation's own response schema says which, and it — not either of these paragraphs — is the thing to code against.
Rate limits
Caller | Limit |
|---|---|
Authenticated, free or starter plan | 600 requests / minute |
Authenticated, business plan | 1,800 / minute |
Authenticated, enterprise plan | 6,000 / minute |
Anonymous | 120 / minute, on every plan |
Authenticated limits are keyed per organization; anonymous limits per IP, which is why they do not vary by plan — a per-IP bucket is the wrong place to sell capacity.
Some individual endpoints are tighter — a handful of public ones are 60, 30 or even 5 a minute — and each declares its own budget. Read the headers rather than this table:
RateLimit-Limit: 600
RateLimit-Remaining: 597
RateLimit-Reset: 41
RateLimit-Policy: 600;w=60On a 429, read Retry-After and wait that many seconds. Do not implement a fixed backoff; the header is more accurate than a guess.
Retries
Two statuses are worth retrying and the rest are not.
429 — you were too fast. Wait Retry-After seconds and send the same request again.
503 service_unavailable — something we depend on is failing, including a 502 or 504 from an upstream we called on your behalf (a BYOK model provider, a mail relay, an identity provider). It is retryable and it carries Retry-After when we know how long. Back off exponentially from there, with jitter, and give up after a few attempts rather than holding a request open: the edge cuts a connection at 30 seconds whatever we are doing behind it.
Everything else is yours to fix, not to retry. A 422 will fail identically forever; a 409 means the state is not what you assumed, so re-read and decide; a 404 will not become a 200.
Retry a write with Idempotency-Key. Without one, a retried create that actually succeeded the first time makes a second thing — and a timeout you did not see is the normal way that happens. See Idempotency.
Preconditions
Two resources support optimistic concurrency with If-Match: a page and an item. Their reads send an ETag response header; send it back as If-Match:
# Read, and keep the tag.
curl -sS -D- -A 'my-app/1.0' -H "Authorization: Bearer $TOKEN" \
'https://forumulate.com/api/orgs/acme/spaces/docs/pages/3f1e0b2c-8a44-4c2e-9f1a-2b7d5e6c0a11'
# ETag: "r1-Qm8x…"
# Write, but only if nobody else has.
curl -sS -X PATCH -A 'my-app/1.0' -H "Authorization: Bearer $TOKEN" \
-H 'If-Match: "r1-Qm8x…"' -H 'Content-Type: application/json' \
-d '{"title":"Installing"}' \
'https://forumulate.com/api/orgs/acme/spaces/docs/pages/3f1e0b2c-8a44-4c2e-9f1a-2b7d5e6c0a11'If the resource has moved on, the write is refused with 412 precondition.failed, naming the tag you sent and the one it is at. Re-read and retry. The tag a read gives you works on every write to that resource — its body, its metadata, its slug, its deletion.
The ETag is opaque and changes on ANY change to what the read returns — the body, but also the title, slug, declared locale, metadata or anything else in the representation. It is the right tag for If-None-Match (a 304 means the response you hold is still exactly current) and for If-Match (a write is refused if anything moved). Do not parse it or compare it to contentHash.
contentHash still changes only when the content does. A slug, language or metadata edit leaves it exactly where it was, so it remains the value to compare for drift between what you pushed and what is published. It is also still accepted as If-Match, as it was before the ETag covered the whole representation, and there it guards the content only: a concurrent rename does not refuse it. Send the ETag when a metadata race matters.
Where a write cannot evaluate the header it is refused with 428 rather than ignored. That is deliberate: a caller who sends If-Match and has it dropped believes they have optimistic concurrency and loses a write in the exact case the header exists to catch. The routes that answer 428 are the ones where a single tag could not mean anything — a bulk operation over many pages, or a resource with no content to hash. If-Match: * passes everywhere, since it only asserts the thing exists.
A docs change request and a theme draft have their own named concurrency control (theme_draft.stale, publish with force) rather than an ETag.
Deprecation
A response that is serving a shape with a removal date carries:
Deprecation: @1788220800
Sunset: Wed, 01 Sep 2027 00:00:00 GMT
Link: <https://forumulate.com/api/openapi.json>; rel="service-desc",
<https://forumulate.com/reference/versioning>; rel="deprecation"
forumulate-version: legacyDeprecation is an RFC 9745 structured date — an @ followed by Unix seconds. It is not Deprecation: true; three places in our own docs said it was. @1788220800 is 2026-09-01T00:00:00Z, the day the shape became deprecated. Sunset (RFC 8594) is the day it stops being served.
Which responses carry them
An operation sends them when, and only when, it negotiates its response shape — when it answers one body to a caller who states a Forumulate-Version and a different one to a caller who does not. These are collections that answer { items } to an unversioned caller and { items, page } to a versioned one: /orgs, /pats, /orgs/{orgId}/spaces, the blog, the changelog, the forum, the audit log, …/items and others.
Do not count them from this page and do not keep your own list. Read it off the spec, where it is generated from the same fact the server reads:
an operation that sends them declares
Deprecation,SunsetandLinkunderresponses.<2xx>.headers, with the date in the header's own description;and its
2xxresponse schema is ananyOfof exactly two variants, the withdrawn one markeddeprecated.
Those two always arrive together, on the same operations. A tally written in prose beside a generated set goes stale the first time a route gains or loses a second shape — this page used to carry one that no longer matched the spec, which is how you came to be reading this paragraph.
These headers used to go out on every unversioned response in the API. That was wrong and it has been fixed. Sunset means this resource stops responding, and GET /orgs is not stopping: an unversioned caller and a versioned caller get the identical body from it, today and after the sunset date. If you built anything on seeing Sunset everywhere, it was reading a bug.
What is, and is not, marked deprecated in the spec
These operations are marked deprecated: true at the operation level. They are genuinely going away:
GET /orgs/{orgId}/templatesPOST /hooks/cookiemunch
The shape-negotiating operations are not, and that is deliberate. The route is not deprecated — there is no replacement for GET /orgs and you will be calling it forever. What is deprecated is the response body you get by stating no version, so that is what carries the mark: the non-enveloped half of the operation's response anyOf has deprecated: true and a description naming 2027-09-01. OpenAPI 3.1 allows deprecated on a Schema Object, which is exactly the granularity this needs.
Both halves are spelled out, on every one of these operations: the withdrawn one lists the collection key alone, and the one you should move to lists page as required. If you have been reading a single schema with an optional page and wondering which kind of optional it was — negotiated, or simply sometimes absent — that was the gap, and it is closed.
So when you are looking at one of these operations and deciding which half of its anyOf to write a parser against: the struck-through one is the one with the date on it. Write against the other, and send the version header.
After the date
On 2027-09-01 the pre-envelope shapes stop being served and a request that states no version receives the 2026-09-01 shape instead. Nothing else changes — not the paths, not the parameters, not the error envelope. Send Forumulate-Version: 2026-09-01 to move now, and these headers stop arriving.
Versioning
Send Forumulate-Version on every request. It is optional only so that integrations written before versioning keep working:
Forumulate-Version: 2026-12-01Each version includes everything before it, and a version never changes once it is served. Start a new integration on the newest one, 2026-12-01.
Without it you get the legacy shape and the forumulate-version: legacy response header. Every response echoes the version it was served as.
What a dated version changes, for a caller who states it or later — everything else ships to every caller and needs no version:
Version | Changes |
|---|---|
| Collections answer with the |
|
|
|
|
The SDK cannot currently send this header, nor Idempotency-Key — it has no option for arbitrary request headers. Use fetch for calls that need either.
Idempotency
POST /orgs/{orgId}/spaces/{spaceId}/items accepts:
Idempotency-Key: <any string, up to 200 characters>It is optional and inert without the header — a request that omits it behaves exactly as it always did. But send one: a retried create without a key makes a second page, and a retry is the normal outcome of a timeout you did not see.
A UUID per logical create is the easy choice.
This is currently the only operation in the API that declares the header.
Comma lists: fields and include
GET /orgs/{orgId}/spaces/{spaceId}/items?fields=id,title,slug,published&include=sectionsBoth take a comma-separated list. An unrecognised name is a 422 that enumerates the allowed set.
fields accepts: id, kind, title, slug, published, group, state, updatedAt, url, freshness, deleted, sections, markdown, contentIn, locale.
include accepts: sections, body.
A caveat about generated clients. The OpenAPI document currently declares both as single-valued enums rather than as exploded arrays. The server accepts the list; a strict generated client, or an OpenAPI-driven "try it" panel, may refuse to send one. Until that is corrected in the spec, build those two query strings yourself.
Item languages: locale
Every row of GET /orgs/{orgId}/spaces/{spaceId}/items carries locale: the language that piece is declared to be written in, as canonical BCP-47 — es, pt-BR, zh-Hant, es-419. Language lowercase, script title case, region uppercase; never an underscore form, whatever was stored.
locale is null when nobody declared a language for that piece. It is never filled in from the space's contentLanguage or the organization's: a space holding two languages is where a default is wrong for half the rows, and a substituted default cannot be told apart from a fact. If you want a fallback, read GET /public/orgs/{org}/spaces/{space}/seo yourself and apply it knowing it is one.
What counts as declared, per kind:
Kind |
|
|---|---|
| what was declared for it; else, for a language twin, the twin's language; a source page is |
| what was declared for it, else |
| what was declared for it, else |
Language twins of the primary version (POST …/docs/locales) are listed as items of their own, with their own id, locale and url (the language's address, e.g. …/docs/es/webhooks). A topic's or an incident's translations are served under the piece's own id and are not separate items.
Correcting a language. PATCH /orgs/{orgId}/spaces/{spaceId}/items/{itemId} with { "locale": "es" } — or null to clear it — works on every kind. A language-only correction moves the item's updatedAt, so it comes back in ?updated_since=, and never changes contentHash: the hash is of what the piece says, and its language is not part of that. It does not move a page to another language's address.
Joining /items to the other routes. An item's id is the id its kind's own routes use. A page item's id is the page id — the same value as id in GET …/pages (PageListRow) and the {pageId} of every …/pages/{pageId} route, twins included. A topic item's id is the topic id of the blog, forum, changelog and roadmap routes (topics are not in …/pages). An incident item's id is the {incidentId} of …/status/incidents/{incidentId}.
Share tokens
A private space's content can be read with a rotating share token:
?share=<token>It is accepted on the public reader routes and on the PDF routes. It is scoped to one space and it rotates, so it is safe to put in a review link and not safe to put in a public page.
Forum counts and fields that read one rule
Likes. Every like count in the forum API counts the same thing: a member's reaction on a visible post that is not 👎, from anyone but the post's author. That covers a topic list row's likeCount, each post's likeCount in a topic payload, the profile summary's topReplies[].likes, topTopics[].likes and topPosts[].likes, the profile's stats.likesReceived, and the leaderboard's likesReceived. So a member's item likes add up to their "likes received". voteCount is still the net score (👍 minus 👎) that ranks a question's answers. The published reactions map still lists every emoji, anonymous reactions included.
Fields the front-page bands read (all optional on older payloads):
Payload | Field | What it is |
|---|---|---|
|
| Published topics created in the last 7 days, own + subcategories. |
same, |
| When the newest visible post went up (ISO), and the reply count. |
|
| The same time for a list row. |
|
| The @handle (null when there is none) and the name the member goes by. |
OpenAPI import. An import's answer carries landing: false when it laid the tags at the collection's top level on its own (a fresh import with landing unset, see Import content). Absent means the landing you sent, or a landing page.
Categories. A category carries topicKind ("question", "discussion" or null), the owner's word for what it holds. It decides which topics count toward the automatic Q&A look; see Forum.
What is not in the spec
Routes under /internal and /platform are ours, and are stripped from the published document. If you find one in a reference page, that page predates the stripping — the live spec has none.
Two tag groups that are published and look internal are genuinely yours: Impersonation (a "view as" for staff with the capability) and QueueAdmin (your organization's own background job queues).
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.
Escalation Providers
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List providers in an organization (escalation) |
| |
| Replace the provider |
| |
| Delete the provider |
| |
| Send a test call to an escalation provider |
| |
| Rotate inbound secret in an organization |
|
Escalation Reader
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Get the topic |
| |
| Create the topic |
|
Form Insights
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Get the form insight |
| |
| Delete the partial |
|
Item
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List items in a space |
| |
| Create an item in a space |
| |
| Get the item (spaces) |
| |
| Update the item (spaces) |
| |
| Delete the item (spaces) |
| |
| Get the content in a space |
| |
| Replace the content in a space (items) |
| |
| List chunks in a space |
| |
| Verify the item |
| |
| Publish the item (spaces) |
| |
| List fields in a space |
| |
| Update fields in a space |
| |
| Replace the section (items) |
|
Live Rooms
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List live rooms in a space |
| |
| Create a live room in a space |
| |
| Update a live room |
| |
| Delete the live room |
| |
| Start a live room |
| |
| Create the end in a space |
|
Live Rooms Public
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List live rooms in a space (public reader) |
| |
| Get a live room |
| |
| Join a live room |
| |
| Get the stream in a space (live rooms) |
| |
| Create the signal in a space |
| |
| Create the heartbeat in a space (public reader live rooms) |
| |
| Leave the live room |
| |
| Create the role in a space |
| |
| Create the end in a space (public reader) |
| |
| Create the sfu role in a space |
| |
| Create the sfu end in a space |
|
Manifest
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Apply a declarative site manifest (dry run by default) |
|
Org orgs
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List orgs |
| |
| Create an org |
| |
| Get the org |
| |
| Update the org |
| |
| Delete the org |
|
Phone Optins
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| The text channels this space offers readers |
| |
| Opt a phone in for event texts; a code is texted to it |
| |
| Confirm a phone with the code texted to it |
| |
| Stop the texts to a phone |
|
Problems
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Health of an organization |
|
Public seo
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List SEO settings in a space (public reader) |
|
Public Federation
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Get the forum federation in a space |
|
Public Member Segments
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Get the membership in an organization |
|
Public Network
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Whether this reader may read the space from their network |
| |
| Whether this space is limited to some networks |
|
Public Post Engagement
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Record a reader event on a post or release |
|
Public Reader Marks
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| Read the signed-in reader’s reading streak |
| |
| Read a post’s claps, top highlight and restacks |
| |
| Highlight, note or restack a post |
| |
| Clap for a post |
| |
| Remove one of your own marks |
|
Public Tags
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List tags in a space (public reader) |
| |
| Get the tag (public reader spaces) |
|
Reports
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List reports in an organization |
| |
| Community health report |
| |
| File of members (reports) |
| |
| File of export (reports) |
|
Saved Queries
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List saved queries in an organization |
| |
| Create a saved query in an organization |
| |
| List recipients in an organization (admin saved queries) |
| |
| Create the schedule preview in an organization |
| |
| Get the saved query |
| |
| Update the saved query |
| |
| Delete the saved query |
| |
| Run the saved query |
| |
| List runs in an organization (admin saved queries) |
| |
| Get the run |
| |
| File of export (admin saved queries runs) |
|
Scim
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List users |
| |
| Create an user |
| |
| Get the user |
| |
| Update the user |
| |
| Delete the user |
|
Scim Groups
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List groups |
| |
| Create a group |
| |
| Get the group (SCIM v2 groups) |
| |
| Replace the group |
| |
| Update the group (SCIM v2 groups) |
| |
| Delete the group (SCIM v2 groups) |
|
Security Policy
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| My standing against the organization’s two-step-verification policy |
| |
| Devices my account has signed in from |
| |
| Forget a remembered sign-in device |
|
Service Connectors
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| The service connectors on offer and their settings fields |
| |
| Every service connector and whether it is set up (never a secret) |
| |
| One service connector (never a secret) |
| |
| Set up or change a service connector |
| |
| Remove a service connector and its stored credentials |
| |
| Pull the trust centre controls from Vanta or Drata now |
| |
| The consent URL that connects Zoom or Google Meet |
|
Template
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| List the built-in space templates (deprecated) |
|
Ticket Wallet
Operation | Request | What it does | Shortcuts |
|---|---|---|---|
| The ticket as an Apple Wallet pass (.pkpass) |
| |
| Send the ticket holder to Google Wallet to save the pass |
|