# Authentication and API keys

> How the data API authenticates requests, what an API key is, and the limits you can set on it.

Page: https://docs.aggre.org/authentication · Section: Get started · All pages: https://docs.aggre.org/llms.txt

The data API (`https://api.aggre.org`) accepts **API keys only**. The accounts service behind the console (`https://accounts.aggre.org`) accepts **session cookies only** and never an API key. The two never mix.

## Sending the key {#sending-the-key}

```http
GET /v1/whoami HTTP/1.1
Host: api.aggre.org
Authorization: Bearer aggre_sk_...
```

`X-API-Key: aggre_sk_...` is accepted instead of the `Authorization` header. Every `/v1/*` route needs a key; `GET /healthz` and `GET /readyz` do not.

## What a key is {#what-a-key-is}

- The format is `aggre_sk_` followed by 43 characters of base64url (32 random bytes).
- The secret is shown **once**, when you create the key, and is never returned again. Aggre stores a SHA-256 hash and the first 8 characters after `aggre_sk_` as a non-secret display prefix; listings show only that prefix.
- A key belongs to an account: your personal account or an [organization](https://docs.aggre.org/console/organizations.md). Members with the right role manage the organization's keys ([roles](https://docs.aggre.org/console/organizations.md#roles)).
- Never put a key in client-side code, a repository, a log or a URL. Calls to the data API belong on a server or in an agent's tool configuration.

## Limits you can set {#limits}

Each key has:

| Setting | Meaning |
|---|---|
| Quota (`usage_limit`) and period (`usage_period`: `day`, `month` or `total`) | How many requests the key may make per period. Once spent, requests answer `429 usage_limit_exceeded`. |
| IP allowlist (`ip_allowlist`) | A list of CIDR ranges the key may be used from. Empty means open. Outside the list: `403 ip_not_allowed`. |
| Expiry (`expires_at`) | Optional date after which the key stops working. |
| Rate policy (`rate_policy`) | `default`. `exempt` exists for platform staff only. |

Self-service keys have a monthly allowance (the default is shown in the console when you create a key; a `day` quota counts as up to 31 times its limit against that allowance), and an account can hold at most 20 active keys. Unlimited keys, `exempt` rate policy and quotas above the default are set by platform staff.

## Revoking and rotating {#revoking}

Revoke a key in the console. Revocation reaches the API within about 30 seconds (the gateway caches keys for that long). To rotate: create the new key, deploy it, then revoke the old one.

## Usage counting {#usage}

Each request made with a key is recorded as a usage event: time, method, route template (never the raw URL or query string), dataset id, HTTP status and request id. Your IP address and query text are not stored. The count in `GET /v1/whoami` and in the console is the key's counter for its current period; it can lag a few seconds because the gateway writes counters in batches. `GET /v1/whoami` itself counts as a normal request. See [Usage and audit log](https://docs.aggre.org/console/usage.md).

## Errors you will see {#errors}

| Status | `error.code` | Cause |
|---|---|---|
| 401 | `unauthorized` | Missing, malformed, unknown or revoked key. |
| 403 | `ip_not_allowed` | The key has an allowlist and the request came from elsewhere. |
| 403 | `forbidden` | The account is disabled. |
| 429 | `rate_limited` | Per-source-IP limit, checked before the key. Retry after `Retry-After`. |
| 429 | `usage_limit_exceeded` | The key's quota is spent. Retrying will not help. |

Details: [Errors](https://docs.aggre.org/concepts/errors.md) and [Rate limits and quotas](https://docs.aggre.org/concepts/rate-limits.md).
