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

# API Keys

> Long-lived bearer credentials bound to a principal — the format, the headers that work, and where their authority actually comes from

An **API key** is a long-lived bearer credential for unattended callers: backend services, integrations, scheduled jobs. Unlike a session or a device-flow token, it does not expire on its own.

## Format

```
ak-{access_id}{secret}
```

* `ak-` marks the string as an API key.
* **Access id** — 32 hex characters, a UUID with the hyphens stripped. This is the public half; it is how the key is looked up.
* **Secret** — appended directly after, no separator. This is the half that is verified.

```
ak-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4s9t0u1v2w3x4y5z6
   |---------- access id ----------||------ secret ------|
```

An older form with a dot between the two halves is still accepted.

The secret is stored as a hash. It is shown once at creation and cannot be recovered.

## Sending one

The management API accepts an API key four ways:

```bash theme={null}
curl https://api.noorle.com/v1/agents -H "X-API-Key: $NOORLE_API_KEY"
curl https://api.noorle.com/v1/agents -H "API-Key: $NOORLE_API_KEY"
curl https://api.noorle.com/v1/agents -H "Authorization: ApiKey $NOORLE_API_KEY"
```

`Authorization: Bearer` is tried as a JWT first, then falls back to API-key validation — but prefer one of the explicit forms above.

MCP gateways and the agent gateway both accept an API key as a bearer credential, disambiguated by the `ak-` prefix.

## Where a key's authority comes from

This is the part worth internalizing.

**An API key carries no permissions of its own.** It identifies a principal, and that principal's role and grants decide what the request may do.

```mermaid theme={null}
graph LR
    K["API key"] --> P["Its principal"]
    P --> R["Account role"]
    P --> G["Explicit grants"]
    R --> D["Authorization decision"]
    G --> D
```

The practical consequence: **you scope a key by scoping the principal you attach it to.** Create a service account with a Restricted role and exactly the grants it needs, then issue its key. Issuing a key against an Owner and hoping to narrow it afterwards is not something the platform supports.

<Warning>
  There is no per-key permission list, no per-key resource scope, and no per-key rate limit. A `rate_limit` column exists on the key record but nothing reads it. Do not design around it.
</Warning>

## Lifecycle

A key record carries an optional expiry and an optional revocation timestamp. Both are checked *before* the secret is verified.

| State       | Behavior                                          |
| ----------- | ------------------------------------------------- |
| **Active**  | Accepted                                          |
| **Expired** | Rejected — set only if you gave the key an expiry |
| **Revoked** | Rejected, immediately and permanently             |

Most keys have no expiry. Revocation is the control you actually use, and it takes effect on the next request.

## Two ways to get one

**On a service account.** The recommended path for anything production. The service account is a principal you can scope with grants, name, audit, and revoke independently of any person.

**Directly in account settings.** Faster, useful for a personal script. The key is bound to your own principal, which means it carries *your* authority.

Both produce the same format and behave identically on the wire.

In the Portal: **Settings → API Keys**, and **Settings → Users** for service accounts.

## API key or device flow?

|                   | API key                                          | Device flow               |
| ----------------- | ------------------------------------------------ | ------------------------- |
| Expires           | Only if you set an expiry                        | Access token after 1 hour |
| Who it identifies | A principal you chose, usually a service account | The human who approved it |
| Needs a browser   | No                                               | Yes, once                 |
| Good for          | Unattended services                              | Interactive CLI use       |

Use a key when nobody is at the keyboard. Use the device flow when a person is, and their identity should be on the record.

## Practical guidance

* **Environment variables or a secret manager.** Never version control, never a config file you commit.
* **One key per consumer.** Shared keys cannot be revoked without breaking everything that shares them.
* **Scope the principal, not the key.** It is the only scoping that exists.
* **Revoke on suspicion.** It is instant and cheap; rotating later is neither.

## Next steps

* [Generating and managing API keys](/docs/run/platform/api-keys) — the step-by-step
* [Service accounts](/docs/run/platform/service-accounts) — the principal to attach a production key to
* [Roles and permissions](/docs/learn/auth/roles-and-permissions) — how to scope that principal
