Skip to content

Docs / 11 of 14

API keys

Create, rotate, and revoke Organization ApiKey credentials. Scopes, secret handling, usage ingestion, and the errors a runtime will see. For workspace admins.

2 min read

An ApiKey belongs to the Organization, not to a User. Most operators never need one. Create a key if a runtime, self-hosted license, or internal job must call /api without a browser session.

Manage keys at /dashboard/api-keys. Empty state: No keys. Create one if you are calling the API. Most operators never need this.

owner or admin only. member and billing cannot issue keys. Rate limit: 10 creates or rotates per hour per Organization.

What is stored

You seeWe store
Name you chosename
Display prefix, for example nm_live_7Qf2…prefix (first 12 characters)
Secret, once, at creationsha256 of the secret only (hashedSecret)
Scopesscopes (default ["usage:write"])
Live vs testlivemode
Last use, expiry, revoke timelastUsedAt, expiresAt, revokedAt

There is no “show secret again.” If you lost it, rotate or create a new key.

Format: nm_{live|test}_{32 chars base62}.

Create

  1. /dashboard/api-keys → create.
  2. Name the key after the runtime that will hold it (for example billtray-prod), not after a person.
  3. Set scopes if you need more than usage write.
  4. Optional expiresAt.
  5. Copy the secret immediately.

Confirmation: Key created. Copy it now; we will not show it again.

The JSON create response is the only payload that ever contains secret. List endpoints return metadata only.

Send the key as a bearer credential on API-key routes. Do not put it in a query string, a repo, or a frontend bundle. API-key routes must not also present a session cookie.

Scopes

ScopeUse
usage:writePOST /api/usage/events — default.
entitlements:readGET /api/entitlements, GET /api/entitlements/[productSlug], POST /api/entitlements/check (batch, max 50 slugs).

A key does not impersonate a User and does not grant owner. It cannot invite members, change plans, or issue other keys.

orgId is taken from the key. Clients cannot pass a different Organization.

Rotate and revoke

Rotate (POST .../api-keys/[id]/rotate): issues a new secret. The old key remains valid for graceMinutes (default 60), then expires. Use this when you can update the runtime within an hour.

Revoke (DELETE): immediate. Confirmation: Key revoked. Calls using it will fail.

Removing a Membership does not revoke keys. If a departing admin copied a secret, revoke that key.

Issuance, rotation, and revocation write AuditLog rows.

Usage ingestion

POST /api/usage/events with scope usage:write. Batch max 500 events. Each event: productSlug, metric, optional quantity, optional occurredAt, required idempotencyKey.

Checks:

  • Live Entitlement for that productSlug, or 403 entitlement_required.
  • read_only Entitlement → 403 entitlement_read_only.
  • metric must equal Product.usageMetric, or 422 unknown_metric.
  • occurredAt within [-7 days, +5 minutes], or 422 timestamp_out_of_range.
  • Duplicate (orgId, idempotencyKey) → counted as deduped, HTTP 202.

Over unitCap, events are still recorded. The response may include warnings: ["unit_cap_exceeded"].

Rate limit: 600 requests per minute per key. Entitlement checks: 1,200 per minute per key. Exceeding returns 429 with Retry-After.

Test vs live

nm_test_… keys are for non-production runtimes. Do not point a production connected worker at test keys. Do not put live keys in a laptop .env that is copied around.

Next