Provenance

Authentication

Provenance authenticates every request (except /health) with an API key.

Key format

Keys are prefixed by environment:

prv_live_<32 base62>
prv_test_<32 base62>

We store only a SHA-256 hash of the key, its 8-character display prefix, and its last 4 characters, so the dashboard can show prv_test_…a1B2 and you can tell keys apart (keys created before last-4 display existed show the prefix only). The raw key is shown once, at creation. If you lose it, revoke and issue a new one.

Passing your key

Either header works:

curl $PROVENANCE_API/v1/claims \
  -H "Authorization: Bearer $PRV_KEY"

# or
curl $PROVENANCE_API/v1/claims \
  -H "X-API-Key: $PRV_KEY"

A missing key returns authentication_required; a bad one, invalid_api_key.

Sandbox keys

Three keys are pre-provisioned in the sandbox and safe to publish — they only ever touch sandbox data:

| Key | Scopes | | --- | --- | | prv_test_full_K7mN3xQp9RbT2vWm8sYd4cFjLhXn6gAe | all | | prv_test_verify_M3xQp9RbT2vWmK7n8sYd4cFjLhXe6gA | verify | | prv_test_attest_p9RbT2vWmK7n3xQ8sYd4cFjLhXe6gAM | attest |

Scopes

Each route requires one scope: verify, attest, escalate, admin, intent, or screen. A key missing the required scope gets insufficient_scope (403). Grant least privilege — a verify-only integration should carry only verify.

Self-serve Authorize keys also carry a plan (developer, growth, or enterprise) that governs metering and the monthly cap — see Billing.

Rotation & lost keys

Create a replacement key, deploy it, then revoke the old one. Revoked keys return api_key_revoked; expired keys, api_key_expired. Because we never store the raw key, "recovering" a lost key is impossible by design — rotate instead.

Sandbox vs live

Sandbox and live are fully isolated at the query level. A sandbox key can never read or write live data; crossing environments returns environment_mismatch. See Environments.

Dashboard login vs. API keys

There are two ways to authenticate, for two different callers:

Account-management endpoints accept either. /v1/policy* and /v1/account/* work with an account-bearing API key or a dashboard session, so anything you do in the UI you can also script. Cookie-authenticated mutations additionally require a CSRF header (the dashboard handles this); API-key calls are exempt. Product-section visibility in the dashboard is driven by the account's products entitlement — a UX convenience only; real authorization is still enforced per API scope and per-account policy on the server.

Magic-link tokens and session secrets are stored only as hashes (like API keys), tokens are single-use with a short TTL, and in sandbox the sign-in link is echoed in the response so you can log in without an inbox.

Teams, roles & SSO (Enterprise)

An account is an organization; users are members with a role. Magic-link stays for self-serve — teams and SSO are additive (a single-user account behaves exactly as before).

SSO, teams, and roles beyond owner are an Enterprise feature (requirePlan(enterprise)).