> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Permissions

> Complete reference of all root key permissions in Unkey. Control which API operations each root key can perform across your workspace.

export const DashboardScreenshot = ({src, alt, width}) => <>
    <img className="block dark:hidden" src={`${src}-light.png`} alt={alt} style={{
  width,
  maxWidth: "100%",
  height: "auto"
}} />
    <img className="hidden dark:block" src={`${src}-dark.png`} alt={alt} style={{
  width,
  maxWidth: "100%",
  height: "auto"
}} />
  </>;

Each root key has a set of permissions that control which API operations it can perform.

## Permission format

Permissions follow the pattern `{resource}.{scope}.{action}`. The scope determines which specific resource the permission applies to.

### Wildcards vs specific IDs

The scope can be either a wildcard (`*`) or a specific resource ID:

* `api.*.create_key` grants `create_key` on **all** keyspaces in the workspace.
* `api.api_abc123.create_key` grants `create_key` on **only** that specific keyspace.

The wildcard `*` means "all current and future resources of this type." A root key with `api.*.read_key` automatically gains read access to any keyspace created after the key was issued. A key with `api.api_abc123.read_key` can only read keys belonging to that one keyspace, even if new keyspaces are created later.

You can mix wildcards and specific IDs on the same root key. For example, a key for your billing service might have:

* `api.*.verify_key` to verify keys across all keyspaces
* `api.api_billing.create_key` to create keys in only the billing keyspace
* `ratelimit.*.limit` to enforce rate limits in any namespace

When configuring a root key in the dashboard, workspace-wide permissions (using `*`) are listed at the top under "Workspace." Below them, under "From APIs," each keyspace in your workspace is listed so you can grant keyspace-scoped permissions selectively.

<Frame>
  <DashboardScreenshot target="root-key-permissions" capture="target" capturedAt="2026-09-11T04:48:23Z" description="In a local workspace with a Billing keyspace, open Settings, Root Keys, New root key, then Select Permissions. Leave the search empty. Expand Workspace to show its permission groups. Keep Billing visible under From APIs. Do not select any permissions or create a root key. Use a 1440 by 1000 viewport. Capture only the permission sheet in light and dark themes." src="/docs/platform/root-keys/root-key-permissions" width={384} alt="Root key permission sheet showing workspace-wide permission groups and the Billing keyspace under From APIs" />
</Frame>

### Insufficient permissions

If a root key attempts an operation it does not have permission for, the Unkey API returns a `403 Forbidden` response with an error indicating which permission is missing. Check the error message to determine which permission to add to the key.

## Keyspace permissions

These permissions control management of keyspaces in your workspace.

<ResponseField name="api.*.create_api">
  Create new keyspaces in the workspace. There is no keyspace-scoped variant of this permission, since the keyspace does not exist yet at creation time.
</ResponseField>

<ResponseField name="api.{apiId}.read_api">
  Read information about a keyspace, including its name, configuration, and settings. Use `api.*.read_api` to read all keyspaces.
</ResponseField>

<ResponseField name="api.{apiId}.update_api">
  Update a keyspace's configuration. Use `api.*.update_api` to update any keyspace.
</ResponseField>

<ResponseField name="api.{apiId}.delete_api">
  Delete a keyspace and all its associated keys. Granting this on a specific keyspace does not grant delete access to other keyspaces. Use `api.*.delete_api` to delete any keyspace.
</ResponseField>

<ResponseField name="api.{apiId}.read_analytics">
  Query analytics data for a keyspace using SQL. Use `api.*.read_analytics` to query across all keyspaces.
</ResponseField>

## Key permissions

These permissions control creation, verification, and management of API keys.

<ResponseField name="api.{apiId}.create_key">
  Create new keys in a keyspace. Use `api.*.create_key` to create keys in any keyspace.
</ResponseField>

<ResponseField name="api.{apiId}.read_key">
  Read information and analytics about keys, including metadata, expiration, remaining uses, and rate limit configuration. Use `api.*.read_key` to read keys across all keyspaces.
</ResponseField>

<ResponseField name="api.{apiId}.update_key">
  Update a key's metadata, rate limits, expiration, remaining uses, or other properties. Use `api.*.update_key` to update keys in any keyspace.
</ResponseField>

