Skip to main content

Master key — Platform API key

The master key (mk_) is the highest-privilege credential in the CashXChain system. It is a platform-operations credential, distinct from the developer API keys (sk_, pk_, rk_) used by external integrations.


What it can do

CapabilityMaster key
Access all /v1/* routes
Access /internal/* dashboard routes
Write operations (POST, PUT, DELETE, PATCH)
Scope enforcementBypassed — all scopes always pass
Create via API❌ — admin script only
Revoke via API❌ — database only

The master key is the only API credential that can reach dashboard routes. Regular API keys (sk_, pk_, rk_) are rejected at the middleware layer before any database lookup — they cannot access dashboard endpoints regardless of their scopes or type.


Key format

mk_sandbox_<64 hex characters>

Total length: 75 characters. Identical format to other key types — only the prefix differs.

Production: mk_live_<64 hex characters>


How to obtain one

Master keys cannot be created through any HTTP endpoint. They are provisioned exclusively by running the admin seed script with direct database access:

node scripts/create-master-key.mjs \
--account-id <account-uuid> \
--label "Ops dashboard key"

Prerequisites:

  • DATABASE_URL environment variable pointing at the target database.
  • Direct network access to the database (not via the API).

What the script does:

  1. Generates 32 random bytes → 64 hex characters.
  2. Prepends mk_sandbox_ (or mk_live_) to form the full key.
  3. SHA-256 hashes the full key.
  4. Extracts key_prefix (first 20 characters) and key_suffix (last 4 characters) for masked display.
  5. Inserts into the master_keys table with created_by = 'admin-seed-script'.
  6. Prints the full key to stdout once with a warning.
✓ Master key created
Label: Ops dashboard key
Prefix: mk_sandbox_ab12cd34ef56
Last 4: a1b2
Token: mk_sandbox_ab12cd34ef56...a1b2 ← COPY THIS NOW
⚠ This key is not stored. Copy it before closing this terminal.

Using the key

Pass the master key in the Authorization header exactly like any other bearer token:

Authorization: Bearer mk_sandbox_ab12cd34ef56...a1b2

The API detects the mk_ prefix and routes the lookup to the master_keys table (not api_keys). All scope checks are bypassed. All dashboard routes are accessible.


Request flow

Authorization: Bearer mk_sandbox_<64hex>

api_key_auth middleware detects mk_ prefix

SHA-256 hash the token

SELECT FROM master_keys WHERE key_hash = $1 AND revoked_at IS NULL

Found → AuthContext { key_type: "master", scopes: [] }

Background task: UPDATE master_keys SET last_used_at = NOW()

Handler runs — scope checks unconditionally pass

Revoking a master key

There is no API endpoint for revoking a master key. Revocation requires direct database access:

UPDATE master_keys
SET revoked_at = NOW()
WHERE id = '<key-uuid>';

In an incident, revocation takes effect immediately on the next request to the key — the partial index WHERE revoked_at IS NULL ensures revoked keys are never found in authentication lookups.


Storage and security

PropertyDetail
Tablemaster_keys (separate from api_keys)
Stored valueSHA-256 hex digest only — plain-text never stored
Domain structMasterKey deliberately excludes the key_hash field — hash never leaves the database layer
Collision preventionUNIQUE (key_hash) constraint
Lookup indexPartial index on (key_hash) WHERE revoked_at IS NULL — O(1) and never touches revoked rows

When to use a master key

Use master keys for:

  • Internal dashboards — the CashXChain ops dashboard and monitoring tools.
  • Platform automation — scripts that manage accounts, run reconciliation, or access multi-account data.
  • Internal tooling — anything that needs /internal/* routes.

Do not use master keys for:

  • Third-party integrations — issue a sk_ key with the minimum required scopes.
  • Customer-facing applications — issue a pk_ key for read-only access.
  • Any context where the key could be exposed outside your infrastructure.

Differences from secret key (sk_)

mk_sk_
Dashboard routes (/internal/*)
Created via API
Revoked via API
Stored in master_keys table
Scope bypass
Write access