Compliance endpoint permissions: the role matrix
Role requirements for compliance endpoints live on each feature’s own page, so until now you reconstructed the matrix by opening seven pages. This page centralizes it. Every row below names the gate exactly as the feature page states it, so the table and the pages cannot drift — and the pinned test that covers this page fails if they do. Two readings of a 403 disappear once you see the table: it is either a scope refusal (the credential’s API scope did not cover the route) or a role refusal (the member’s workspace role fell below the route’s declared floor). The fix is different for each, and Section 3 shows which one you got. All endpoints below are rooted athttps://api.orbit.devotel.io/api/v1. “Reads” and “writes” split at the
usual HTTP-method line: GET is a read; POST/PUT/PATCH/DELETE are
writes.
Section 1 — The per-endpoint role matrix
R = can read (GET). W = can write (POST/PUT/PATCH/DELETE). — = the
gate refuses with 403 INSUFFICIENT_PERMISSIONS. Where two rows appear,
the endpoint family splits read and write gates.
* Agent-identity routes additionally require the
agents:read scope (the
inventory) or agents:write (the bulk suspend) on the credential — see
Section 2.
Notes that the bare grid cannot hold:
- DSAR also has a public path. A data subject files without any role
at all through the unauthenticated
/compliance/public/dsar/*endpoints (Turnstile + OTP). The matrix covers operator calls; the public flow is how your customers’ rights arrive. - BAA splits owner-only from owner/admin. Reading the state,
previewing the template, downloading the executed copy, and the
require/decline attestations all admit
owneroradmin— butexecuteandrevertareowner-only because they bind or unwind a legal agreement. An admin starring as “the compliance person” on an execute call is the single most common mistaken hand-off. - Vertical bundles and fraud review read lower than they write.
Bundles admit any of the four standard workspace roles on reads
(
owner/admin/developer/viewer) but dropvieweron writes. Fraud-review reads go to any authenticated member — includingbilling— so an on-call accountant can investigate an alert, but only owner/admin can acknowledge, dismiss, or move thresholds. - SCIM settings are owner-only throughout. Token issuance, role mapping, and group mapping are all owner-gated; there is no admin delegation on that surface.
Section 2 — agents:read / agents:write scopes versus workspace roles
A 403 on an agent-adjacent route is one of two different refusals, and the
fix differs.
Scope is a property of the credential. An API key minted without
agents:read cannot read an agent surface no matter whose role it was
minted from; without agents:write it cannot write. Scope travels with
the key, so passing an admin’s viewer-scoped key still fails the scope
check.
Role is a property of the member. When you call through the
dashboard or a session token, the member’s workspace role is what the gate
reads. When you call with an API key, the role of the member the key was
minted under is what the gate reads.
Agent-identity governance needs both — the inventory gates on the
agents:read scope AND an owner/admin role; the bulk-suspend gates on the
agents:write scope AND an owner/admin role. Neither alone is enough:
The same dual gate shows up on the broader agent stack (guardrail
effectiveness, computer-use sessions, fine-tuning, authorization
mandates): reads on
agents:read, writes on agents:write, each with a
declared role floor on top. If your call is to an agent route and you got
a 403 you cannot explain, check scope first — it is the less visible half.
Section 3 — Reading a 403 and handing the call off
The error envelope tells you which layer refused. Readerror.code
first:
401 UNAUTHORIZED/401 INVALID_API_KEY/401 EXPIRED_TOKEN— no usable credential reached the gate at all. This is an authentication problem, not a permission problem: fix the key, its expiry, or its source IP (see Authentication and API keys).403 INSUFFICIENT_PERMISSIONS— the credential authenticated, but its role or scope does not cover the route. This is the matrix above.
403 INSUFFICIENT_PERMISSIONS, the hand-off depends on
which row the endpoint sits on:
Do not escalate scope and role asks in the wrong direction. Elevating a
viewer to admin fixes every role refusal above, but it cannot fix a
missing agents:write scope on the key, and an owner-scoped key minted
under a developer still mis-carries role. Name which of the two you
need when you hand the call off — “elevate me” for a role refusal,
“re-mint the key with the scope” for a scope refusal, “both” when the
route gates both (see Section 2).
Section 4 — Where your failed call is recorded
Every refusal above is recorded against your organization. Open Settings → Audit log — the page is restricted toowner and admin,
which is why the failed caller cannot always self-serve their own
attempt. Filter by the actor (your own name), the target endpoint’s
resource, or the time the call failed; each row carries the event code, the
resource, and the full detail JSON once you expand it. Write attempts that
succeeded land in the same ledger — the SCIM token-issuance, BAA
execute/revert, vertical-bundle activations and checklist toggles,
fraud-review acknowledges and dismisses, agent-identity suspends, and
DSAR filings all append an entry naming the actor — so the same page
answers both “why did my 403 happen” and “who executed this BAA.”
For longer-horizon evidence — SOC 2 evidence hand-offs, GDPR Article-30
records — the audit-export family (owner/admin, per the matrix) bundles
the whole ledger into a hash-chained export an auditor can verify
independently: Audit Export.
Related references
- Roles, teams, and permissions — the ten built-in roles, the hierarchy floor, and the custom-role grant model this matrix gates on.
- BAA — the owner-only execute/revert split in detail.
- SCIM Provisioning — the owner-only settings and token surface.
- Data Subject Access Requests — the operator-filed versus public-subject split.
- Audit Export — the owner/admin export family and the hash-chain verification.
- PHI Audiences — the owner/admin gate plus the BAA prerequisite.
- Plugin Marketplace and Vertical Bundles — where the any-member-read / three-role-write split comes from.
- Fraud Review Triage — the any-member-read / owner-admin-write split, end to end.
- Agent Identity Governance — the scope-plus-role dual gate.
- Authentication and API keys — the 401 family this page splits from the 403 family.
- Audit Log — reading the record of your own failed call.