Skip to main content

Permissions & Roles

Overview

Keyban authenticates two kinds of identity, with two separate permission systems:

  • Member roles govern human users in the Admin Console — Owner, Admin, Editor, Viewer.
  • API key permissions govern programmatic access — every call carrying an X-Api-Key header.

The two are orthogonal: a key issued by an Owner is not automatically Owner-equivalent.

Concepts

A small vocabulary set, used consistently throughout this page and the API.

TermMeaning
RoleNamed bundle of permissions assigned to a member of an organization (Owner, Admin, Editor, Viewer). One role per member per organization.
PermissionA (resource, action) tuple — e.g. (dpp, create). Permissions are not assigned individually to humans; they're assigned through a role.
ResourceA surface of the platform that can be acted upon: organization, member, invitation, team, application, dpp, loyalty, billing, settings, agentWallet, apiKey.
ActionWhat a permission grants on a resource: read, create, update, delete.
API key permissionThe same (resource, action) model, attached to an individual API key rather than to a role. Independent from the issuer's role.
Super-adminA platform-level flag set on a Keyban-team user account, granting cross-organization access. Not a role within an organization, not exposed to partners.
  1. Identity

    • Member

      Human user, signed into the Admin Console.

    • API key

      Machine identity, sent in the X-Api-Key header.

  2. Authorization

    • Role

      Owner, Admin, Editor, or Viewer — bundle of permissions.

    • Permissions map

      resource → actions[] attached directly to the key.

  3. Resource

    • dpp

      Digital Product Passports.

    • loyalty

      Programmes, accounts, points.

    • application · billing · …

      The other 9 resources defined in access-control.ts.

Human users reach a resource through their organization role; programmatic clients reach the same resource through the permissions field of an API key. The two paths converge on the same access-control gate.

Member roles

Roles at a glance

RoleBest forSummary
OwnerOrganization creator, CTOFull control over the organization, including deletion.
AdminTeam leads, project managersManages members, settings, and all modules — except organization deletion.
EditorDevelopers, content managersCreates and edits products and campaigns; reads settings.
ViewerStakeholders, external reviewersRead-only access to products and campaigns.

The only Owner-exclusive action is organization.delete. Editor and Viewer differ on a single axis: write access to products and campaigns.

What each role can do

The tables below use the user-facing labels (« DPP products », « Loyalty campaigns », « Applications »). The corresponding API resources are dpp, loyalty, and application.

Products & Campaigns

ActionOwnerAdminEditorViewer
View DPP products
Create DPP products
Edit DPP products
Delete DPP products
View Loyalty campaigns
Create Loyalty campaigns
Edit Loyalty campaigns
Delete Loyalty campaigns

Applications

ActionOwnerAdminEditorViewer
View applications
Create applications
Edit applications
Delete applications

Team management

ActionOwnerAdminEditorViewer
View members
Invite or remove members
Change member roles
Create or manage teams

Organization & Billing

ActionOwnerAdminEditorViewer
View settings
Edit organization settings
Delete organization
View and manage billing

Manage members

To invite or change member roles, you need the Owner or Admin role yourself.

Invite a member

  1. Go to Organization → Members in the Admin Console.
  2. Click Invite Member.
  3. Enter the member's email and pick a role (Admin, Editor, or Viewer).
  4. The invitee receives a magic-link email; the invitation expires after a set window.

Change a member's role

  1. Go to Organization → Members, find the member.
  2. Click the role dropdown next to their name and pick the new role.
  3. The change takes effect immediately on their next page load. No data is lost — the member simply gains or loses access to certain actions. In-progress writes that exceed the new role are rejected by the API.

Typical role assignments

Team memberRecommended roleWhy
Company founder / CTOOwnerNeeds full control including billing and org deletion.
Project managerAdminManages the team and settings, but shouldn't delete the org.
Developer / DesignerEditorCreates and updates products and campaigns daily.
Client / External auditorViewerNeeds to see data without modifying anything.

API key permissions

API keys carry their own permission map, independent from the role of the person who created them.

Permission shape

{
"<resource>": ["<action>", "<action>", ...],
...
}

Available resources and actions

The resources are the same as for member roles (defined in auth/access-control.ts):

organization, member, invitation, team, application, dpp, loyalty, billing, settings, agentWallet, apiKey.

