Virtual Keys
A virtual key is a safe stand-in for a real provider API key. Your application carries a short, opaque slug (like vk-1a2b3c4d5e6f7a8b) instead of a secret — and VectorAxis swaps in the real credential at request time. It’s the single place to store keys securely, cap spend, throttle usage, and switch providers, without ever exposing a raw key to your code.
- Secrets stay out of your app. The real provider key lives encrypted in the vault; your code only ever sees the slug. Rotate or revoke the underlying key without redeploying.
- Budgets & guardrails per key. Give each team, customer, or environment its own key with its own spend cap and rate limits — so a runaway script can’t blow the bill.
- One slug, many controls. Restrict which models a key may use, set an expiry, attach metadata for reporting, and watch usage — all on the key, no app changes.
- Provider freedom. Each key points at a provider of your choice (OpenAI, Anthropic, and more), or lets the platform supply access on your behalf.
| Mode | What it means |
|---|---|
| BYOK | Bring Your Own Key. You provide your provider’s API key; VectorAxis encrypts and stores it, then uses it for this key’s requests. You’re billed by the provider directly. |
| PLATFORM | VectorAxis supplies provider access from its own accounts and draws down a prepaid credit balance you top up. No provider account needed. See Platform Keys. |
Most providers take a single API key. Google Vertex AI is the exception: its credential is a service-account JSON plus a project and region, which the key stores alongside the secret.
Slugs follow the format vk-{16 hex characters}. Use the slug anywhere you’d normally put an API key:
- As the api_key in any OpenAI-compatible SDK — it travels as Authorization: Bearer vk-… and resolves to your real credential.
- Or on the x-virtual-key header of a direct API call.
from openai import OpenAI
client = OpenAI(
base_url="https://api.vectoraxis.ai/v1",
api_key="vk-1a2b3c4d5e6f7a8b", # the virtual key slug — not a real provider key
)
client.chat.completions.create(model="gpt-4o-mini", messages=[...])Lifecycle states
Every key is always in one of four states. This is what decides whether a request is allowed through.
| State | What it means | Moves to |
|---|---|---|
| ACTIVE | Working normally — requests are served. | DISABLED, EXHAUSTED, or EXPIRED |
| DISABLED | Manually paused (e.g. you suspect it leaked). Requests are refused. | back to ACTIVE when you re-enable it |
| EXHAUSTED | Hit its spend cap. Requests are refused until budget frees up. | back to ACTIVE when the credit counter resets |
| EXPIRED | Past its expiry date. Terminal — it can’t be reactivated. | — |
Rate limits — throttle usage
Cap how fast a key can be used so one team or script can’t starve everyone else or trip a provider’s limits. A request over the limit is refused with 429 Too Many Requests. Leave a limit unset to not enforce it.
| Field | What it does | Accepted values | Default |
|---|---|---|---|
| rate_limit_rpm | Requests per minute. Checked before the call; the request over the limit is rejected. | a whole number of requests | unlimited |
| rate_limit_rpd | Requests per day (resets at midnight UTC). Checked before the call. | a whole number of requests | unlimited |
| rate_limit_tpm | Tokens per minute. Checked after each call (tokens are only known once the model responds), so it caps sustained throughput. | a whole number of tokens | unlimited |
Credit budgets — cap spend
Put a hard dollar ceiling on a key. VectorAxis tracks the running cost of every request against the cap; when it’s reached, the key flips to EXHAUSTED and further requests are refused — so a bug or abuse can’t run up an unbounded bill.
| Field | What it does | Accepted values | Default |
|---|---|---|---|
| credit_limit_usd | The spend ceiling. Reaching it moves the key to EXHAUSTED. | a dollar amount | no cap |
| credit_alert_threshold_usd | A softer line that raises a warning (not a block) when spend crosses it — an early heads-up before the cap. | a dollar amount | no alert |
| credit_reset_policy | Whether (and how often) the spend counter resets, restoring an exhausted key to ACTIVE. | MONTHLY / WEEKLY / NEVER | NEVER |
What a key may do, and how it’s labelled
| Field | What it does | Accepted values | Default |
|---|---|---|---|
| model_allowlist | Limit the key to specific models. A request for any other model is rejected before it reaches the provider. | a list of model ids | any model the provider supports |
| provider_whitelist | Limit which providers the key may reach. | a list of provider ids | the key’s own provider(s) |
| expires_at | An automatic end date; after it, the key becomes EXPIRED (terminal). | a date/time | never expires |
| note | A free-text description for humans — what the key is for. | any text | empty |
| metadata | Your own key/value tags, echoed into logs and analytics for grouping and cost attribution. | flat key→value pairs | none |
Moving & auditing keys
- Transfer between workspaces. Move a key — and its remaining credit balance — to another workspace in the same organization with POST /v1/virtual-keys/{slug}/transfer. Requires a workspace (or org) admin; an expired key can’t be moved.
- Full audit trail. Every change to a key — create, update, disable, enable, delete — is recorded with who did it and when, so you always have a history for security and compliance reviews.