#Roles & permissions
Ratifia controls who in your org can do what through roles. A role is a named bundle of permissions, and a person's (or an API key's) access is the union of every role they're assigned. Roles and their assignments are owned by Ratifia, per org, so access doesn't drift from wherever your team happens to sign in.
#Permissions
A permission is a single coarse capability. The full vocabulary:
| Permission | Grants |
|---|---|
decisions:read-mine | see the decisions you take part in: you are one of its approvers or its assignee, or you voted on it. Also a pending decision that names no approvers, since anyone may answer it |
decisions:read-all | see every decision in the org |
decisions:decide | approve / reject decisions |
decisions:request | ask for decisions: create, read, cancel, verify and consume them; register a worker; trigger a run (for API keys) |
policies:read | view approval policies |
policies:write | create / edit approval policies |
approvers:write | manage approvers |
settings:write | change org settings |
members:manage | manage members and their role assignments |
roles:manage | create / edit / delete custom roles |
apikeys:manage | manage API keys |
billing:read / billing:write | view / manage billing |
usage:read | view usage |
audit:read | read the audit log |
The same vocabulary is shared by the dashboard (what it shows you) and the API (what it lets you call), so a permission means the same thing wherever it's checked.
Roles govern people and API keys alike. See API keys below.
#Built-in roles
Three roles ship with every org and are always present. They're defined in code, not stored as editable rows, so they never drift:
- admin. Full access, including managing roles, members, and billing.
- approver. Review and decide (
decisions:read-mine,decisions:decide). They see their own Inbox and Archives, not other people's decisions, and nothing under Configuration. To let someone read policies or every decision, give them a custom role withpolicies:readordecisions:read-all. - integration (API keys only). Request, verify and consume decisions, and read policies (
decisions:request,decisions:read-mine,decisions:read-all,policies:read). It can't change who approves. New API keys get this role.
Built-in roles can't be edited or deleted, and their names (admin, approver, integration) are reserved, so you can't create a custom role with any of them.
#Custom roles
Need something between the two? Create a custom role with exactly the permissions you choose. Custom roles are org-scoped and managed in the dashboard under Roles (or via /v1/roles, gated on roles:manage). Deleting a custom role also drops it from everyone it was assigned to.
#Assigning roles
Assign roles to people in the dashboard under Members (or via /v1/members, gated on members:manage). Each member lists their roles; add or remove assignments there. A member with several roles gets the combined permissions of all of them.
Nobody is locked out by default
A person with no explicit role assigned still gets a safe default so they're never stranded: a solo account resolves to admin, and a team member with nothing assigned yet gets the approver baseline (they can review). Any explicit assignment, including a restrictive custom role, always overrides this default.
#API keys
An API key holds roles too, chosen when you create it in the dashboard under API Keys; you can change them later without changing the key. A key can do only what its roles allow, and a key with no role can do nothing. Rotating a key keeps its roles.
What each integration needs:
| Integration | Role |
|---|---|
| Agents via the MCP server, the SDK, the Inngest adapter, n8n | integration (the default) |
Policy-as-code (POST /v1/worker/policies, preview) | a role with policies:write, e.g. admin |
Keep policies:write off keys that don't manage policies. A key that can write a policy can change who approves, so a leaked one could route the next approval to someone else. Every such change still creates a policy version and an audit row.
No key can vote, whatever its roles: deciding is for people (not_an_approver).
Keys created before roles existed were given admin, the access they already had. Narrow them under API Keys.
#The last-admin guard
An org can never lose its ability to administer itself:
- Removing the final
adminfrom an org is rejected. There must always be at least one admin. - The org owner's admin role is permanent; nobody, not even the owner, can remove it.
#Enforcement
Permissions are enforced server-side: a request from someone (or an API key) lacking the required permission is rejected with 403 insufficient_permission, naming the permission. The dashboard uses the same vocabulary to hide actions a person can't take, so the UI and the API agree on who can do what.