Skip to content

Auth And Scopes

Use this page to choose the correct auth surface and least-privilege management scopes before you start calling the API.

Who This Is For

  • developers creating or rotating management API keys
  • AI agents selecting scopes for an automation task
  • operators debugging 401 and 403 TOKEN_SCOPE_DENIED responses

When To Use This

Read this before creating keys, wiring SDK clients, or documenting example requests.

This page is intentionally scope-first because auth mistakes are one of the most common reasons integrations fail early.

How It Works

Three auth surfaces

SurfaceHeaderUsed forSuccess shape
ManagementAuthorization: Bearer <token>catalog setup, licenses, devices, events, webhooks, reporting{data, meta}
RuntimeAuthorization: License <license-key>activation, validation, check, consume, deactivate, offline issuance, floating leases{data, signature, meta}
Systemnonepublic keys, health, readiness, metricsendpoint-specific

Do not reuse a management bearer token for runtime requests. Do not put a license key on management routes.

Scope model

Management operations expose least-privilege requirements via the operation-level x-required-scopes field in api/openapi.yaml.

Current management scopes are:

ScopeUse it for
adminbootstrap, API-key management, customer records, any management route
product:readread products, policies, features, versions, orders, subscriptions
product:writecreate and update catalog resources
license:readread licenses, devices, license features, license custom fields
license:writeissue, renew, suspend, reinstate, revoke, transfer, assign features, reset usage
device:writedevice reset and blacklist
event:readraw audit event feed
ops:readops summary, runtime-error groups, webhook health
report:readactivity feed and reporting read endpoints
report:exportexport creation, export metadata, export download
webhook:writewebhook endpoint management

Important rules:

  • admin satisfies every management route even when a narrower scope is listed.
  • customer routes are currently admin-only.
  • webhook read routes currently still require webhook:write.
  • reporting read and export scopes are separate on purpose.

Common scope bundles

Use these as a starting point, then confirm against the exact operation:

  • catalog setup: product:write
  • catalog readback: product:read
  • license issuance and lifecycle: license:write
  • license and device inspection: license:read
  • device reset and blacklist: device:write
  • raw audit polling: event:read
  • operator rollups: ops:read
  • reporting reads: report:read
  • frozen exports: report:export

Example

Create a scoped management key with admin, then use narrower keys for routine automation:

bash
curl -X POST https://api.licensekit.dev/api/v1/api-keys \
  -H "Authorization: Bearer $BOOTSTRAP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "license-writer",
    "scopes": ["license:write"]
  }'

If you are using the TypeScript SDK, scope metadata can be queried by operationId:

ts
import { getRequiredScopes, hasRequiredScopes } from "@licensekit/sdk";

const required = getRequiredScopes("createLicense");
const allowed = hasRequiredScopes("createLicense", ["license:write"]);

Common Mistakes

  • creating every automation key with admin instead of narrowing it
  • assuming a route named GET must always use a read scope
  • forgetting that runtime routes use a different auth header entirely
  • debugging TOKEN_SCOPE_DENIED without checking the exact operation in api/openapi.yaml

Prototype docs shell for the rewrite workspace.