ApikeeApikeeDocs
Core concepts

Scopes

Naming scopes, enforcing them, and why they cannot change after issuance.

A scope is a short string naming one capability. Verification proves a key is genuine; scopes decide what that key may actually do.

read:users
write:orders
billing:refund
admin

Format

Scopes match ^[a-z0-9*][a-z0-9:._*-]{0,63}$ (case-insensitive), and a key may carry at most 32 of them. Duplicates are collapsed.

The conventional shape is action:resource. Nothing enforces that — admin is a perfectly valid scope — but a consistent convention pays off once you have more than a handful.

PatternExampleUse for
action:resourceread:usersMost things
resource:action:qualifierorders:write:bulkFiner splits
Bare capabilityadminCoarse, whole-surface access

Enforcing

from apikee.fastapi import require_scope
from fastapi import Depends

@app.delete("/v1/users/{id}", dependencies=[Depends(require_scope("admin"))])
def delete_user(id: str): ...

A missing scope is a 403, not a 401 — the caller is authenticated, just not permitted.

Reading them yourself

The claims object always carries the full list, so you can branch on it directly when a decorator is too blunt:

if (req.apikee!.scopes.includes('billing:refund')) { /* … */ }

Scopes are immutable

Scopes are signed into the key, so they cannot be edited afterwards. To change what a consumer may do, issue a new key and revoke the old one.

This is what makes local verification trustworthy: if scopes could drift server-side, every request would need a lookup to be sure, and the 0.1ms local path would be a lie.

Declaring scopes on endpoints

Registering which scopes a route needs does not enforce anything — enforcement is the code above. It populates your generated docs and the developer portal, so consumers can see what to ask for:

apikee.describeEndpoint('DELETE', '/v1/users/{id}', {
  description: 'Permanently delete a user.',
  scopes: ['admin'],
})

See Endpoints.

On this page