# API keys

Create keys under **Settings › API keys**. Veqen stores only a hash, so a key is shown once, when it's created.

## Scopes

The dashboard calls the two scopes **Send-only** and **Full access**; the API and the docs also call send-only keys *ingest* keys.

| Scope | Can | Who creates it |
|---|---|---|
| **Send-only** (`ingest`) | Send calls (`/v1/events`, OpenTelemetry, LiteLLM), read budget status and account usage, read model volumes for `veqen diff` (Pro and up) | Members, admins and owners in the dashboard; a full-access key through the API |
| **Full access** (`full`) | Everything a send-only key can, plus nearly everything the dashboard does through the [API](/docs/api) (and much of it over [MCP](/docs/mcp)): read all spend, and manage budgets, credits, bills, prices, month-end, connections, alerts, members and send-only keys | Owners and admins, in the dashboard only |

Give every app or service its own send-only key and keep it on the server. Use full-access keys for the CLI in CI, scripts and tools that read or manage Veqen, and MCP clients that can't sign in with OAuth.

## What a full-access key can do

A full-access key acts as an **admin**, on behalf of the person who created it, for as long as that person is still an owner or admin of the organization. It can do what an admin can in the dashboard and nothing more: it can't change owners, change the plan, set up single sign-on or delete the organization. If its creator stops being an owner or admin, or their account is deleted, the key is revoked; a key with no creator left can still read, but can't change anything.

Changes made with a key appear in the [audit log](/docs/teams#audit-log) under its creator's name, marked `via: api` with the key's id (or `via: mcp` over MCP).

## Controls on a key

When you create a key, choose when it expires; the address and rate limits are under **Limit where it works and how fast**.

- **Expires** in 30 days, 90 days or a year, or never. An expired key gets `401 invalid_api_key` with a message saying it expired.
- **Only from these IP addresses.** Up to 50 IP addresses or CIDR ranges (`203.0.113.7`, `10.0.0.0/8`, IPv6 too). A call from anywhere else gets `403 forbidden_address`. An IPv4 client reaching a dual-stack listener is matched as IPv4. A range has to start at its network address: `203.0.113.7/24` is refused, so it can't quietly allow the whole `/24`.
- **At most, requests a second.** A rate cap for this key, from 0.1 to 10,000, under your organization's own limit. A key over its cap gets `429` with `Retry-After`.

Keys limited to addresses don't work with the MCP server, which can't see the caller's address; use OAuth sign-in there instead.

## Rotation

**Rotate** (or `POST /v1/keys/{id}/rotate` for a send-only key) issues a replacement with the same name, scope, addresses and cap, and the same lifetime if the old key had one. The old key keeps working for **24 hours**, so you can deploy the new one without dropping calls. A key that has already been rotated (or lapses within a day) can't be rotated again: use its replacement.

## Reminders

Once a day Veqen tells owners and admins, in one message per organization, about keys that are over 90 days old or expire within a week, at most once every 30 days per key. Keys that expire within a day, such as one you've just rotated, are left out.

## Revoking

Owners and admins can revoke any key; other members can revoke the keys they created. A full-access key can also revoke keys with `DELETE /v1/keys/{id}`. Revoking takes effect on the next request. An organization can have 50 active keys.

When an owner or admin is demoted, removed, leaves or has their account deleted, the full keys they created are revoked. Their ingest keys keep working, so production traffic isn't interrupted; revoke those too if you need to. Every create, rotate and revoke is in the [audit log](/docs/teams).
