---
title: "Mint an API key"
method: POST
path: "/v1/api-keys"
tags: ["API keys"]
---

# Mint an API key

`POST /v1/api-keys`

## Request

- Base URL: `https://realtimeavatar.ai/api`
- URL: `https://realtimeavatar.ai/api/v1/api-keys`
- Auth: HTTP bearer

Mint a developer API key for the caller's own tenant. The plaintext key is returned in this response. Workspace owners and admins can recover eligible keys in the dashboard; recovery is not available through the developer API.

Requires an API key with the `api_keys:write` scope.

## Request body

- CreateApiKeyRequest
  - `name` string, required
  - `environment` 'live' | 'test': Deprecated. Accepted for older clients but ignored; all new keys use the same tic_ format.
  - `scopes` string[]
  - `spendLimitCreditMicros` integer, nullable
  - `expiresAt` string, date-time, nullable

## Response `201`

Created. The plaintext key is returned on creation; workspace owners and admins can recover eligible keys in the dashboard. Recovery is not available through the developer API.

- CreateApiKeyResponse
  - `id` string, required
  - `keyId` string, required
  - `tenantId` string, required
  - `name` string, required
  - `redactedKey` string, required
  - `canReveal` boolean, required
  - `scopes` string[], required
  - `status` 'active' | 'revoked' | 'expired', required
  - `spendLimitCreditMicros` integer, nullable, required
  - `createdAt` string, required
  - `expiresAt` string, nullable, required
  - `apiKey` string, starts_with, required

## Other responses

- `401`: Missing, malformed, revoked, or expired key.
- `403`: The key lacks the scope for this operation, or the tenant is not active.
- `default`: Error. Route-dependent: 400 (a field this route cannot honour — see `portraitUrl` on `UpdateAvatarRequest`), 402 (insufficient credits or spend limit), 404 (no such avatar, voice, or key for this tenant — the message often reads "does not belong to this tenant", which is a missing id and not a permission failure), 408 (the request was cancelled), 409 (the resource is not in a state that accepts this write — a stale `expectedRevision`, a render already in flight, or a mint that asked for a clip library still building), 411 (`POST /v1/assets/remote` only — the origin serving `remoteUrl` sent no `content-length`, so the platform will not stream it), 422 (strict schema rejection, or a motion description the safety screen refused), 429 (rate limited), 502 (upstream render failed), 503 (a dependency this route needs is unavailable — retryable, and nothing was written), 504 (the upstream request budget expired), 500 (unhandled). Switch on `code` where present, else `status`.

---

[API](https://skmtc.dev/realtimeavatar/apis/realtime-avatar-api.md) · [All operations](https://skmtc.dev/realtimeavatar/apis/realtime-avatar-api/llms.txt) · [OpenAPI document](https://skmtc.dev/realtimeavatar/apis/realtime-avatar-api/revisions/e9e3e998e673?raw)
