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

# Create an API key

`POST /apiKeys`

## Request

- Base URL: `https://api.cactal.ai/v1`
- URL: `https://api.cactal.ai/v1/apiKeys`
- Auth: HTTP bearer

Creates an API key that authenticates as its own principal within the organization. `access` grants either one organization-wide role (`admin`, `full_editor`, or `content_editor`) or one role (`full_editor` or `content_editor`) on at least one website in the organization; the `owner` role can never be granted, and website ids outside the organization fail with 400. `name` is 1–200 characters and `expiresAt` is an ISO 8601 timestamp or `null` for a key that never expires. The response contains the plaintext secret exactly once — only a SHA-256 hash is stored, so it cannot be retrieved again.

## Request body

- object
  - `organizationId` string, required
  - `name` string, required
  - `expiresAt` union, required
    - unknown
    - string, date-time
  - `access` union, required: Access configuration of an API key: either one organization-wide role, or one role across an explicit set of websites. The `owner` role can never be granted to an API key.
    - object
      - `kind` 'organization', required: Grants one role across the entire organization.
      - `role` 'admin' | 'full_editor' | 'content_editor', required: Organization-wide role held by the key.
    - object
      - `kind` 'websites', required: Grants one role on an explicit set of websites.
      - `websiteIds` string[], required: Ids of the websites the key can access. All must belong to the organization of the key.
      - `role` 'content_editor' | 'full_editor', required: Role held by the key on each listed website.

## Response `200`

The created key and its `plaintextKey` secret. Store the secret now; it is never shown again.

- object
  - `apiKey` object, required: Metadata and access configuration of the key.
    - `id` string, required: Unique id of the API key.
    - `name` string, required: Human-readable label, 1–200 characters.
    - `organizationId` string, required: Id of the organization that owns the key.
    - `access` union, required: Access configuration of an API key: either one organization-wide role, or one role across an explicit set of websites. The `owner` role can never be granted to an API key.
      - object
        - `kind` 'organization', required: Grants one role across the entire organization.
        - `role` 'admin' | 'full_editor' | 'content_editor', required: Organization-wide role held by the key.
      - object
        - `kind` 'websites', required: Grants one role on an explicit set of websites.
        - `websiteIds` string[], required: Ids of the websites the key can access. All must belong to the organization of the key.
        - `role` 'content_editor' | 'full_editor', required: Role held by the key on each listed website.
    - `expiresAt` string, date-time, nullable, required: When the key stops authenticating. `null` when it never expires.
    - `revokedAt` string, date-time, nullable, required: When the key was revoked. `null` while the key is active.
    - `createdAt` string, date-time, required: When the key was created.
  - `plaintextKey` string, required: The plaintext secret, a 32-byte base64url string. Store it now; it is never shown again, and only a SHA-256 hash is kept.

## Other responses

- `400`: Validation failed. The response `message` names the first invalid field.
- `401`: Missing, invalid, expired, or revoked API key.
- `403`: The authenticated principal lacks the required capability.
- `404`: The resource does not exist or is outside the principal’s access scope.
- `429`: Rate limit exceeded. Retry after the number of seconds in the `Retry-After` header.

---

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