Organizations
Create API Key
Server-side issuance of a database-backed AXON API key
POST
Create API Key
Mint a new
Success (
Returned when:
The caller is authenticated but cannot mint the requested key. Common causes:
axon_sk_* API key for an organization. The server generates the plaintext, HMAC-hashes it with the AXON_API_KEY_HASH_PEPPER (the same hash function verifyDatabaseApiKey uses on the read side), stores only the hash in api_keys, and returns the plaintext exactly once.
This route replaces the dashboard’s previous client-side hashing path, which was broken because the dashboard and the verifier used different hash functions. All new keys — dashboard-issued or CLI-issued — now flow through
POST /v1/api-keys so they are verifiable on the read side.Authentication
This is an operator-surface route. Accepted callers:- A Supabase JWT with
owneroradminmembership onorganization_id - An org-wide tenant API key with write scope on the same organization
- A wallet-bound tenant API key with write scope, but only when minting another key for that same wallet
- The static operator key
Request Body
Response
Success (201 Created)
Response Fields
Errors
400 VALIDATION_ERROR
Returned when:
organization_idis missing or not a valid UUIDnameis missing or emptyscopesis present but emptywallet_idis present but belongs to a different organization
403 REJECTED_POLICY
The caller is authenticated but cannot mint the requested key. Common causes:
- wallet-bound key trying to mint an org-wide key
- wallet-bound key trying to mint a key for a different wallet
- caller lacks write authority on
organization_id
404 NOT_FOUND
wallet_id was supplied but does not exist (or the caller cannot see it).
Hash function
The server storesHMAC-SHA256(plaintext, AXON_API_KEY_HASH_PEPPER) — never the plaintext itself. The pepper lives in Cloud Run’s Secret Manager and is not accessible from the database. A DB leak alone is not enough to reverse or brute-force a stored key.
verifyDatabaseApiKey (the function that runs on every authenticated request) uses the same HMAC function, which is why all new keys must be issued through this server-side route — client-side hashing with a different function would produce unverifiable keys (the bug that motivated this route’s creation, see CHANGELOG 2026-04-08).
See also
@axon402/cli— the primary consumer of org-wide tenant keys- GET /v1/me — introspect which org + scopes a key resolves to
- Authentication — overall auth model for the Decision API