> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ellaworx.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ellaworx.ai/_mcp/server.

# API Keys

API keys let you call the Ellaworx API from scripts, CI pipelines, and deployed agents without a browser session. Each key is scoped to a single organization.

## Create an API key

1. Sign in to [platform.ellaworx.ai](https://platform.ellaworx.ai) and select your organization
2. Navigate to **Settings → API Keys**
3. Click **Create API Key** and give it a descriptive name of up to 32 characters (e.g. `ci-deploy`, `production-agent`)
4. Optionally pick an **expiration date** (see [Expiration](#expiration)), then confirm
5. Copy the key immediately — it is only shown once

> **Warning**
>
> Store your API key in a secrets manager or environment variable. If you lose it, revoke the old key and create a new one.

## Expiration

A key created without an expiration date never expires. To limit its lifetime,
pick a date when you create it:

* The date can be from tomorrow up to 365 days ahead.
* The key stops working during that day (UTC). After that it returns
  `401 Unauthorized`, like a revoked key.
* The key's owner gets an in-app notification before it expires.
* The expiry is fixed at creation. To extend it, create a new key and revoke
  the old one.

Keys created through `POST /api-keys` never expire.

> **Note**
>
> The expiration date chosen in Settings used to be ignored: a key created with
> one before expiry was enforced never expires, and still does not. If you relied
> on such a key expiring, revoke it and create a new one.

## Use the key

Send your API key using **either** header below. The same key works across
almost the entire API — see [endpoints that require a browser session](/api-reference#endpoints-that-require-a-browser-session)
for the exceptions, which notably include creating and listing API keys. A
key can revoke itself, and only itself.

### `X-API-Key`

```bash
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://platform.ellaworx.ai/api/environments?orgSlug=your-org"
```

### `Authorization: Bearer`

Many HTTP clients and SDKs (including OpenAI-compatible libraries) send credentials as a Bearer token by default:

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://platform.ellaworx.ai/api/environments?orgSlug=your-org"
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "YOUR_API_KEY",
  baseURL: "https://platform.ellaworx.ai/api", // use the path from the API reference for your endpoint
});
```

If you send **both** headers on the same request, `X-API-Key` takes precedence.

Missing or invalid keys return `401 Unauthorized`. A valid key used on an
endpoint that requires a browser session returns `401` as well.

A key is scoped to exactly one organization. Using it against a different
organization fails as though the organization did not exist, even if the person
who owns the key belongs to both.

By default a key acts as the user who created it. Admin-gated operations and
per-resource grants are checked against that person's access **at the time of
the request** — so demoting someone, or revoking a grant, takes effect on
their keys immediately, without needing to delete the keys.

The exception is **delegated deployment approval**, used when an integration
(Ellavox) holds one org key and records approve/deny as a named required
approver:

* Organization owners and admins can grant `deployment:approve-as` at key
  creation (`allowApproveAs` in **Settings → API Keys**). Existing keys cannot
  be upgraded; rotate the key to add the permission.
* A key with that permission **must** send `actingUserEmail` on
  approve/deny. The address is matched against this job's required approvers
  (verified Ellaworx users only). It is not a search over the rest of the
  platform.
* The decision is logged `via: ellavox`. One such key can satisfy every vote
  in a multi-approver flow — that is why the grant is opt-in and admin-only.
* The same key may send `actingUserEmail` on deploy dispatch
  (`POST /agents/deployments/dispatch`) to name the person who clicked Deploy.
  It is optional there. The address is stored on the deployment job as its
  requester and logged `via: ellavox`, and it is not looked up, so that person
  needs no Ellaworx account. That person cannot then approve the job, by any
  path; the refusal is a 403 with `data.code` `SELF_APPROVAL_NOT_ALLOWED`. If
  they are a required approver they are not asked, and if they are the only
  one, dispatch is refused with a 403 and `data.code` `NO_OTHER_APPROVER`.
* If approve answers 500 with `data.code` `APPROVAL_FINALIZE_FAILED`, the vote
  was recorded but the deployment did not start. Send the same approve request
  again to finish it.

Ordinary keys (no `deployment:approve-as`) still approve and dispatch as the key
owner when `actingUserEmail` is omitted. They may send `actingUserEmail` only
with the key owner's own address; any other address is refused with a 403.

## Rate limit

A key may make 1000 requests before it has to pause. The count starts over
only when a request arrives more than one second after the last accepted one,
so it is not a per-second allowance: a client that never leaves a one-second
gap is refused at request 1001, however slowly it sends.

A refused request returns `429 Too Many Requests`:

```json
{
  "defined": false,
  "code": "TOO_MANY_REQUESTS",
  "status": 429,
  "message": "API key rate limited",
  "data": { "code": "API_KEY_RATE_LIMITED", "retryAfterMs": 800 }
}
```

Wait `retryAfterMs` milliseconds (at most 1000) and retry. Refused requests do
not extend the wait, and after it the key has a fresh 1000 requests. A client
that sends long runs of requests should either pause for a second at least
once every 1000 requests, or handle the `429`.

> **Note**
>
> A key used to be deleted after its 1000th request, before it could reach this
> limit. Keys no longer stop working after a number of requests.

## Manage existing keys

From the **Settings → API Keys** page you can:

* **View** a list of all active keys with their names and creation dates
* **Revoke** a key you no longer need — revocation is immediate and cannot be undone

> **Note**
>
> API keys inherit the permissions of the organization they belong to. Any key for an organization can access all registries, agents, and environments within that organization.

## Security best practices

* **Rotate regularly** — create a new key and revoke the old one on a schedule that fits your security policy
* **Use one key per integration** — if a key is compromised you can revoke it without disrupting other systems
* **Never commit keys to source control** — use environment variables or a secrets manager instead
* **Restrict network access** where possible using firewall rules or allowlists

## Next steps

#### [API Reference](/api-reference)

Explore the available endpoints

#### [Creating an Account](/creating-an-account)

Set up your account and organization