# API keys

> Create, limit, inspect, rotate and revoke the inference keys that authenticate model requests.

Source: https://0.0.0.0:3000/docs/account/api-keys
Documentation index: https://0.0.0.0:3000/docs/llms.txt

An inference key authenticates requests to the compatible API. It belongs to one account, is charged in one permanent currency, and can carry its own spending limit.

Numes has two kinds of key:

| Kind | Can call | Created in |
| --- | --- | --- |
| **Inference** | Models, chat, embeddings, media, `GET /key`, `GET /generation` | Dashboard, or the API with a management key |
| **Management** | `GET /key`, the key-management endpoints and `GET /credits` | Dashboard only |

This page covers inference keys. For management keys, see [Management keys](/docs/account/management-keys).

## Create a key in the dashboard

:::steps
### Open Keys

Sign in, choose the account the key should belong to in the account switcher, and open [Keys](/dashboard/keys). Choose **Create key**.

### Fill in the form

| Field | What it does |
| --- | --- |
| **Name** | A label for you, 1–100 characters, such as `production-backend`. You can rename the key later. |
| **Type** | **Inference** runs models, billed to the account balance. **Management** manages keys through the API and can't run models. |
| **Currency** | **USD** or **BTC**, when your account has both. Permanent: the key is always charged in this currency. |
| **Spend limit** | An exact amount in the key's currency. Leave it empty for no limit. |
| **Limit resets** | **No reset**, **Daily**, **Weekly** or **Monthly**. With **No reset**, the limit is a lifetime total. |

### Save the secret

Choose **Create key**. The **Save this key now** dialog shows the full secret once. Copy it into your secret manager or an environment variable, then choose **I saved it**. The secret can't be recovered after the dialog closes; if you lose it, create a new key.

```bash
export NUMES_API_KEY="sk-..."
```
:::

The list shows each key's name, masked label, type, **Usage** in the current window, **Limit** and **Status** (**Active** or **Disabled**, plus the expiry date when one is set).

:::note Keys managed by Chat
Using [Chat](/chat) adds a key marked **Managed by Chat** for each currency you chat in. It pays for your chats and has no secret you can copy. You can set its spending limit, disable it and enable it again, but you can't rename or delete it. It doesn't appear in the [Management API](/docs/account/management-keys) key list.
:::

## The billing currency is permanent

Each inference key is charged in one currency, chosen at creation:

- Prices from [`GET /models`](/docs/api-reference/models/list-models), `usage.cost` and `provider.max_price` are in the key's currency. For BTC keys, `1` is one sat.
- Only offers priced in that currency are eligible. There's no conversion between USD and BTC and no fallback to the other balance.

To spend both balances, create one key per currency. See [Bitcoin payments](/docs/account/bitcoin) for BTC keys.

## Spending limits

A key's limit caps what that key can spend. It counts settled spend plus the funds held for requests still running. When the next request would exceed it, the API returns `402` `insufficient_credits`, the same response as an empty balance. Compare `limit_remaining` from [`GET /key`](#inspect-the-current-key) with your balance in [Billing](/dashboard/billing) to tell them apart.

| Period | Resets at |
| --- | --- |
| Daily | 00:00 UTC every day |
| Weekly | 00:00 UTC every Monday |
| Monthly | 00:00 UTC on the first day of the month |
| No reset | Never; the limit is a lifetime total |

