> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gateway.connexease.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create API Key

> Issue a new API key for an application. The key value is returned once and cannot be retrieved again.

## What it does

Creates a new API key for an application. The response contains the key value itself — **this is the only time it is ever returned**. Later reads expose the key's metadata (name, expiry, status) but never the secret again.

<Warning>
  **The key value is shown once.** Store it in your secret manager the moment you receive it. If it is lost, the only remedy is to create a new key.
</Warning>

***

## Endpoint

```text theme={null}
POST /api/v1/apps/{app_id}/api-keys
```

### Headers

<ParamField header="Authorization" type="string" required>
  Secret key in `Bearer sk_...` format. See [Secret Key authentication](/essentials/authentication#secret-key).
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Always `application/json`.
</ParamField>

### Path parameters

<ParamField path="app_id" type="string" required>
  Application ID the key is issued for. Must belong to the organization (otherwise `404`).
</ParamField>

***

## Request Body

<ParamField body="name" type="string" required>
  A label for the key. Use something that identifies where the key is deployed (`prod-backend`, `ci-pipeline`) — it is how you will recognise the key later, since the value itself is not visible.
</ParamField>

<ParamField body="expiresAt" type="string">
  ISO-8601 timestamp at which the key stops working. Must be in the future.

  <Tip>
    Set an expiry even for long-lived keys, and rotate before it lands: create the new key, deploy it, then let the old one expire. That way a rotation never needs a window where no valid key exists.
  </Tip>
</ParamField>

***

## Response

<ResponseField name="isSuccess" type="boolean">
  `true` when the key was created.
</ResponseField>

<ResponseField name="data" type="object">
  The created key.

  <Expandable title="data">
    <ResponseField name="id" type="string">
      UUID of the key record. Use this to refer to the key afterwards.
    </ResponseField>

    <ResponseField name="appId" type="string">
      The application the key belongs to.
    </ResponseField>

    <ResponseField name="name" type="string">
      The label you supplied.
    </ResponseField>

    <ResponseField name="key" type="string">
      **The key value — returned only in this response.** Not retrievable afterwards.
    </ResponseField>

    <ResponseField name="isActive" type="boolean">
      Whether the key is currently usable.
    </ResponseField>

    <ResponseField name="expiresAt" type="string">
      ISO-8601 expiry timestamp.
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO-8601 creation timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

***

## Examples

<AccordionGroup>
  <Accordion title="Demo 1 — create a key with an expiry">
    ```text theme={null}
    POST /api/v1/apps/app_7poyXj8GXuv76e/api-keys
    Authorization: Bearer sk_...
    Content-Type: application/json
    ```

    ```json theme={null}
    {
      "name": "prod-backend",
      "expiresAt": "2027-08-20T13:27:30.368Z"
    }
    ```

    ```json theme={null}
    {
      "data": {
        "id": "47fee6cf-9634-47b2-882f-4e9b90e57158",
        "appId": "app_7poyXj8GXuv76e",
        "name": "prod-backend",
        "key": "<secret_key>",
        "isActive": true,
        "expiresAt": "2027-08-20T13:27:30.368000Z",
        "createdAt": "2026-08-20T13:33:15.985914Z"
      },
      "isSuccess": true
    }
    ```

    Copy `data.key` now — the next read of this key will not include it.
  </Accordion>

  <Accordion title="Demo 2 — error: missing name → 400">
    ```text theme={null}
    POST /api/v1/apps/app_7poyXj8GXuv76e/api-keys
    Authorization: Bearer sk_...
    Content-Type: application/json
    ```

    ```json theme={null}
    { "expiresAt": "2027-08-20T13:27:30.368Z" }
    ```

    ```json theme={null}
    { "errors": { "code": "REQ_001", "group": "VALIDATION", "description": "Missing required field: name" }, "isSuccess": false }
    ```
  </Accordion>

  <Accordion title="Demo 3 — error: expiresAt in the past → 422">
    ```text theme={null}
    POST /api/v1/apps/app_7poyXj8GXuv76e/api-keys
    Authorization: Bearer sk_...
    Content-Type: application/json
    ```

    ```json theme={null}
    { "name": "stale-key", "expiresAt": "2025-01-01T00:00:00Z" }
    ```

    ```json theme={null}
    {
      "errors": {
        "code": "VAL_000",
        "group": "VALIDATION",
        "description": "Validation failed.",
        "fields": {
          "expiresAt": { "code": "VAL_018", "description": "Date must be in the future." }
        }
      },
      "isSuccess": false
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Errors

<ResponseField name="errors" type="object">
  Error details with `code`, `group`, and `description`; `isSuccess` is `false`.
</ResponseField>

| HTTP | Code                      | Group        | When                                                                                                                                        |
| ---- | ------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `REQ_001`                 | `VALIDATION` | Missing required field or invalid JSON.                                                                                                     |
| 401  | `ORGANIZATION_SECRET_010` | `NOT_FOUND`  | Authorization / secret key is missing.                                                                                                      |
| 401  | `ORGANIZATION_SECRET_011` | `NOT_FOUND`  | Secret key is invalid.                                                                                                                      |
| 404  | `APPLICATION_004`         | `NOT_FOUND`  | `app_id` does not belong to the organization.                                                                                               |
| 422  | `VAL_000`                 | `VALIDATION` | Field validation — `expiresAt` not in the future, invalid date format, `name` length. Each offending field is listed under `errors.fields`. |

***

## Next steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="lock" href="/essentials/authentication#secret-key">
    How keys are presented on requests.
  </Card>

  <Card title="Update Webhook" icon="link" href="/public-api-reference/developers/update-webhook">
    Point the app's events at your server.
  </Card>
</CardGroup>
