For the complete documentation index, see llms.txt. This page is also available as Markdown.

API keys

pk_, sk_, rk_, ak_ — when to use which.

All API access uses Bearer tokens. We ship four kinds, modelled after Stripe's pk_/sk_ split so the right ones can safely live in a browser.

Kind
Example
Where to use it
What it can do

pk_live_…

pk_live_f6589a94_7xPq…

Browsers, public pages, snippets

Ingest only. Origin-allowlisted — requests must come from an origin in your project's allowed_origins. Rejected at /mcp — MCP never accepts a key that ships in browser source.

sk_live_…

sk_live_a1b2c3d4_secret…

Servers, cron jobs, MCP write access

Ingest + read. No origin check.

rk_live_…

rk_live_99887766_secret…

Server-side dashboards, MCP clients (recommended)

Read only — query, stats, sources, MCP read tools. Cannot ingest.

ak_live_…

ak_live_1c4d8a90_secret…

Account-level MCP — agencies, multi-product teams

Read every project this account owns through one credential. Business tier only. Used by /mcp/account. Cannot ingest.

What's in a key

{kind}_{env}_{prefix}_{secret}
└──┬──┘ └─┬┘ └──┬───┘ └──┬───┘
 pk/sk/rk live  8-char  url-safe
                lookup  secret
  • The prefix (pk_live_f6589a94) is the lookup key. It's safe to display in dashboards and logs.

  • The secret is shown to you exactly once at mint time. Only sha256(secret || pepper) is stored — we cannot recover or re-display it. If you lose it, revoke and mint a new one.

Origin allowlist for pk_* keys

Every project has a list of allowed_origins. pk_* requests must carry an Origin: header that matches one of them, or they're rejected with 403 origin_not_allowed.

POST /v1/track HTTP/1.1
Authorization: Bearer pk_live_…
Origin: https://yoursite.com   ← must be in the project's allowed_origins

If you serve from https://yoursite.com and https://www.yoursite.com, list both.

sk_* and rk_* keys ignore Origin because they're never meant to be in a browser.

Minting and revoking

In the dashboard (apps/web):

  1. Open the project.

  2. Click + pk / + sk / + rk, give it a label.

  3. The secret appears in a modal once — copy it.

  4. To revoke, click Revoke on the key row. It cannot be undone; existing clients will immediately get 401 invalid_api_key.

Scopes vs kinds

Kind
Scope
Notes

pk

ingest

Browser-safe. Only ingest endpoints. Never accepted by /mcp.

sk

ingest

Same powers as pk but no origin check. Required for /v1/forget. Accepted by /mcp.

rk

read

Read endpoints + MCP read tools. Accepted by /mcp (recommended for AI agents).

ak

read

Account-scoped. Accepted only by /mcp/account. Sees every project the account owns. Business tier.

If you call a read endpoint with an ingest-scope key (or vice versa) you'll get 403 insufficient_scope. If you hit /mcp with a pk_ or ak_ key you'll get 403 key_kind_not_allowed. If you hit /mcp/account with anything other than ak_, you'll get 403 account_key_required.

When to use an ak_ key

Use one if you own more than one Millimetric project and you'd otherwise mint and rotate an rk_ key per project for the same agent. Examples:

  • A consultancy / agency running analytics for many clients.

  • A multi-product company with one project per app.

  • Staging + production isolated as separate projects.

You configure your MCP client once, against /mcp/account, and the agent can call list_projects, query a single project by project_id / project_slug, or run cross-project tools like compare_projects in one round trip. See MCP overview.

Operational notes

  • Rotation: revoke + re-mint. Re-issuing all keys requires changing the server pepper, which is a deliberate, planned event.

  • Last-used timestamp: each successful auth updates last_used_at on the key. Stale keys are easy to spot.

  • Caching: the Worker caches verified keys for 5 minutes per instance. Revocation takes effect within that window.

Last updated

Was this helpful?