> ## Documentation Index
> Fetch the complete documentation index at: https://developers.meshapi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API Keys

> Create and manage inference keys programmatically — labels, limits, spend caps, model allow-lists, and org/team assignment.

An API key (`rsk_...`) is how your applications authenticate to MeshAPI. It is also the unit that carries **limits, spend caps, model access, and usage attribution** — so managing keys is how you control what each application is allowed to do.

This page covers the key-management API. For *using* a key to authenticate a request, see [Authentication](/docs/getting-started/authentication).

<Warning>
  Key management uses a **user JWT** — your dashboard session token — not an `rsk_` key. An inference key cannot create or modify keys, by design: a leaked key must not be able to mint more.
</Warning>

***

## Creating a key

```bash theme={null}
curl https://api.meshapi.ai/v1/keys \
  -H "Authorization: Bearer <YOUR_USER_JWT>" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "production-web",
    "rpm": 300,
    "spend_cap_usd": "50.00",
    "allowed_models": ["openai/gpt-4o-mini", "anthropic/claude-sonnet-4-5"]
  }'
```

<Warning>
  The plaintext key is returned **once**, in the `key` field of the create response, and is never retrievable again — only a hash is stored. Capture it at creation or you will have to issue a new one.
</Warning>

### Fields

| Field                                           | Purpose                                                                         |
| ----------------------------------------------- | ------------------------------------------------------------------------------- |
| `label`                                         | Human name shown in the dashboard and usage breakdowns                          |
| `default_model`                                 | Model used when a request omits `model`                                         |
| `rpm` / `rpd` / `tpm`                           | Rate limits — see [Rate Limits & Spend Caps](/docs/getting-started/rate-limits) |
| `spend_cap_usd`                                 | Cumulative USD ceiling for this key                                             |
| `allowed_models`                                | Allow-list of models this key may call                                          |
| `model_limits`                                  | Per-model overrides                                                             |
| `org_id` / `team_id`                            | Attach the key to an org or team for pooled billing and limits                  |
| `routing_policy` / `routing_policy_template_id` | Retry and fallback behaviour (mutually exclusive — sending both is a `422`)     |

`rpm` above 1,000 or `rpd` above 1,000,000 are rejected with `422`.

***

## Managing keys

| Operation                   | Endpoint                      |
| --------------------------- | ----------------------------- |
| List keys                   | `GET /v1/keys`                |
| Filter options for the list | `GET /v1/keys/filter-options` |
| Update a key                | `PATCH /v1/keys/{id}`         |
| Suspend a key               | `DELETE /v1/keys/{id}`        |
| Resolved effective limits   | `GET /v1/keys/{id}/limits`    |

<Note>
  `DELETE` is a **soft delete**: it sets the key's status to `suspended`. The key stops working at the inference layer immediately, but the record and its usage history are preserved. There is no hard-delete endpoint — this keeps historical usage attributable.
</Note>

***

## Pinning the API version

A key can carry an `api_version` — the dated contract every request made with it receives,
unless the request sends its own `X-Mesh-Version` header. Useful when the calling code is not
yours to change, or when a whole integration should sit on one version.

```bash theme={null}
curl -X PATCH https://api.meshapi.ai/v1/keys/{id} \
  -H "Authorization: Bearer <session-token>" \
  -H "Content-Type: application/json" \
  -d '{"api_version": "2026-08"}'
```

Send `null` to clear it. In the dashboard it is the key's **API Version** field. See
[API versioning](/docs/reference/api-versioning) for what a version covers and which ones are
served.

***

## Model allow-lists

`allowed_models` restricts a key to a named set of models. It is the cleanest way to stop a cheap application reaching an expensive model.

<Warning>
  An allow-list silently breaks features that route to models you didn't list:

  * **`model: "auto"`** — the Auto Router picks from your allow-list. If none of its candidates are listed, routing fails.
  * **Web search** — `/v1/web/search` checks against its own model pin. An allow-list that omits it disables web search for that key.

  Neither failure is obvious from the error. If a feature stops working right after you set an allow-list, this is why. Include the models those features depend on, or leave the key unrestricted.
</Warning>

***

## Org and team keys

Assigning `org_id` or `team_id` makes a key part of a shared structure: it draws on the **org's shared balance** and inherits the org's and team's limits, resolved minimum-wins alongside the key's own.

Attaching a `routing_policy_template_id` requires the key to belong to an org — templates are org-scoped, and a key with no org gets a `422`.

See [Organizations & Teams](/docs/getting-started/organizations) for the surrounding model.

***

## Related

* [Authentication](/docs/getting-started/authentication) — using a key to make requests
* [Rate Limits & Spend Caps](/docs/getting-started/rate-limits) — how limits resolve across tiers
* [API Versioning](/docs/reference/api-versioning) — pinning a key to a dated contract
* [Organizations & Teams](/docs/getting-started/organizations) — shared billing and pooled limits
* [Account Configuration Checklist](/docs/getting-started/account-checklist) — recommended setup pass
