Developers & AI agents
API keys & scopes
Create scoped keys and the capability each scope grants.
Scoped API keys let an agent (or any external client) act as you, limited to exactly the capabilities you grant. JWT sessions have full rights; API keys are constrained to their scopes.
Creating a key
Create keys in the web app: account menu (your avatar) → Developer → Create API key. Pick a name and the scopes, then copy the secret — it is shown once and stored only as a hash. Under the hood this is:
POST /v1/api-keys (requires a logged-in user JWT)
// body
{
"name": "my-agent",
"scopes": ["BALANCE", "TROPHIES", "WAGERS"]
}
The response includes the plaintext secret (prefix rk_) one time. Send it on
every request as x-api-key: rk_....
Managing keys
| Action | Endpoint | Auth |
|---|---|---|
| List your keys | GET /v1/api-keys |
JWT |
| Create a key | POST /v1/api-keys |
JWT |
| Revoke a key | DELETE /v1/api-keys/:id |
JWT |
Revoking is immediate and permanent; a revoked key stops authenticating.
The ApiKeyScope enum
Each scope gates one capability area. A route declares the scope it needs with
@Scope(...); a key must hold that scope or the request is 403'd. (The enum's
DB values use lowercase colon names like markets:write; the API and web UI use
the UPPERCASE enum names below.)
| Scope | Grants | Example routes |
|---|---|---|
MARKETS_READ |
Read contract acceptors / your bets (catalog & single-contract reads are public anyway) | GET /v1/markets/:id/acceptors, GET /v1/markets/:id/my-bets |
MARKETS_WRITE |
Issue / edit / close contracts, upload image, deposit collateral | POST /v1/markets, PATCH /v1/markets/:id, POST /v1/markets/:id/close, POST /v1/markets/:id/deposit-collateral |
ORDERS_WRITE |
Record an on-chain bet position on a contract | POST /v1/markets/:id/bet |
WAGERS |
Open / accept / cancel trophy wagers, list your wagers | POST /v1/trophies/wagers, POST /v1/trophies/wagers/:id/accept, POST /v1/trophies/wagers/:id/cancel, GET /v1/trophies/wagers/me |
TROPHIES |
View your case, buy / sell / gift trophies, claim / redeposit NFTs | GET /v1/trophies/me, POST /v1/trophies/buy, POST /v1/trophies/sell, POST /v1/trophies/claim |
BALANCE |
View in-app balance + ledger, deposit, withdraw | GET /v1/balance, GET /v1/balance/transactions, POST /v1/balance/deposit, POST /v1/balance/withdraw |
PROFILE |
View / update your profile, view metrics, view / submit KYC | GET /v1/users/me, PATCH /v1/users/me, GET /v1/users/me/metrics |
STORES |
View / create / update your store | GET /v1/stores/me, POST /v1/stores, PATCH /v1/stores/:id |
STORE_READ |
Reserved scope for store reads (public store browse needs no scope) | GET /v1/stores (public) |
WEBHOOKS |
Manage webhooks | webhook management routes |
Public reads (contract catalog, a single contract, the trophy store, open wagers, the public store list, NFT metadata) require no scope at all.
Principle of least privilege
Grant only the scopes the agent needs. A read-and-deposit balance bot needs only
BALANCE; a market-making agent needs MARKETS_WRITE (+ MARKETS_READ for its
own bets). Adding TROPHIES to a key that never touches trophies just widens the
blast radius if the key leaks.