Each resource accepts the same set of actions: read, create, update, delete.

Common scope recipes

Use casePermissions
Read-only audit script{ "dpp": ["read"], "loyalty": ["read"] }
Catalogue migration (one-shot){ "dpp": ["create", "update", "read"] }
Loyalty backend with mint{ "loyalty": ["read", "update"] }
Shopify integration{ "dpp": ["create", "update", "read"] }

Lifecycle

API keys are created, scoped, rotated, and revoked entirely from the Organization → API keys screen of the Admin Console. The full secret is shown once at creation time and cannot be re-displayed. There is no public REST surface for the key lifecycle today — the underlying authentication plugin (@better-auth/api-key) is integrated, but its routes are not part of Keyban's documented API.


How permissions are enforced

The Admin Console hides actions the current member's role doesn't grant — there are no greyed-out buttons. The API performs the same check on every request.

Two parallel checks, OR semantics

When an API call lands on the backend, the access-control gate accepts the request if either of the two paths grants the permission:

  • The session's user is a member with a role that includes (resource, action) for the calling organization, or
  • The X-Api-Key header carries a permission map that includes (resource, action).

A failure on both paths returns 403 Forbidden with a structured JSON body — see How to handle Keyban API errors.

A Viewer with a permissive API key can write

Because the gate is OR, a member with the Viewer role who also holds an API key carrying dpp: ["create"] can create passports through that key. Treat API keys as first-class identities — least-privilege scopes matter even for accounts whose human role is read-only.


Best practices

Least privilege

Pick the minimum role for each member, and the minimum scope for each API key. A read-only dashboard shouldn't carry create. A one-shot migration shouldn't carry delete.

One key per integration

Bind one key to one purpose — shopify-prod, migration-2026-q2, bi-dashboard. The blast radius on a leak is then limited to a single integration, and audit log entries identify the offender immediately.

Rotate proactively

Run the rotation pattern (create-deploy-revoke) at a known cadence, even when no incident pushed you to. Aim for once per quarter on long-lived integrations; immediately on any suspicion (committed to a public repo, shared in chat, exposed in a packet capture).

Set an expiry on temporary keys

For migrations, audits, demos: set expiresAt to the smallest reasonable window. Keyban does not currently send a reminder before expiry — set a calendar event of your own.

Audit the lifecycle

Every member role change and every API key creation/revocation is recorded by the Admin Console. Review the log periodically and after every team change.


Debug a 403

Run through this checklist before opening a support ticket. Most 403 responses fall into one of these four buckets.

  1. Identify your identity

    • If the call was made through the Admin Console, your active member role applies. Check it under Organization → Members → [your row].
    • If the call was made with an X-Api-Key, only the key's permissions apply. The session role of the key's creator is not considered.
  2. Map the endpoint to a (resource, action) pair

    • POST /v1/dpp/passports(dpp, create).
    • PATCH /v1/dpp/passports/:id(dpp, update).
    • POST /v1/loyalty/account/:id/mint(loyalty, update).
    • DELETE /v1/dpp/passports/:id(dpp, delete).
    • When in doubt, consult /backend-openapi — every operation lists its required permission.
  3. Compare

    • For a member role, look up the table in Member roles → What each role can do.
    • For an API key, fetch the key in Organization → API keys and read its permissions map.
    • If the required pair is absent, that's the cause. Either elevate the role (asking an Owner/Admin) or re-issue the key with a wider scope.
  4. Escalate with context

    • Include the request instance (the path), the response body's status, and your member id (or key prefix).
    • Reach out to your Keyban contact with this information.

What's not exposed today

To set expectations honestly:

  • No public REST surface for API key lifecycle. Creation, listing, rotation, and revocation happen through the Admin Console only.
  • No quota or per-key rate-limit fields surfaced through the UI. The AuthApiKey entity carries rateLimitMax / refillInterval columns but Keyban currently configures rate limits at the platform level.
  • No expiry alerts. Expired keys silently start failing — set a reminder when you create one with expiresAt.
  • No attribute-based access control (ABAC). Permissions today are role-and-resource based; finer-grained rules (« only edit DPP products you created yourself ») are not modelled. Cross-team isolation must be done by splitting into multiple organizations.