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

# API Keys

> Lifecycle, rotation, and revocation of server-to-server API keys.

API keys authenticate **server-to-server** calls. Pass the secret in the `x-api-key` header. Keys can browse the public catalog but **cannot** acquire streams or read user libraries — for those, use OAuth (see [Authentication](/usage-auth)).

## Lifecycle

```
CreateApiKey ──> active ──┬──> RotateApiKey ──> active (new secret)
                          │                      │
                          │                      └──> old secret valid during grace period
                          │
                          └──> RevokeApiKey ──> permanently dead
```

## Creating

```ts theme={null}
const res = await developer.createApiKey({
  name: "my-server-staging",
  scopes: ["read"],
});
console.log(res.apiKey.id, res.secret); // ← copy `secret` now; you'll never see it again
```

The secret is returned **once** in the create response. Store it in your secret manager immediately. `ListApiKeys` and `GetApiKey` only return the `key_prefix` (first \~8 chars) for identification — never the full secret.

## Rotating

Rotate when you suspect leakage, before a teammate offboards, or on a regular schedule.

```ts theme={null}
const res = await developer.rotateApiKey({ id: "key_123" });
console.log(res.secret); // ← new secret, returned once
```

The **old secret remains valid for a server-defined grace period** (typically minutes to hours) so you can roll your servers without downtime. After grace expires, the old secret is dead.

Rotation strategy:

1. Call `RotateApiKey` and capture the new secret.
2. Roll the new secret through your config system.
3. Wait for all your servers to be using the new secret.
4. The old secret expires automatically at the end of the grace window.

## Revoking

```ts theme={null}
await developer.revokeApiKey({ id: "key_123" });
```

**Irreversible.** Revoke immediately on any sign of compromise. There is no recovery — generate a new key with `CreateApiKey`.

## Naming and hygiene

* Use one key per environment (`my-app-prod`, `my-app-staging`, `my-app-ci`). Don't share.
* Prefix names with a clear owner so `ListApiKeys` is auditable.
* Rotate on a schedule (90 days is a reasonable default).
* Never log full secrets. The `key_prefix` is safe to log for correlation.
* Never check secrets into git. The portal enforces single-fetch by design — if you need the secret again, rotate.

## Errors

* `ERROR_CODE_NOT_FOUND` on rotate/revoke — the key ID doesn't exist or you don't own it.
* `ERROR_CODE_CONFLICT` on revoke — the key is already revoked.
* `ERROR_CODE_PERMISSION_DENIED` on any developer call — your OAuth token isn't authenticated as the key's owner.