<ResponseField name="api.{apiId}.delete_key">
  Delete keys belonging to a keyspace. Use `api.*.delete_key` to delete keys in any keyspace.
</ResponseField>

<ResponseField name="api.{apiId}.verify_key">
  Verify API keys and enforce their rate limits and permissions. This is the permission your backend server needs to validate incoming requests from your users. Use `api.*.verify_key` to verify keys across all keyspaces.
</ResponseField>

<ResponseField name="api.{apiId}.encrypt_key">
  Encrypt keys belonging to a keyspace. Unkey stores API keys as hashes by default. With this permission, you can store an encrypted copy of the plaintext key that can be retrieved later. Use `api.*.encrypt_key` for all keyspaces.
</ResponseField>

<ResponseField name="api.{apiId}.decrypt_key">
  Decrypt keys belonging to a keyspace. Required to retrieve the original plaintext value of a key that was stored with encryption. Without this permission, you can verify a key but cannot recover its value. Use `api.*.decrypt_key` for all keyspaces.
</ResponseField>

## Rate limit permissions

These permissions control rate limit namespaces and overrides. All rate limit permissions use the `ratelimit.*` scope.

<ResponseField name="ratelimit.*.create_namespace">
  Create new rate limit namespaces in the workspace. Namespaces group related rate limit configurations together.
</ResponseField>

<ResponseField name="ratelimit.*.read_namespace">
  Read information about rate limit namespaces, including their configuration and current state.
</ResponseField>

<ResponseField name="ratelimit.*.update_namespace">
  Update rate limit namespace configuration, such as changing the default limit or window duration.
</ResponseField>

<ResponseField name="ratelimit.*.delete_namespace">
  Delete rate limit namespaces from the workspace.
</ResponseField>

<ResponseField name="ratelimit.*.limit">
  Execute a rate limit check against an identifier. This is the permission your backend needs to enforce rate limits at runtime.
</ResponseField>

<ResponseField name="ratelimit.*.set_override">
  Set a rate limit override for a specific identifier. Overrides let you grant higher or lower limits to individual users or entities without changing the namespace defaults.
</ResponseField>

<ResponseField name="ratelimit.*.read_override">
  Read rate limit overrides for an identifier.
</ResponseField>

<ResponseField name="ratelimit.*.delete_override">
  Delete a rate limit override, reverting the identifier to the namespace default.
</ResponseField>

## RBAC permissions

These permissions control your ability to manage the [RBAC system](/docs/platform/apis/features/authorization/introduction) through the Unkey API. They govern who can create roles, define permissions, and assign them to API keys.

This is a separate layer from the roles and permissions you define within RBAC itself. For example, `rbac.*.create_role` on a root key lets you call the API to create a new role, while the roles you create (like "editor" or "viewer") are assigned to your end-user API keys and checked at verification time.

All RBAC permissions use the `rbac.*` scope.

### Roles

<ResponseField name="rbac.*.create_role">
  Create a new role in the workspace. Roles are named collections of permissions that you can assign to API keys.
</ResponseField>

<ResponseField name="rbac.*.read_role">
  Read roles and their associated permissions in the workspace.
</ResponseField>

<ResponseField name="rbac.*.delete_role">
  Delete a role from the workspace. Keys that had this role lose the permissions it granted.
</ResponseField>

### Permissions

<ResponseField name="rbac.*.create_permission">
  Create a new permission definition in the workspace. Permissions are the building blocks you assign to roles or directly to keys.
</ResponseField>

<ResponseField name="rbac.*.read_permission">
  Read permission definitions in the workspace.
</ResponseField>

<ResponseField name="rbac.*.delete_permission">
  Delete a permission definition from the workspace.
</ResponseField>

### Key assignments

<ResponseField name="rbac.*.add_role_to_key">
  Assign a role to an API key. The key inherits all permissions associated with that role.
</ResponseField>

<ResponseField name="rbac.*.remove_role_from_key">
  Remove a role from an API key. The key loses the permissions that role granted, unless another assigned role also grants them.
</ResponseField>

<ResponseField name="rbac.*.add_permission_to_key">
  Assign a permission directly to an API key, bypassing roles.
</ResponseField>

<ResponseField name="rbac.*.remove_permission_from_key">
  Remove a directly assigned permission from an API key.
</ResponseField>

