# Bring your own provider key

Your organization can route inference through its own OpenAI, Anthropic or Azure API keys, or an
AWS Bedrock workload role. You still call the gateway with a marketplace key; the provider
credential stays stored with the connection, encrypted, and the provider bills you directly.
The marketplace charges nothing for BYOK inference. Set it up on
[**Console → Provider connections**](https://app.routerplus.com/console/byok) or with the API below.

## Set up in the console

1. Sign in, open [`/console/byok`](https://app.routerplus.com/console/byok), and select your organization.
2. Click **Add connection**. Name it, choose a provider, enter its credential and add exact
   model IDs. Azure also needs a resource and a deployment mapping. Bedrock is selectable
   only when your organization has an operator-approved role. The provider and model list
   are fixed after saving; create a new connection if they change.
3. Click **Save and validate**. If validation fails, the pending connection remains available;
   rotate its credential or retry validation instead of creating a duplicate.
4. Choose an existing provider account's limits, or enter RPM, TPM, concurrency and headroom
   for a new account. Credentials for the same account should share the same pool or parent.
   A connection with no pool cannot serve requests.
5. Create a new platform key or select an existing one. A new BYOK key is created and bound
   in one transaction before it is returned. The page warns before it replaces an existing
   key's connection or key-level policy; an organization or workspace policy still applies.
6. Copy the new platform key once and use the generated request example. The optional
   **Send test request** sends "Reply OK" with at most 8 output tokens; it uses provider
   quota and may incur a small provider charge.

The connection cards support validation, shared-account limit edits, rotation, disable and
permanent deletion. Viewers can inspect metadata; owners and admins make changes. Provider
secrets are never returned. A disabled connection needs rotation and successful validation
to become active again. Deleted connections cannot be restored.

Workspaces and principals provisioned through the [identity API](/docs/identity) can be
selected when issuing a key. The console preserves their limits and restrictions.

## API setup

1. Sign in to the console and create a virtual key. No marketplace credit is
   required for BYOK inference.
2. Send `POST /api/connections` on the **site origin**, with JSON:

   ```json
   {"profile":"openai","models":["your-exact-provider-model-id"],"api_key":"YOUR_PROVIDER_KEY"}
   ```

   Basic profiles are `openai` and `anthropic`; [Azure and policy setup](/docs/routing-policies)
   adds an `azure` profile with mandatory deployment mapping, and [Bedrock](/docs/bedrock) a
   `bedrock` profile whose `workload_role` replaces `api_key`. Supply 1–100 exact model IDs,
   without wildcards. An optional `name` labels the connection.
   The response is `201` with `connection_id` and `status: "pending"`; it never returns the key.
3. Send `POST /api/connections/{connection_id}/validate` with `{}`. A successful result
   has `valid: true`, `status: "active"`. For API-key profiles, validation performs one authenticated model-list
   GET, with a ten-second timeout and no generated tokens. It checks credential access to
   that endpoint; it does not verify access to every declared model or reserve capacity.
4. Send `POST /api/connections/{connection_id}/bind` with `{"key_id":"YOUR_VIRTUAL_KEY_UUID"}`.
   This binds an existing, enabled virtual key in the same org to an active connection. Allow five seconds for a previously
   used house key to switch, or use a fresh virtual key.
5. [Declare a quota pool](/docs/admission) for the provider account and assign the
   connection to it. A route with no declared pool is refused with a 503. Credentials for the same account must share the appropriate pool or parent.
6. Use the virtual key with `/v1/chat/completions` or `/v1/messages`. Both buyer formats and
   streaming work with either profile, subject to the existing wire compatibility limits.

Management requires the `tm_s` session cookie. Mutations also require
`Content-Type: application/json` and an `Origin` header equal to `https://app.routerplus.com`.
Same-origin browser `fetch` supplies the cookie and Origin automatically. A CLI
client must supply both securely; avoid putting cookies or provider keys in shell history.
An inference bearer key cannot manage connections. Viewers can read; owners and admins can write.

## Management operations

| Method and site path | JSON body | Effect |
|---|---|---|
| `GET /api/connections` | none | Newest 100 org-owned connections, including tombstones |
| `GET /api/connections/{id}` | none | One connection's metadata and fully masked label |
| `POST /api/connections` | `profile`, `models`, `api_key` or `workload_role`, optional `name`, `endpoint_config` | Create a pending connection |
| `POST /api/connections/{id}/validate` | `{}` | Check credential, activate on success; failed validation leaves pending |
| `POST /api/connections/{id}/rotate` | `api_key` or `workload_role` | Revoke old versions and create a pending version; validate it before use |
| `POST /api/connections/{id}/disable` | `{}` | Disable connection and revoke its credential versions |
| `POST /api/connections/{id}/bind` | `key_id` | Bind/rebind an org-owned virtual key to an active connection |
| `DELETE /api/connections/{id}` | `{}` | Revoke and tombstone; retain attribution and bindings |

Disabled connections can be restored by rotating and validating a new credential. Deleted
connections cannot be restored. Rotation temporarily stops new inference until validation
succeeds. Profile and allowed-model changes require a new connection and an explicit rebind.
There is no implicit unbind-to-house operation. An explicit house-only policy is available
through the [policy API](/docs/routing-policies). No secret suffix, ciphertext, envelope, or upstream
validation body is exposed in management responses.

## Inference behavior

A bound key can use only its connection's exact models. It never silently falls back to
marketplace supply. `/v1/models` lists that connection's models; Anthropic token counting
uses the same connection and is available only for an Anthropic profile. Unavailable,
disabled, or deleted bindings produce `404 model_unavailable`; database/decryption failures
produce `503 gateway_error`. An invalid virtual key still produces `401 auth`.

BYOK inference is metered and durably audited. Marketplace charges and marketplace provider
payables are zero: the attempt's `billing_source` is `byok`, its `cost_usd` is `0`, and its
inference cost is recorded as unknown (`null`), since the marketplace does not price your
account. The provider still bills your account. Marketplace spend caps do not
limit that external bill; virtual-key RPM enforcement and your organization's token and
concurrency limits still apply, including to token counting. A policy with house fallback
is the one case a BYOK key spends credit: the house attempt reserves and is charged like
any house call.

Image generation works through an `openai` connection: list the exact image model ids you
will send (matching is literal), and the render is billed by OpenAI to your own account, so
`usage.cost` is `0`. See [POST /v1/images/generations](/docs/api-images).

New calls reflect credential disable/rotation within five seconds; existing upstream calls
and streams may finish on their original version. When the configuration database is
unreachable, previously verified authority may serve for a bounded time; see
[limits and outage behavior](/docs/admission). OpenAI, Anthropic and configured Azure v1 public destinations are supported;
redirects are refused. Bedrock uses the separately documented workload-role profile.
No arbitrary endpoint or automatic private-link, residency or retention guarantee is included. [Routing policies](/docs/routing-policies) add explicit ordering, filtering and
funding controls. Request-level credentials or destinations (`api_key`, `base_url` and the like) return 400.

Provider HTTP error bodies are never relayed, so an echoed credential cannot leak.
Validation and token-count calls are not inference ledger attempts; validation has a
content-free management audit event. Shared limits and pilot fairness are described in the [admission guide](/docs/admission).

## Related

Use [workspaces and principals](identity.md) for scoped keys and trusted end-user limits.
The [Bedrock workload-role profile](bedrock.md) adds native regional Claude inference;
its write-only `workload_role` replaces `api_key`. The connection lifecycle,
quota-pool requirement and free BYOK economics are the same for every profile.
