Roles and permissions

Who may write, who may publish, and who may change the settings of a brand.

3 min read

Three roles per brand

Every member of a brand has exactly one role in that brand. The same person can be an editor in one brand and an admin in another. The API checks the role before it looks at the request body, so a call you may not make fails with 403 whatever you send.

RoleCan
EditorWrite drafts, request a review, upload media, create terms, and move pages that are not live.
PublisherEverything an editor can, plus publish, schedule, roll back and delete entries, change or move live pages, manage redirects, menus, fragments and strings, delete media, retry webhook deliveries, and read and manage leads.
AdminEverything a publisher can, plus settings, theme, modules, block definitions, webhooks, members, API tokens, integrations, secrets, custom scripts, imports and the audit log.

A brand always keeps at least one active admin. You cannot remove or suspend the last one.

Platform admin is different

A platform admin manages brands of the whole installation (create, rename, suspend). It is not a brand role, it is set only on the server command line, and it gives no access to the content of a brand. To read or edit a brand, a platform admin still needs a membership there.

Minimum role per content type

An admin can give a custom content type a min_role of editor, publisher or admin. Without one, every member can use the type.

A member who ranks below min_role gets 403 on that type's entries: list filters, show, create, save a draft, publish, revisions, AI actions, reviews and exports. Unfiltered lists simply leave those entries out. Public delivery is not affected.

Review workflow

An editor cannot publish, so they ask for a review. A review pins one revision, so approving it publishes exactly what was reviewed.

StepCallWho
RequestPOST /v1/manage/entries/{entry}/review with an optional noteAny member
ListGET /v1/manage/reviewsPublishers and admins see all, an editor sees their own
ApprovePOST /v1/manage/reviews/{review}/approve, with publish: true to go livePublisher, admin
Send backPOST /v1/manage/reviews/{review}/changes with a required notePublisher, admin
CancelPOST /v1/manage/reviews/{review}/cancelThe requester, publisher, admin
CommentPOST /v1/manage/reviews/{review}/comments with a bodyThe requester, publisher, admin

If the page changed after the review was requested, approving with publish: true answers 409 revision_changed and nothing goes live. A new request for a newer version cancels the older open one. Every step is audited and sends a realtime update.

Members and invitations

Only admins manage members. All calls need the X-Brand-Id header.

CallWhat it does
GET /v1/manage/membersLists members with role and status (active or suspended).
POST /v1/manage/membersBody {email, role}. Adds an existing account (201) or, for an unknown email, creates an invitation and answers 202.
PATCH /v1/manage/members/{user}Changes a member's role.
POST /v1/manage/members/{user}/suspendBlocks the member in this brand. Other brands are unaffected.
POST /v1/manage/members/{user}/unsuspendRestores the member.
DELETE /v1/manage/members/{user}Removes the member from the brand.
GET /v1/manage/invitationsLists pending invitations.
POST /v1/manage/invitations/{id}/resendSends a fresh link and extends the invitation to 7 days.
DELETE /v1/manage/invitations/{id}Revokes an invitation.
invite.jsonjson
{ "email": "[email protected]", "role": "editor" }

The invitation link is sent only by email and is never part of an API answer, so whoever holds the link must own the inbox. If the brand has no working mail connection, the answer says email_sent: false: fix the mail settings and press Resend. A suspended member keeps the membership and role but gets 403 on every call of that brand.

Token kinds and who creates them

POST /v1/manage/api-tokens creates a token. Admins can create every kind. The one exception for other members is a short preview token.

KindWho may create itExpiry
readAdminOptional, 1 to 43200 minutes. Without one it never expires.
previewAdmin, or any memberRequired. Up to 7 days for an admin, 1 to 120 minutes for a member.
agentAdmin, when the brand setting agent.enabled is on15 minutes to 90 days, 30 days by default.
developerAdmin15 minutes to 90 days, 30 days by default.

A member who asks for any other kind, or a longer preview, gets 403. Only admins can list and revoke tokens. See tokens and security for how to send them and MCP and agent access for agent tokens, which write drafts only and always act with the editor role.

Other brands and the audit log

  • A record of another brand is a 404, not a 403. Every query is limited to the active brand, so a foreign id looks exactly like one that does not exist, and ids do not leak.
  • A suspended brand answers 403 on public and dashboard calls alike.
  • Authorization runs first. The role and content type checks happen before validation, so a forbidden call never reveals whether the body was valid.
  • Every live change is audited. Publishing, rollbacks, deletes, setting changes, member and token changes write an audit row with ids, never content bodies or secrets.

GET /v1/manage/audit-logs lists the audit rows to admins, newest first, 50 a page. Add ?action=member.suspended to filter by one action.

For the full list of rules, see tokens and security.

Was this page helpful?

Suggest a change