## Identity permissions

These permissions control [identities](/docs/platform/identities/overview), which let you associate multiple API keys with a single user or entity. All identity permissions use the `identity.*` scope.

<ResponseField name="identity.*.create_identity">
  Create a new identity in the workspace.
</ResponseField>

<ResponseField name="identity.*.read_identity">
  Read identity information, including external ID and metadata.
</ResponseField>

<ResponseField name="identity.*.update_identity">
  Update an identity's metadata or other properties.
</ResponseField>

<ResponseField name="identity.*.delete_identity">
  Delete an identity from the workspace.
</ResponseField>

## Portal permissions

These permissions control the customer portal. All portal permissions use the `portal.*` scope, and portal ids carry the `pc_` prefix.

Only `create_portal_session` is enforced today. The four management actions below are reserved for the portal management API, which has not shipped yet, so granting them currently has no effect.

Session minting is a separate action from the four management actions, so a backend that mints sessions in production does not need the right to change portals.

<ResponseField name="portal.*.create_portal_session">
  Mint a portal session for an end user. This is the permission a production backend needs.

  Minting is additionally bounded by your own permissions: a session can never carry a capability the calling root key does not itself hold. Each requested scope requires the equivalent permission on every keyspace the portal resolves to, so `keys:read` requires `read_key` and `read_api`, and `keys:reroll` requires `create_key` (plus `encrypt_key` when the keyspace stores encrypted keys). `analytics:read` accepts either form: the `api.{apiId}.read_analytics` tuple or the keyspace-logs URN `unkey:v1:{workspaceId}:projects/{projectId}/keyspaces/{keyspaceId}/logs#read`. Requesting a scope you do not hold returns 403 for the whole request.

  Note the breadth of a wildcard grant: holding `api.*.read_key` and `api.*.read_api` lets this key mint a `keys:read` session for **any** portal in the workspace, because a wildcard satisfies every resolved keyspace. That is consistent with what the key can already read directly, but it is not visible when ticking the box. `api.*.read_analytics` grants `analytics:read` the same way.
</ResponseField>

<ResponseField name="portal.*.create_portal">
  Create a new portal in the workspace.
</ResponseField>

<ResponseField name="portal.*.read_portal">
  Read portal configuration.
</ResponseField>

<ResponseField name="portal.*.update_portal">
  Update a portal's configuration, including branding.
</ResponseField>

<ResponseField name="portal.*.delete_portal">
  Delete a portal from the workspace.
</ResponseField>

Revoking an individual portal session is not covered by these actions. When that route lands it gets its own `delete_portal_session` action rather than folding into `delete_portal`, so the ability to end one end user's session stays separable from the ability to remove a portal.

## Deployment permissions

These permissions control deployment operations. All deployment permissions use the `project.*` scope.

<ResponseField name="project.*.create_deployment">
  Create new deployments in the workspace. Required for CI/CD pipelines that deploy through the Unkey API.
</ResponseField>

<ResponseField name="project.*.read_deployment">
  Read deployment details and status, including build logs and instance health.
</ResponseField>

<ResponseField name="project.*.generate_upload_url">
  Generate upload URLs for build contexts. Required during the deployment process to upload your application code.
</ResponseField>

<ResponseField name="project.*.read_gateway_requests">
  Query the gateway request data of all projects in the workspace with SQL.
</ResponseField>

<ResponseField name="project.*.read_runtime_logs">
  Query the runtime logs of all deployments in the workspace with SQL.
</ResponseField>

## Common permission sets

| Use case              | Permissions                                                                  |
| --------------------- | ---------------------------------------------------------------------------- |
| Verify keys only      | `api.*.verify_key`                                                           |
| Create keys for users | `api.*.create_key`, `api.*.read_key`                                         |
| Full key management   | `api.*.create_key`, `api.*.read_key`, `api.*.update_key`, `api.*.delete_key` |
| Rate limiting         | `ratelimit.*.limit`                                                          |
| Rate limit overrides  | `ratelimit.*.set_override`, `ratelimit.*.read_override`                      |
| CI/CD deployments     | `project.*.create_deployment`, `project.*.generate_upload_url`               |
| RBAC management       | `rbac.*.create_role`, `rbac.*.create_permission`, `rbac.*.add_role_to_key`   |
