---
title: "Create a new API key"
method: POST
path: "/v1/auth/keys"
tags: ["Auth"]
---

# Create a new API key

`POST /v1/auth/keys`

## Request

- Base URL: `https://api.zindex.ai`
- URL: `https://api.zindex.ai/v1/auth/keys`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Creates a new API key for the authenticated person. It acts in the workspace the request acts in, and a key made with a key gets a scope no wider than its own. The key is returned in plaintext only once - store it securely. Use a descriptive name to identify the key's purpose (e.g., 'Production', 'Claude Desktop', 'Cursor').

## Request body

- object
  - `name` string: A descriptive name for this key to identify its purpose. Examples: 'Production API', 'Claude Desktop', 'Cursor', 'Development'. If omitted, the key has no name (null).
  - `expiresInDays` integer, nullable: Number of days until the key expires. Integer in [1, 366] inclusive (covers a leap year), or null/omitted for a key that never expires. After expiry, requests with this key return 401 with code 'API_KEY_EXPIRED'. Default: null (never expires) - matches the agent-host integration pattern where the key lives in a long-lived MCP config file.
  - `scope` 'write' | 'read': write: read, change, share and report diagrams. read: read only. Default write when the caller can write, else read.

## Response `201`

API key created

- object
  - `id` string, required
  - `key` string, required: The API key (shown only once). Prefixed with dsp_sk_
  - `ownerId` string, required
  - `workspaceId` string, required: The workspace the key acts in: the one the request acted in
  - `scope` 'write' | 'read', required
  - `name` string, nullable
  - `expiresAt` string, date-time, nullable, required: ISO-8601 UTC timestamp when the key expires, or null if it never expires. Echoes the server-computed expiry from the request's expiresInDays (now + N days). Used by clients to display 'Expires on YYYY-MM-DD' in their UI.

## Other responses

- `400`: INVALID_EXPIRES_IN_DAYS: expiresInDays isn't an integer from 1 to 366 or null. INVALID_REQUEST: name isn't text of at most 64 characters, or scope isn't write or read.
- `401`: Missing or invalid API key. Response includes a `code` field that distinguishes the failure mode so clients (dashboard, MCP server) can render actionable copy: `AUTH_REQUIRED` (no key or session was sent), `API_KEY_INVALID` (key not found), `API_KEY_REVOKED` (key was revoked, or its person is no longer in its workspace), `API_KEY_EXPIRED` (key passed its expires_at), and for the site's session cookie `SESSION_EXPIRED` (past its 24 hours), `SESSION_REVOKED` (the account's sessions were ended, for example by a password reset) and `SESSION_INVALID` (not a session this server signed).
- `403`: PLAN_LIMIT_EXCEEDED: the workspace has reached its plan's `apiKeys` limit (Free 3, Pro 10, Team 10 per paid seat), or a viewer already holds 3 keys in it (`maximumAllowed: 3`); `error` states the limit and the count. READ_ONLY: `write` asked for without write access (a read key, or a viewer); `reason` says which.
- `429`: RATE_LIMITED: over the request rate limit (see Rate Limiting). Wait retryAfter seconds (also the Retry-After header), then try again.

## Changes

- **2026-10-20** `1d21bd5bbf8e`: 9 info
  - added the new optional request property `expiresInDays`
  - added the new optional request property `scope`
  - added the non-success response with the status `400`
  - added the non-success response with the status `403`
  - …5 more

[Operation history](https://skmtc.dev/zindex/apis/zindex-api/changes/v1/auth/keys/post.md)

---

[API](https://skmtc.dev/zindex/apis/zindex-api.md) · [All operations](https://skmtc.dev/zindex/apis/zindex-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zindex/apis/zindex-api/revisions/1d21bd5bbf8e?raw)
