# API key authentication

`ai-gateway-auth-v2`

Clients send the app's API key as a bearer token, and the gateway resolves the
calling app from the key. A missing or invalid key returns `401`. A valid key
whose app doesn't match the `{app_id}` in the URL returns `403`.

The policy applies per app: in an app's chain, it requires a key for that app
alone. A new top-level team's [policy template](../policy-templates.mdx)
includes it as a locked entry—and sub-teams inherit that template by default—so
apps created in the team require keys from the start.

## Options

| Option            | Default         | What it does                                                      |
| ----------------- | --------------- | ----------------------------------------------------------------- |
| `cacheTtlSeconds` | `10`            | How long the gateway caches a key check. `10` is also the minimum |
| `authHeader`      | `Authorization` | The header to read the key from                                   |
| `authScheme`      | `Bearer`        | The scheme prefix. Set it to `""` to use the raw header value     |

For clients that send `x-api-key` instead of a bearer token, use
`{ "authHeader": "x-api-key", "authScheme": "" }`.

Because key checks are cached, a revoked key can keep working until the cache
expires.

:::caution{title="A gateway without this policy is open"}

When an app's chain doesn't include the policy, the gateway resolves the app
from the `{app_id}` segment of the URL and serves the request with no key at
all. Anyone who knows the URL can spend against the app's providers and budget.
Only run an open gateway when something else, such as network isolation,
controls who can reach it.

:::

Each app's key appears on its app page—see [Apps](../apps.mdx).
