Skip to Content
ReferencePermission catalog

Permission catalog

Synq has two permission scopes:

  • System (AdminPermission) — granted to Synq staff or system admins on a Synq deployment. Used for routes under /admin/....
  • Organization (IdentityOrgPermission) — granted to org members via roles. Used for routes under /identity/organizations/.../....

A user can be a system admin without being a member of any organization, and vice versa. They are independent.

Built-in org roles

Every org has three built-in roles:

RolePermissionsNotes
OwnerAll permissions, including OwnershipTransfer and OrgDelete.Exactly one per org. Transfer ownership to change.
AdminEverything except OwnershipTransfer and OrgDelete.Operational admin.
MemberRead-only across most surfaces. No Edit permissions, no API key management.Default for invited users.

Custom roles can be created via the org roles API with any subset of IdentityOrgPermission.

IdentityOrgPermission

PermissionWhat it grants
org.readRead the org metadata. Implied by every member.
org.editUpdate org metadata (name, description, icon, etc.).
org.deleteSoft-delete the org. Owner-only.
org.members.viewList members, view audit log.
org.members.editInvite, remove, change roles. Cannot self-demote below Admin.
org.ownership.transferTransfer ownership. Current owner only.
org.brands.viewList and read brands.
org.brands.editCreate, update, delete brands.
org.apps.viewList and read apps under the brand. Sees clientId, not clientSecret.
org.apps.editCreate, update, delete apps. Rotate secrets.
org.connections.viewList BYO connections (no plaintext config — ever).
org.connections.editConfigure BYO credentials.
org.scopes.viewList brand-defined scopes.
org.scopes.editCreate, update, delete brand-defined scopes.
org.webhooks.viewList webhooks and delivery logs.
org.webhooks.editCreate, update, delete webhooks. Rotate secrets.
org.tokenGates.viewList token gates.
org.tokenGates.editCreate, update, delete token gates.
org.billing.viewView invoices and current plan.
org.billing.editChange plan, manage payment methods.
org.users.viewSearch users associated with this brand.
org.apiKeys.viewList org-owned API keys.
org.apiKeys.editCreate, rotate, revoke org-owned API keys.
  • Developerorg.brands.view, org.apps.edit, org.scopes.edit, org.webhooks.edit. Cannot manage members or billing; can ship.
  • Billingorg.billing.view, org.billing.edit.
  • Supportorg.members.view, org.users.view, org.brands.view, org.apps.view, org.connections.view, org.webhooks.view. Read-only across the board.
  • Security auditororg.members.view (for the audit log), org.connections.view, org.apiKeys.view. Read but cannot modify.

AdminPermission (system)

Most app developers will never see admin permissions. They exist for Synq operators.

PermissionWhat it grants
admin.users.viewRead any user record.
admin.users.editUpdate or delete any user. Used for support.
admin.orgs.viewRead any org.
admin.orgs.editUpdate or delete any org. Manage plans.
admin.plans.editManage Stripe products and tiers.
admin.roles.editManage built-in role definitions.

Permission checking in your backend

Permissions appear in the access token’s scope claim only when your App explicitly requested them. Most product apps don’t request org-permission scopes (they’re dashboard concerns, not user-app concerns).

If your app is a dashboard or admin tool, request the permissions you need:

scope=openid profile email org.members.view org.brands.edit

Then check in your backend:

function requireOrgPermission(perm: string) { return (req, res, next) => { const granted = (req.user.scope ?? '').split(' ') if (!granted.includes(perm)) { return res.status(403).json({ error: { code: 'forbidden', message: 'missing permission', details: { missing: perm } }, }) } next() } } app.post( '/api/admin/brands', authMiddleware, requireOrgPermission('org.brands.edit'), createBrandHandler, )

Inheriting org permissions through API keys

An org API key inherits the scopes its creator was granted. When you create an API key, you can restrict it further by passing a scopes array; the key will be capped by the smaller of (creator’s permissions, explicit scope list).

This lets you give a CI bot a subset of an admin’s permissions without making the bot itself an admin.

Mental model summary

  • Org permissions live in the access token’s scope claim. Your backend reads them and gates routes.
  • Most product apps don’t request org permissions — those are dashboard concerns.
  • Custom roles combine any subset of org permissions.
  • API keys inherit their creator’s permissions, capped by an optional explicit scopes array.
  • System (admin.*) permissions are for Synq operators, not app developers.
Last updated on