Key limits apply alongside the account-wide [spending limit](/docs/account/credits#spending-limits) for each currency. Whichever is reached first stops new requests.

## Expiry

You can set an expiry only when you create a key through the API with a [management key](/docs/account/management-keys) (`expires_at`). The dashboard shows **Expires** or **Expired** with the date. An expired key returns `401` and can't be extended; create a replacement.

## Key format

A key is a prefix followed by 64 lowercase hexadecimal characters. Inference keys start with `sk-` and management keys with `mk-`, for example `sk-example-v1-`. Don't parse keys beyond that.

Every key also has two non-secret identifiers:

- a **label**: the prefix plus the first and last four hex characters, for example `sk-example-v1-3f9a...c21d`;
- a **hash**: the SHA-256 hex digest of the full key. The management endpoints address keys by this value, and you can compute it from a leaked key to disable it.

## Inspect the current key

Call `GET /key` with any inference or management key to read its metadata, limit and spend.

```endpoint
GET /api/v1/key
```

```request
{
  "method": "GET",
  "path": "/key"
}
```

```json title="Response"
{
  "data": {
    "hash": "3b7c9e1f5a2d4c6e8f0a1b3c5d7e9f1a2b4c6d8e0f1a3b5c7d9e1f2a4b6c8d0e",
    "label": "sk-example-v1-3f9a...c21d",
    "name": "production-backend",
    "billing_currency": "USD",
    "disabled": false,
    "limit": 100,
    "limit_remaining": 58.231907,
    "limit_reset": "monthly",
    "usage": 311.402116,
    "usage_daily": 3.120044,
    "usage_weekly": 12.874511,
    "usage_monthly": 41.768093,
    "created_at": "2026-07-01T09:12:44Z",
    "updated_at": "2026-09-02T16:40:03Z",
    "expires_at": null,
    "is_management_key": false
  }
}
```

:::fields Response `data`
- `hash` `string` — Non-secret identifier of the key. Use it with the management endpoints.
- `label` `string` — Masked display label. Safe to log.
- `name` `string` — The key's name.
- `billing_currency` `string` — `USD` or `BTC`. Omitted for management keys.
- `disabled` `boolean` — `true` when the key is disabled and can't authenticate.
- `limit` `number | null` — Spending limit in the key's currency, or `null` for no limit.
- `limit_remaining` `number | null` — `limit` minus settled spend in the current reset window (lifetime spend when there's no reset), never below `0`. `null` when there's no limit.
- `limit_reset` `string | null` — `daily`, `weekly`, `monthly`, or `null` for a lifetime limit.
- `usage` `number` — Settled spend over the key's lifetime.
- `usage_daily` `number` — Settled spend since 00:00 UTC today.
- `usage_weekly` `number` — Settled spend since 00:00 UTC on Monday.
- `usage_monthly` `number` — Settled spend since 00:00 UTC on the first of the month.
- `created_at` `string` — Creation time.
- `updated_at` `string | null` — Last change to name, state or limit; `null` if never changed.
- `expires_at` `string | null` — Expiry time, or `null`.
- `is_management_key` `boolean` — `true` for a management key.
:::

Money values are exact decimals written as JSON numbers; parse them as decimals. For BTC keys they're in sats.

:::note limit_remaining counts settled spend only
Requests still running hold funds that also count toward the limit, so a request can get `402` while `limit_remaining` is above zero. See [Reservations](/docs/account/credits#reservations).
:::

## Why a key is rejected

Every authentication failure returns `401` `invalid_credentials` with the same message, so the response doesn't reveal which check failed. Check these causes:

| Cause | What to do |
| --- | --- |
| Missing or malformed `Authorization` header | Send exactly `Authorization: Bearer <key>` |
| Wrong key kind | Use an inference key for models, a management key for `/keys` and `/credits` |
| Key disabled | Enable it in [Keys](/dashboard/keys) or with `PATCH /keys/{hash}` |
| Key deleted or expired | Create a new key |
| Account closed | Use a key from an active account |
| Creator removed from the organization or suspended | An owner or administrator issues a new key |

Repeated failed authentications are throttled with `429` `rate_limited`; wait for `Retry-After`. Don't retry a key that returned `401`.

## Disable, delete and rotate

**Disable** is a reversible stop. Choose **Disable** in the key's menu; requests get `401` until you choose **Enable**.

**Delete** permanently revokes the key. Clients using it stop authenticating immediately, and the key can't be restored. Past usage stays in [Activity](/dashboard/activity) and [Logs](/dashboard/logs).

Requests already running when you disable or delete a key still finish and are charged.

To rotate a key without downtime:

:::steps
### Create the replacement

Create a new key with the same currency and limit, in the dashboard or with `POST /keys`.

### Deploy it

Update your secret store and roll out the new key. Call `GET /key` from each environment and check the returned `name` or `label`.

### Revoke the old key

When traffic on the old key stops in [Activity](/dashboard/activity) (filter by API key), delete it. If you suspect a leak, disable it first.
:::

To automate rotation, see [Management keys](/docs/account/management-keys#rotate-a-key).

## Who can see which keys

In a personal account you see all keys. In an organization:

- **Owners** and **administrators** see and manage every key.
- Other members see and manage only the keys they created.

A key stops working when its creator is removed from the organization or their account is suspended. If a suspended person is restored, their keys work again, except keys that were deleted, disabled or have expired. See [Organizations](/docs/account/organizations).

## Best practices

- **One key per application and environment.** You get separate limits, separate Activity breakdowns and a smaller blast radius if one leaks.
- **Keep keys server-side.** Never ship a key in browser or mobile code. The API rejects browser requests from third-party origins with `403` `cors_forbidden`.
- **Never put a key in a URL.** The API accepts keys only in the `Authorization` header.
- **Set a limit on every key.** A monthly limit bounds the cost of a bug or a leak.
- **Log the `label` or `hash`, never the secret.** When contacting support, quote the `X-Request-Id` response header.
- **Use expiring keys for temporary access.** Create them with `expires_at` through the management API.

## Next steps

:::cards
- {key} [Management keys](/docs/account/management-keys) Create, limit and revoke inference keys from code.
- {coins} [Credits and payments](/docs/account/credits) Fund the balance your keys spend.
- {receipt} [Usage accounting](/docs/account/usage-accounting) How each request is measured and charged.
- {building} [Organizations](/docs/account/organizations) Share an account and its keys with a team.
- {lock} [Authentication](/docs/api-reference/authentication) Headers, key kinds and authentication errors.
:::
