---
title: "Create API key"
method: POST
path: "/api_keys"
tags: ["API keys"]
---

# Create API key

`POST /api_keys`

## Request

- Base URL: `https://arena-predictions.com/api/v1`
- URL: `https://arena-predictions.com/api/v1/api_keys`
- Auth: one of:
  - API key in cookie `sb-access-token`
  - HTTP bearer

Mint a key. The plaintext token is returned once, in this response, and never again. Not idempotent: every call mints a new key. At most 20 keys (created or rotated) per account in any 24 hours.

## Request body

- KeyCreateRequest
  - `label` string: Trimmed; an empty label becomes "Untitled key".
  - `scopes` string[]: Defaults to records:read, portfolio:read and markets:read. trade:write is never a default: name it to place and cancel paper orders. While trading with keys is switched off it is refused (403 scope_not_available).
  - `expiresInDays` integer: Omit for a key that never expires.

## Response `201`

Created.

- KeyCreateResponse
  - `key` KeyView, required
    - `id` string, uuid, required
    - `label` string, required
    - `tokenPrefix` string, required: First 16 characters of the token, for matching a row to a key. Never the token.
    - `scopes` string[], required
    - `status` 'active' | 'rotating' | 'revoked' | 'expired', required: rotating: replaced by a rotation and still inside its grace period (it works until expiresAt).
    - `createdAt` string, date-time, required
    - `lastUsedAt` string, date-time, nullable, required: Updated at most once an hour.
    - `expiresAt` string, date-time, nullable, required
    - `revokedAt` string, date-time, nullable, required
    - `createdVia` 'web' | 'cli', required: web: Settings. cli: arena keys.
    - `rotatedFrom` string, uuid, nullable, required: The key this one replaced by rotation.
    - `rotatedAt` string, date-time, nullable, required: When this key was rotated.
    - `requestsThisMonth` integer, required: Keyed requests counted against this key this month (UTC).
  - `token` string, required: The plaintext key. Shown once; only its hash is stored.
  - `warning` string, required

## Other responses

- `400`: invalid_request: a cookie-session request that is not same-origin (Sec-Fetch-Site must be same-origin, or Origin must equal this site), Content-Type is not application/json, the body is not an object, label is not a string, scopes is malformed or names an unknown scope, or expiresInDays is out of 1..365.
- `401`: unauthorized (not signed in) or session_required (an API key was presented).
- `403`: guest_account (anonymous session), or scope_not_available (trade:write requested while trading with keys is switched off).
- `409`: key_limit_reached: ten active keys already. Revoke one first.
- `429`: key_creation_limited: 20 keys made in the last 24 hours. Retry-After says when the oldest turns a day old.
- `500`: Could not create the key.

---

[API](https://skmtc.dev/arena-predictions/apis/arena-api.md) · [All operations](https://skmtc.dev/arena-predictions/apis/arena-api/llms.txt) · [OpenAPI document](https://skmtc.dev/arena-predictions/apis/arena-api/revisions/9d89d166dae6?raw)
