Help us improve
Share bugs, ideas, or general feedback.
From venice
Manage Venice API keys. Covers GET/POST/PATCH/DELETE /api_keys, GET /api_keys/{id}, GET /api_keys/rate_limits, GET /api_keys/rate_limits/log, the two-step /api_keys/generate_web3_key wallet flow, INFERENCE vs ADMIN key types, and per-key consumption limits (USD / DIEM).
npx claudepluginhub veniceai/skillsHow this skill is triggered — by the user, by Claude, or both
Slash command
/venice:venice-api-keysThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Admin endpoints for managing Bearer API keys. You need an **ADMIN** key (or parent session) to call these. For wallet-only auth, use [`venice-auth`](../venice-auth/SKILL.md) / [`venice-x402`](../venice-x402/SKILL.md) instead.
Authenticate to the Venice API with a Bearer API key or with an x402 / SIWE wallet. Covers header formats, the SIWE message fields, TTL and nonce rules, the venice-x402-client SDK, and how to choose between the two modes.
Implements secure API key generation with entropy, hashed storage, rotation, revocation, scoping, rate limiting, and leak monitoring for backend services.
Guides Bankr API and CLI security: read-only keys, IP whitelisting, rate limits, dedicated agent wallets, key rotation, and transaction safety.
Share bugs, ideas, or general feedback.
Admin endpoints for managing Bearer API keys. You need an ADMIN key (or parent session) to call these. For wallet-only auth, use venice-auth / venice-x402 instead.
| Endpoint | Purpose |
|---|---|
GET /api_keys | List your keys (masked). |
POST /api_keys | Create a new key. Response contains the only copy of the secret. |
PATCH /api_keys | Update description, expiresAt, consumptionLimit. |
DELETE /api_keys?id=... | Revoke a key. |
GET /api_keys/{id} | Full details for one key (usage, limits, expiration). |
GET /api_keys/rate_limits | Balances + per-model rate-limit tiers for the current key. |
GET /api_keys/rate_limits/log | Last 50 rate-limit breaches. |
GET /api_keys/generate_web3_key | Get a SIWE-style token to sign with a wallet. |
POST /api_keys/generate_web3_key | Authenticate a wallet (holds sVVV) and mint a classic API key. |
Limits: key creation is capped at 20 requests/minute and 500 active keys per user.
| Type | Can call |
|---|---|
INFERENCE | Inference endpoints plus any route that only requires authentication — e.g. /chat/*, /image/*, /audio/*, /video/*, /embeddings, /augment/*, /crypto/rpc, /characters, /api_keys/rate_limits*, /support-bot. Rejected from admin routes listed below with 401. |
ADMIN | Everything an INFERENCE key can do, plus admin-only routes: POST/PATCH/DELETE /api_keys, GET /api_keys (list), GET /api_keys/{id}, GET /billing/balance, GET /billing/usage. |
A leaf app should almost always use INFERENCE keys — per-app, per-user, with consumption caps.
GET /api_keyscurl https://api.venice.ai/api/v1/api_keys \
-H "Authorization: Bearer $ADMIN_KEY"
Returns:
{
"object": "list",
"data": [
{
"id": "uuid",
"apiKeyType": "INFERENCE",
"description": "backend prod",
"createdAt": "2025-10-01T12:00:00Z",
"expiresAt": null,
"lastUsedAt": "2026-04-20T10:05:00Z",
"last6Chars": "2V2jNW",
"consumptionLimits": { "usd": 50, "diem": 10 },
"usage": { "trailingSevenDays": { "usd": "4.20", "diem": "0.00" } }
}
]
}
The full secret is never returned on list — only last6Chars.
POST /api_keys — createcurl https://api.venice.ai/api/v1/api_keys \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"apiKeyType": "INFERENCE",
"description": "backend prod",
"expiresAt": "2026-12-31T23:59:59Z",
"consumptionLimit": { "usd": 50, "diem": 10 }
}'
Response includes the one-time apiKey secret:
{
"success": true,
"data": {
"id": "uuid",
"apiKey": "VENICE_INFERENCE_KEY_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"apiKeyType": "INFERENCE",
"description": "backend prod",
"expiresAt": "2026-12-31T23:59:59Z",
"consumptionLimit": { "usd": 50, "diem": 10 }
}
}
Save it immediately — Venice won't show the secret again. If you lose it, delete and re-create.
apiKeyTypedescriptionexpiresAt — empty string or ISO 8601 date/datetime. Omit for non-expiring.consumptionLimit.usd / .diem — per-epoch caps. Null means no cap on that currency.consumptionLimit.vcu — deprecated (legacy Diem). Use diem instead.PATCH /api_keys — updatecurl -X PATCH https://api.venice.ai/api/v1/api_keys \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{ "id": "uuid", "description": "renamed", "consumptionLimit": { "usd": 100 } }'
Only description, expiresAt, and consumptionLimit are mutable. Pass "expiresAt": "" or null to remove an expiration.
DELETE /api_keys?id=<uuid> — revokecurl -X DELETE "https://api.venice.ai/api/v1/api_keys?id=uuid" \
-H "Authorization: Bearer $ADMIN_KEY"
Returns {"success": true}. Revocation is immediate.
GET /api_keys/{id} — detailsReturns one key's full metadata plus trailing-7-day usage. Useful for an admin dashboard row view.
GET /api_keys/rate_limitscurl https://api.venice.ai/api/v1/api_keys/rate_limits \
-H "Authorization: Bearer $VENICE_API_KEY"
Returns for the calling key:
{
"data": {
"accessPermitted": true,
"apiTier": { "id": "paid", "isCharged": true },
"balances": { "USD": 50.23, "DIEM": 100.023 },
"keyExpiration": "2025-06-01T00:00:00Z",
"nextEpochBegins": "2025-05-07T00:00:00.000Z",
"rateLimits": [
{
"apiModelId": "zai-org-glm-5-1",
"rateLimits": [
{ "type": "RPM", "amount": 100 },
{ "type": "TPM", "amount": 200000 },
{ "type": "RPD", "amount": 10000 }
]
}
]
}
}
Use it to:
GET /api_keys/rate_limits/logReturns the last 50 rate-limit breaches. Response is wrapped as { object: "list", data: [...] }:
{
"object": "list",
"data": [
{ "apiKeyId": "...", "modelId": "zai-org-glm-5-1", "rateLimitType": "RPM",
"rateLimitTier": "paid", "timestamp": "2026-04-20T12:34:56Z" }
]
}
Feed these into your monitoring when tuning concurrency.
Lets a wallet that holds sVVV mint a classic Bearer API key. No Venice account required.
GET /api_keys/generate_web3_keycurl https://api.venice.ai/api/v1/api_keys/generate_web3_key
Returns { success: true, data: { token: "<jwt-ish token>" } }.
POST /api_keys/generate_web3_keyimport { Wallet } from 'ethers'
const { data: { token } } = await fetch(`${base}/api_keys/generate_web3_key`).then(r => r.json())
const wallet = new Wallet(process.env.WALLET_KEY!)
const signature = await wallet.signMessage(token)
const res = await fetch(`${base}/api_keys/generate_web3_key`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
apiKeyType: 'INFERENCE',
description: 'Web3 API Key',
address: wallet.address,
signature,
token,
consumptionLimit: { usd: 50 },
}),
})
const { data } = await res.json()
console.log(data.apiKey) // save this once
The returned apiKey behaves exactly like a normal Bearer key.
await fetch(`${base}/api_keys`, {
method: 'POST',
headers: { Authorization: `Bearer ${ADMIN_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
apiKeyType: 'INFERENCE',
description: `cust:${customerId}`,
consumptionLimit: { usd: 5 },
}),
})
Rotate monthly; revoke on churn.
const { data } = await fetch(`${base}/api_keys/rate_limits`, {
headers: { Authorization: `Bearer ${key}` },
}).then(r => r.json())
if (!data.accessPermitted) alert('Key blocked — top up or change tier')
| Code | Meaning |
|---|---|
400 | Bad body (e.g. missing apiKeyType, malformed expiresAt), or attempting to create when you already have 500 active keys. |
401 | Missing / bad / non-admin key for admin-only routes. |
429 | Exceeded 20 creates/min. |
500 | Transient; retry. |
POST response. Losing it = delete + recreate.consumptionLimit is per epoch (day / reset cycle), not per call.INFERENCE keys can't call admin-only routes (POST/PATCH/DELETE /api_keys, GET /api_keys, GET /api_keys/{id}, GET /billing/balance, GET /billing/usage). They can call GET /api_keys/rate_limits and /api_keys/rate_limits/log for themselves. Use a separate ADMIN key for management.vcu is legacy — use diem.expiresAt of empty string "" means "no expiration" in CREATE; on UPDATE it removes an existing one.