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

# Managing API Keys

> Create, cap, track, update, and revoke Venice API keys from code with an Admin key.

An Admin key can manage all of your other API keys through the API. Give each app, environment, or customer its own Inference key, cap what each one can spend, track usage per key, and change or revoke keys without opening the dashboard.

> [card] [Create](#create-a-key)
>
> Issue a key with a spend cap

> [card] [Track](#track-usage)
>
> See what each key spends

> [card] [Change](#change-limits-and-settings)
>
> Raise a cap or extend an expiry

> [card] [Revoke](#revoke-or-rotate-a-key)
>
> Shut a key off right away

## How it works

Admin key
Your control key
Creates, changes, and revokes keys
Reads usage and billing
Stays on your server

Inference
cust:acme

\$50 / month
Private models only

Inference
cust:globex

\$5 / month
Only from 11.22.33.0/24

Inference
staging

\$10 / day
Expires Jun 30

Admin keys can call every endpoint, including the ones that manage keys and read billing. Inference keys can call models but can't manage keys or read billing, so they're the keys you hand out.

| | Admin | Inference |
| - | :-: | :-: |
| Call models and other inference endpoints | ✓ | ✓ |
| Check its own balance and rate limits (`GET /api_keys/rate_limits`) | ✓ | ✓ |
| Create, update, and revoke keys (`/api_keys`) | ✓ | |
| Read usage and billing (`/billing/*`) | ✓ | |

> [!NOTE]
>
> Create your first Admin key in the dashboard: follow [Generating an API Key](https://docs.venice.ai/guides/getting-started/generating-api-key.md) and choose **Admin** as the key type. Keep it in a server-side secret store, never in client code.

The examples on this page read the Admin key from `VENICE_ADMIN_KEY`:

```bash cURL theme={"system"}
export VENICE_ADMIN_KEY="your-admin-key"
```

```python Python theme={"system"}
import os
import requests

BASE = "https://api.venice.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['VENICE_ADMIN_KEY']}"}
```

```javascript Node.js theme={"system"}
const BASE = "https://api.venice.ai/api/v1";
const headers = {
  Authorization: `Bearer ${process.env.VENICE_ADMIN_KEY}`,
  "Content-Type": "application/json",
};
```

## Create a key

This creates an Inference key for one customer, capped at \$50 a month and expiring on June 30, 2027:

```bash cURL theme={"system"}
curl https://api.venice.ai/api/v1/api_keys \
  -H "Authorization: Bearer $VENICE_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "apiKeyType": "INFERENCE",
    "description": "cust:acme",
    "consumptionLimit": { "usd": 50 },
    "limitPeriod": "MONTH",
    "expiresAt": "2027-06-30"
  }'
```

```python Python theme={"system"}
resp = requests.post(f"{BASE}/api_keys", headers=HEADERS, json={
    "apiKeyType": "INFERENCE",
    "description": "cust:acme",
    "consumptionLimit": {"usd": 50},
    "limitPeriod": "MONTH",
    "expiresAt": "2027-06-30",
})
resp.raise_for_status()
key = resp.json()["data"]
key_id, secret = key["id"], key["apiKey"]
```

```javascript Node.js theme={"system"}
const res = await fetch(`${BASE}/api_keys`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    apiKeyType: "INFERENCE",
    description: "cust:acme",
    consumptionLimit: { usd: 50 },
    limitPeriod: "MONTH",
    expiresAt: "2027-06-30",
  }),
});
const { data: key } = await res.json();
const { id: keyId, apiKey: secret } = key;
```

```json Response theme={"system"}
{
  "success": true,
  "data": {
    "id": "e28e82dc-9df2-4b47-b726-d0a222ef2ab5",
    "apiKey": "VENICE_INFERENCE_KEY_...",
    "apiKeyType": "INFERENCE",
    "description": "cust:acme",
    "consumptionLimit": { "usd": 50, "vcu": null, "diem": null },
    "limitPeriod": "MONTH",
    "modelPrivacy": "ALL",
    "expiresAt": "2027-06-30T00:00:00.000Z",
    "ipAllowlist": []
  }
}
```

> [!WARNING]
>
> `data.apiKey` is the key's secret, and this response is the only time you'll see it. Store it right away. If it's lost, revoke the key and create a new one. Keep `data.id` too: every other call on this page uses it.

### Key settings

Set these when you create a key, or change them later with `PATCH /api_keys`. The request body is strict, so an unknown field returns `400`.

| Field | Values | What it does |
| - | - | - |
| `apiKeyType` | `INFERENCE` or `ADMIN` | Required on create. It can't be changed later. |
| `description` | Up to 64 characters | Required on create. Usage analytics labels the key with it, so put your own identifier here, like `cust:acme`. |
| `consumptionLimit` | `{ "usd": 50 }` | Spend cap for each `limitPeriod`, in `usd`, `diem`, or both. Leave a currency out, or set it to `null`, for no cap. The USD cap counts USD, bundled credits, and earned credits together. |
| `limitPeriod` | `EPOCH`, `MONTH`, `LIFETIME` | When the cap resets. `EPOCH`, the default, resets daily at 00:00 UTC, `MONTH` on the 1st of each month (UTC), and `LIFETIME` never. |
| `expiresAt` | `"2027-06-30"` | A date, or a UTC time like `"2027-06-30T23:59:59Z"`. A date on its own means 00:00 UTC on that day. Leave it out for a key that never expires. |
| `modelPrivacy` | `ALL`, `PRIVATE_TEXT`, `PRIVATE_ONLY` | `ALL`, the default, allows any model. `PRIVATE_TEXT` requires Private, TEE, or E2EE text and embedding models. `PRIVATE_ONLY` requires that for every model. |
| `ipAllowlist` | `["11.22.33.0/24"]` | Up to 100 public IPv4 or IPv6 addresses or CIDR ranges. An empty list allows any IP. |

You can create up to 20 keys a minute and keep up to 500 active keys. Contact support if you need more.

> [!TIP]
>
> Building an agent? A wallet holding staked VVV on Base can mint its own key without a Venice account. See [Autonomous Agent API Key Creation](https://docs.venice.ai/guides/integrations/generating-api-key-agent.md).

## Track usage

| To find out | Call | Read |
| - | - | - |
| What one key has spent this period | `GET /api_keys/{id}` | `currentPeriodUsage` |
| What each key spent in the last 7 days | `GET /api_keys` | `usage.trailingSevenDays` |
| Spend per key, by day | `GET /billing/usage-analytics` | `byKey`, `byKeyDaily` |
| Every charge, with the key it was billed to | `GET /billing/usage-history` | `apiKeyId` |
| Whether a key can spend right now | `GET /api_keys/rate_limits`, called with that key | `accessPermitted`, `balances` |
| Which keys are hitting rate limits | `GET /api_keys/rate_limits/log` | `apiKeyId`, `modelId` |

### One key

```bash cURL theme={"system"}
curl https://api.venice.ai/api/v1/api_keys/e28e82dc-9df2-4b47-b726-d0a222ef2ab5 \
  -H "Authorization: Bearer $VENICE_ADMIN_KEY"
```

```python Python theme={"system"}
key = requests.get(f"{BASE}/api_keys/{key_id}", headers=HEADERS).json()["data"]
```

```javascript Node.js theme={"system"}
const res = await fetch(`${BASE}/api_keys/${keyId}`, { headers });
const { data: key } = await res.json();
```

```json Response (trimmed) theme={"system"}
{
  "data": {
    "id": "e28e82dc-9df2-4b47-b726-d0a222ef2ab5",
    "description": "cust:acme",
    "consumptionLimits": { "usd": 50, "diem": null, "vcu": null },
    "limitPeriod": "MONTH",
    "currentPeriodUsage": { "usd": "12.5000", "diem": "0.0000" },
    "usage": { "trailingSevenDays": { "usd": "4.2000", "diem": "0.0000", "vcu": "0.0000" } },
    "lastUsedAt": "2026-11-03T14:05:00.000Z"
  }
}
```

This key has used $12.50 of its $50 for the month. `currentPeriodUsage` only appears on keys with a USD or DIEM cap, and usage amounts are strings with four decimal places. Responses return `consumptionLimits` (plural), while requests send `consumptionLimit` (singular).

### Spend per key over time

`GET /billing/usage-analytics` returns totals per key in `byKey` and one row per day in `byKeyDaily`, ready to chart. Pass `lookback` (`7d` by default, up to `90d`) or a `startDate` and `endDate` pair that spans up to 90 days. Results are cached for 10 minutes.

```bash cURL theme={"system"}
curl "https://api.venice.ai/api/v1/billing/usage-analytics?lookback=30d" \
  -H "Authorization: Bearer $VENICE_ADMIN_KEY"
```

```json Response (trimmed) theme={"system"}
{
  "byKey": [
    {
      "apiKeyId": "e28e82dc-9df2-4b47-b726-d0a222ef2ab5",
      "description": "cust:acme",
      "totalUsd": 12.5,
      "totalDiem": 0,
      "totalUnits": 1830000
    }
  ]
}
```

### Every charge, per key

`GET /billing/usage-history` lists every charge, and each entry carries the `apiKeyId` it was billed to. Use it to reconcile spend or bill your own customers. Entries come back oldest first. Send `nextCursor` back as `cursor`, on its own, until it's `null`. Send `Accept: text/csv` to get CSV instead.

```bash cURL theme={"system"}
curl -G https://api.venice.ai/api/v1/billing/usage-history \
  -H "Authorization: Bearer $VENICE_ADMIN_KEY" \
  --data-urlencode "startTimestamp=2026-10-01T00:00:00Z" \
  --data-urlencode "endTimestamp=2026-11-01T00:00:00Z"
```

```python Python theme={"system"}
from collections import defaultdict

spend = defaultdict(float)
params = {"startTimestamp": "2026-10-01T00:00:00Z", "endTimestamp": "2026-11-01T00:00:00Z"}
while True:
    page = requests.get(f"{BASE}/billing/usage-history", headers=HEADERS, params=params).json()
    for entry in page["data"]:
        if entry["apiKeyId"]:
            spend[(entry["apiKeyId"], entry["currency"])] -= entry["amount"]
    if page["nextCursor"] is None:
        break
    params = {"cursor": page["nextCursor"]}
```

Charges have a negative `amount`, so the loop subtracts it to get a positive total per key and currency. Entries without an `apiKeyId` come from the Venice web app, or are account entries such as credit purchases.

### Whether a key can spend right now

`GET /api_keys/rate_limits` works with any key and reports on the key that calls it. `accessPermitted` says whether the key can spend right now, and `balances` shows what it has left to spend.

```bash cURL theme={"system"}
curl https://api.venice.ai/api/v1/api_keys/rate_limits \
  -H "Authorization: Bearer $VENICE_API_KEY"
```

`GET /api_keys/rate_limits/log`, with an Admin key, returns your last 50 rate-limit hits, each with its `apiKeyId` and `modelId`.

## Change limits and settings

Send the key's `id` and only the fields you want to change. Everything else stays as it is. This raises the cap to \$100 a month:

```bash cURL theme={"system"}
curl -X PATCH https://api.venice.ai/api/v1/api_keys \
  -H "Authorization: Bearer $VENICE_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "e28e82dc-9df2-4b47-b726-d0a222ef2ab5",
    "consumptionLimit": { "usd": 100 }
  }'
```

```python Python theme={"system"}
requests.patch(f"{BASE}/api_keys", headers=HEADERS, json={
    "id": key_id,
    "consumptionLimit": {"usd": 100},
}).raise_for_status()
```

```javascript Node.js theme={"system"}
await fetch(`${BASE}/api_keys`, {
  method: "PATCH",
  headers,
  body: JSON.stringify({ id: keyId, consumptionLimit: { usd: 100 } }),
});
```

Send any of these fields instead to make other changes:

| To | Send |
| - | - |
| Remove the cap | `"consumptionLimit": { "usd": null }` |
| Reset the cap monthly instead of daily | `"limitPeriod": "MONTH"` |
| Make the cap a one-time budget | `"limitPeriod": "LIFETIME"` |
| Extend the expiry | `"expiresAt": "2027-12-31"` |
| Remove the expiry | `"expiresAt": null` |
| Only accept requests from your servers | `"ipAllowlist": ["11.22.33.0/24"]` |
| Accept requests from any IP again | `"ipAllowlist": []` |
| Allow only private models | `"modelPrivacy": "PRIVATE_ONLY"` |
| Rename the key | `"description": "cust:acme-prod"` |

A new `limitPeriod` applies right away, so switching to `LIFETIME` counts all of the key's past spend against the cap. `apiKeyType` can't be changed; create a new key instead.

## Revoke or rotate a key

```bash cURL theme={"system"}
curl -X DELETE \
  "https://api.venice.ai/api/v1/api_keys?id=e28e82dc-9df2-4b47-b726-d0a222ef2ab5" \
  -H "Authorization: Bearer $VENICE_ADMIN_KEY"
```

```python Python theme={"system"}
requests.delete(f"{BASE}/api_keys", headers=HEADERS, params={"id": key_id}).raise_for_status()
```

```javascript Node.js theme={"system"}
await fetch(`${BASE}/api_keys?id=${keyId}`, { method: "DELETE", headers });
```

The response is `{ "success": true }`. Revocation is immediate: the key's next request gets `401 Authentication failed`, and the key drops out of `GET /api_keys`. Its past charges stay in usage history.

To rotate a key without downtime:

**1. Create the replacement**

Create a new key with the same settings and store its secret.

**2. Deploy it**

Switch your app over to the new secret.

**3. Revoke the old key**

Once the old key's `lastUsedAt` in `GET /api_keys` stops moving, delete it.

## Errors your callers may see

| Status | Message | What to do |
| - | - | - |
| `402` | `API key USD spend limit exceeded...`, or the same for DIEM | Raise or remove the cap, or wait for the next period. The account itself may still have funds. |
| `403` | The model isn't allowed by the key's privacy setting | Use a Private, TEE, or E2EE model, or change `modelPrivacy`. |
| `403` | `This API key is restricted to configured IP addresses...` | Add the caller's IP to `ipAllowlist`. |
| `401` | `Authentication failed` | The key is revoked, expired, or mistyped. |
| `401` | `Admin API key required` | An Inference key called a key management or billing endpoint. |
| `429` | `Too many API key creation requests...` | Key creation is limited to 20 a minute. Wait, then retry. |
| `400` | `Maximum number of active API keys (500) reached...` | Revoke keys you no longer use, or contact support. |

See [Error Codes](https://docs.venice.ai/api-reference/error-codes.md) for the full list.

## Best practices

* Keep Admin keys on your server, and hand out only Inference keys.
* Give every app, environment, and customer its own key, so each one can be tracked and revoked on its own.
* Put your own identifier in `description`. Usage analytics labels keys with it.
* Cap and expire every key you give to someone else, and lock server-to-server keys to your IPs with `ipAllowlist`.

## API reference

> [card] [Create API Key](https://docs.venice.ai/api-reference/endpoint/api_keys/create.md)
>
> All fields accepted on create.

> [card] [Update API Key](https://docs.venice.ai/api-reference/endpoint/api_keys/update.md)
>
> Change limits, expiry, privacy, and IPs.

> [card] [List API Keys](https://docs.venice.ai/api-reference/endpoint/api_keys/list.md)
>
> Every active key with its usage.

> [card] [Delete API Key](https://docs.venice.ai/api-reference/endpoint/api_keys/delete.md)
>
> Revoke a key.

> [card] [Usage Analytics](https://docs.venice.ai/api-reference/endpoint/billing/usage-analytics.md)
>
> Spend by key, model, and day.

> [card] [Usage History](https://docs.venice.ai/api-reference/endpoint/billing/usage-history.md)
>
> Every charge, with its API key.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.