> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.adid.dev/llms.txt.
> For full documentation content, see https://docs.adid.dev/llms-full.txt.

# API Key Management

API keys are the **server-to-server** authentication path. Every key is treated as **admin-equivalent** by the RBAC middleware (Pillar 13.4), so they should be protected like database credentials.

#### 13.6.1 Configuration

The platform supports a **single shared key** out-of-the-box, configured by the `API_KEY` environment variable:

```yaml
# deployments/docker/docker-compose.yml
environment:
  API_KEY: dev-api-key            # change in production
```

A multi-tenant key store with per-key rate limits is supported in the `RateLimiter` (see `middleware/ratelimit.go:133-136`):

```go
rateLimiter.SetKeyLimit("partner-acme",  500, 1000)   // 500 req/s burst 1000
rateLimiter.SetKeyLimit("partner-globex", 50, 100)
```

> **VERIFY:** confirm whether the key store is read from a config file, env var list, or a DB-backed registry.

#### 13.6.2 Calling with an API key

```bash
# Either header form is accepted
curl https://adid.dev/api/v1/dids \
  -H "X-API-Key: prod-secret-key-xxxxxxxxxx"

curl https://adid.dev/api/v1/dids \
  -H "Authorization: ApiKey prod-secret-key-xxxxxxxxxx"
```

The `auth.go:120-124` block normalises the `X-API-Key` header into `Authorization: ApiKey ...` before scheme parsing — both forms produce identical behaviour downstream.

#### 13.6.3 Operational best practices

| Practice                                                             | Rationale                                                        |
| -------------------------------------------------------------------- | ---------------------------------------------------------------- |
| Rotate `API_KEY` quarterly (or on suspected leak)                    | Limits blast radius                                              |
| Use a separate key per partner                                       | Per-key rate-limit bucket; revocation does not affect others     |
| Inject via secret manager (Vault, AWS Secrets Manager, K8s Secret)   | Avoids `.env` checked into source control                        |
| Restrict by source IP at the load balancer                           | Defence-in-depth — even a leaked key fails outside the allowlist |
| Log every API-key call with key fingerprint (sha256 of last 8 bytes) | Audit trail without storing the key in logs                      |

#### 13.6.4 What an API key cannot do

API keys do **not** automatically grant ownership of a DID or credential. When an API-key caller mutates a resource owned by a real user, the handler must:

1. Resolve the user/DID via path or query parameter.
2. Treat the API-key call as an "operator-on-behalf-of" call — log the operator key fingerprint *and* the target user.
3. Optionally enforce an allowlist of permitted target users per API key.

> **Threat:** a leaked API key bypasses RBAC entirely. **Mitigation:** alert on `auth_scheme=apikey` requests originating from new IPs (Pillar 13.7.3 audit logging).

***