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

# Authentication

> Create API keys, set an expiry, and send them on requests.

Every endpoint except `GET /openapi.json` requires a valid API key. Keys are
**organization-scoped** — a key can only access data belonging to the
organization that issued it, and it acts as the organization, not as any
individual coach.

## Create a key

API keys are managed by a **head coach or org admin** in the Coach Console under
**Settings → Security**.

<Steps>
  <Step title="Open Settings → Security">
    In the [web console](https://app.nexrex.ai), go to **Settings → Security** and
    find the **API keys** section.
  </Step>

  <Step title="Name the key and choose scopes">
    Give the key a descriptive name (e.g. "Analytics dashboard") and select the
    [scopes](/api-reference/scopes) your integration needs. The default is
    read-only.
  </Step>

  <Step title="Set an expiry">
    Choose an expiry window — **90 days** is the default. Keys that never expire
    are allowed but not recommended.
  </Step>

  <Step title="Copy the secret once">
    The full key (`nrx_prod_…`) is shown **once** at creation. Copy it into your
    secret store immediately — it cannot be retrieved again.
  </Step>
</Steps>

<Warning>
  Treat API keys like passwords. Store them in a secrets manager, never in source
  control or client-side code. If a key is exposed, revoke it in **Settings →
  Security** and issue a new one.
</Warning>

## Send a key

Two schemes are supported. **Bearer** is recommended.

<CodeGroup>
  ```bash Bearer (recommended) theme={null}
  curl https://api.nexrex.ai/api/v1/developer/v1/org \
    -H "Authorization: Bearer nrx_prod_your_key_here"
  ```

  ```bash X-API-Key header theme={null}
  curl https://api.nexrex.ai/api/v1/developer/v1/org \
    -H "X-API-Key: nrx_prod_your_key_here"
  ```
</CodeGroup>

## Expiry and revocation

* **Expiry** is enforced on every request. A request with an expired key receives
  `401` with code `key_expired` — so your integration can detect the cause and
  prompt for a fresh key rather than failing opaquely.
* **Revocation** is immediate. A revoked key receives `401` with code
  `key_revoked`.
* An unknown or malformed key receives `401` with code `invalid_key`.

See [Errors](/api-reference/errors) for the full envelope and code list.

## Key rotation

There is no automatic rotation. To rotate: create a new key, deploy it, confirm
traffic has moved over (the console shows each key's **last used** time), then
revoke the old one.
