Control plane API
BYOK provider keys
Store your own upstream provider API key so i2 calls that provider under your account instead of ours.
By default, i2 serves your requests from its own capacity and its own provider accounts, and bills you at i2's published rates. BYOK (bring your own key) changes that for one provider at a time: store your key here and the gateway calls that provider under your account and your billing relationship.
One key per provider, per organisation. Setting a second one for the same provider replaces the first, so a rotation is a single call with nothing to delete first.
Everything below requires a session cookie (Auth endpoints) and acts on your own organisation. There is no cross-organisation parameter.
Supported providers
provider | Resolves today |
|---|---|
anthropic | Yes. Anthropic routes call your account when a key is stored. |
openai | Stored and encrypted; no i2 route resolves from it yet. |
deepinfra | Stored and encrypted; no i2 route resolves from it yet. |
vertex | Stored and encrypted; no i2 route resolves from it yet. |
Any other value is rejected 400, naming the valid set. Storing a key against one of the last three is accepted and changes nothing about how your requests are served or billed until routes for it land.
POST /vault/keys
Sets or rotates the key for one provider.
{"provider": "anthropic", "api_key": "sk-ant-…"}{"status": "success", "provider": "anthropic", "key_suffix": "ey-value", "is_active": true}api_key must be non-blank after stripping, or 400.
key_suffix is the last 8 characters of the key you sent, in plaintext, so you can tell which credential is loaded. It cannot authenticate anything on its own. The key itself is never returned again by this or any other endpoint, so treat this response as confirmation and not as storage.
GET /vault/keys
{
"vault_keys": [
{"provider": "anthropic", "key_suffix": "ey-value", "is_active": true, "created_at": "2026-08-30T10:00:00+00:00"}
]
}Only your organisation's entries. The stored secret is never selected, let alone returned.
DELETE /vault/keys/{provider}
No body. Removes the key for that provider; the gateway stops resolving a BYOK credential on its very next lookup, and requests fall back to i2's own capacity at i2's published rates.
{"status": "deleted", "provider": "anthropic"}Repeating the call, or naming a provider you never set a key for, both return 404 rather than a silent success.
How the key is held
- Encrypted at rest with AES-256-GCM, and never read from durable storage on the request path.
- Not readable by anyone, including i2 staff and the dashboard. Every endpoint returns the 8-character suffix and nothing more. If you lose the key, rotate it at the provider and store the new one; it cannot be recovered from here.
- Effective immediately, in both directions. Storing takes effect on the gateway's next lookup, and so does removing. There is no cache to wait out.
What changes when a key is stored
- Requests on routes that resolve from that provider are made under your upstream account, so they appear in that provider's own dashboard and on that provider's own bill.
- i2's per-token rates no longer apply to those requests. Your organisation's i2 budget is not drawn down for the upstream cost of a BYOK-served request.
- Everything else is unchanged: the same route ids, the same request logs, the same key scoping and rate limits.
Calling Anthropic through i2
Anthropic's native Messages API is served at POST /v1/messages on the same host as everything else, and the call has the same signature as any other on the platform: your i2 key, the i2 host. The one addition is Anthropic's own anthropic-version header, which the gateway passes through unchanged.
The model is Anthropic's own id rather than an i2 route alias. This path resolves against the provider, so the catalogue does not list it and any model Anthropic publishes can go in that field.
export I2_BASE_URL=https://api.intelligentinference.ai
export I2_API_KEY=your_key_here
curl "$I2_BASE_URL/v1/messages" \
-H "Authorization: Bearer $I2_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 200,
"messages": [{ "role": "user", "content": "Hello" }],
"stream": true
}'Anthropic's own SDKs work unchanged apart from the client constructor. Point base_url at the host root, not at /v1: these SDKs append /v1/messages themselves, unlike an OpenAI client whose base_url includes the /v1.
import os
import anthropic
client = anthropic.Anthropic(
base_url=os.environ["I2_BASE_URL"],
api_key=os.environ["I2_API_KEY"],
)
with client.messages.stream(
model="claude-sonnet-5",
max_tokens=200,
messages=[{"role": "user", "content": "Hello"}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)In Node it is the same two arguments: new Anthropic({ baseURL: process.env.I2_BASE_URL, apiKey: process.env.I2_API_KEY }).
Note The two examples above put the key in different headers, and both are correct. cURL sends
Authorization: Bearer, the header every other i2 call uses. The SDKs sendx-api-key, because that is what they do withapi_keyand they offer no way to change it. Send whichever your client makes natural.
Note This endpoint answers with or without a stored key. Without one the request is served from i2's own Anthropic capacity and billed at i2's published rates; with one, the identical request is made under your account. Nothing in the snippets above changes either way, which is the point of storing the key here rather than in your code.
Audit
Setting or removing a key writes to the activity log as vault_key.set or vault_key.revoked, with the provider name as the target. The key and its suffix are never written to the audit log, and never appear in a log line anywhere in the platform.
In the dashboard
BYOK, under Organization settings. It lists all four providers whether or not a key is set, shows the suffix and the date for the ones that are, and offers add, rotate and a confirmed remove.
Something unclear or wrong on this page? Tell us. Machine-readable copies: llms.txt.