# Bring your own key (BYOK)

BYOK sends requests through your own account at a cloud. Connect a key once, then call the same API as for any request. The cloud bills you for the tokens. The exchange charges only its [fee](https://inference.ai.exchange/docs/fees.md).

You keep your own agreement and quota. The exchange seals your key when you connect it. The console shows only the last four characters.

## Clouds

| Cloud            | Name in the API | Key kinds                                   | Region                              |
| ---------------- | --------------- | ------------------------------------------- | ----------------------------------- |
| Anthropic        | `anthropic`     | `anthropic_api_key`                         | None. The exchange stores `global`. |
| Amazon Bedrock   | `bedrock`       | `aws_access_key`, `aws_api_key`             | The AWS region of your models.      |
| Google Vertex AI | `vertex`        | `gcp_service_account`                       | The Vertex location, `us-east5`.    |
| Azure OpenAI     | `azure_openai`  | `azure_api_key`, `azure_client_credentials` | None. The endpoint names the place. |
| OpenAI           | `openai`        | `openai_api_key`                            | None. The exchange stores `global`. |
| Google Gemini    | `gemini`        | `gemini_api_key`                            | None. The exchange stores `global`. |
| Other makers     | See below       | `<name>_api_key`                            | None. The exchange stores `global`. |

The other makers and hosts are `xai`, `mistral`, `deepseek`, `moonshot`, `zai`, `qwen`, `together`, `fireworks`, `groq` and `cerebras`. Each takes one API key and uses the OpenAI chat API. `qwen` uses the international endpoint of Alibaba Model Studio.

`gemini` means a key from Google AI Studio. Use `vertex` for a Google Cloud project.

An operator can turn a cloud off. You then get `403 upstream_disabled` when you connect a key for it.

## Connect a key

Choose a cloud in the cloud accounts of your workspace. Only an owner or an admin can connect a key, with a recent sign-in. Only a Clerk session works. An API key or a CLI token cannot connect a key.

The console calls `POST /v1/workspaces/{slug}/byok/grants`:

```json
{
  "upstream": "bedrock",
  "kind": "aws_access_key",
  "region": "us-east-1",
  "grant": {
    "access_key_id": "AKIA…",
    "secret_access_key": "…"
  }
}
```

| Kind                       | Fields of `grant`                                                                                                                                                                   |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `anthropic_api_key`        | `api_key` (starts with `sk-ant-`), and optional `workspace_id`. The exchange refuses an Admin key (`sk-ant-admin01-`).                                                              |
| `<name>_api_key`           | `api_key`. Allowed characters are letters, digits, `.`, `-` and `_`. The key must start as the cloud requires, such as `sk-` for `openai`, `AIza` for `gemini` or `xai-` for `xai`. |
| `aws_access_key`           | `access_key_id`, `secret_access_key`, and `session_token` for temporary keys.                                                                                                       |
| `aws_api_key`              | `api_key`: a Bedrock API key.                                                                                                                                                       |
| `gcp_service_account`      | The key file of the service account, as Google writes it.                                                                                                                           |
| `azure_api_key`            | `api_key`, `endpoint`, `api_version` and `deployments`.                                                                                                                             |
| `azure_client_credentials` | `tenant_id`, `client_id`, `client_secret`, `endpoint`, `api_version` and `deployments`.                                                                                             |

List 1 to 32 Azure `deployments` yourself. Each has a `name` and a `model`, and can have a `context_window` and `vision`.

Use the least rights that work. For Bedrock, allow model invocation and `bedrock:GetFoundationModelAvailability`.

### Bedrock model access

The exchange offers only the Bedrock models that your account can call, which it reads with `bedrock:GetFoundationModelAvailability`. Without that action, it offers every Bedrock model, and some can fail at the first call. The grant then shows `missing_permission`. Allow the action and test the key to clear the notice.

### Rotate, revoke and test

- A workspace can hold one live key of each kind for each cloud.
- Rotate a key with `PUT /v1/workspaces/{slug}/byok/grants/{id}`.
- Revoke a key with `DELETE`. This deletes the sealed key and stops service at once.
- With several live keys for one cloud, the exchange tries the oldest first. It tries the next key only when the cloud refuses the credentials.

The exchange does not test a key at connect. Send `POST …/grants/{id}/test`. The answer is `202`, and the result is in `last_test_ok`.

## Find your models

`GET /v1/workspaces/{slug}/byok/models` lists the models that your live keys offer. Each entry has `upstream` (the cloud), `name` (use it as the `model` of a request), `upstream_model` (the id at the cloud, used by the model scope) and `max_input_tokens` (absent when the key states none).

A new key shows its models after a few seconds. A model that the cloud adds later appears too, unless the key has a model scope.

`GET …/byok/models/unavailable` lists the models that the cloud lists and your account cannot call. Only Bedrock reports them now. Each entry has `upstream`, `name`, `upstream_model` and a `reason`.

The `reason` is `not_in_region`, `agreement_missing`, `not_entitled` or `not_authorized`.

## Send a request

Name the cloud in the model: `<cloud>[byok]/<model>`.

```bash
curl https://router.inference.ai.exchange/v1/chat/completions \
  -H "Authorization: Bearer sk-liquid-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic[byok]/claude-opus-5-5",
    "messages": [{ "role": "user", "content": "Hello" }]
  }'
```

The mark uses the names in the table above, with `azure-openai` for Azure. If your key cannot serve the request, your routing policy decides. See [When your account cannot serve](#when-your-account-cannot-serve).

With a plain model name, such as `claude-opus-5-5`, your offer competes with the market in the usual ranking. Only your workspace can buy from your account. For the guardrails that apply, see [Your own cloud keys](https://inference.ai.exchange/docs/guardrails.md#your-own-cloud-keys).

### Parameters that some models refuse

The exchange refuses these before it calls your cloud, so the cloud does not bill you.

| Model                                           | Refused                                                                |
| ----------------------------------------------- | ---------------------------------------------------------------------- |
| Claude Opus 4.7 and later, every Claude 5 model | `temperature`, `top_p`, `top_k` and a thinking budget                  |
| Claude Opus 5.5, Sonnet 5.5, Fable 5.1          | Also a `tool_choice` that forces a tool                                |
| OpenAI GPT-6 models on Bedrock                  | `temperature`, `top_p`, `stop`, and a `tool_choice` that forces a tool |
| gpt-oss                                         | `stop`                                                                 |

The GPT-6 models read images but not documents. A Bedrock model with a long-context price takes only a prompt below that size through your key: 100,000 tokens for Claude Haiku 5.5 and 272,000 for the GPT-6 models.

### Models of an API-key cloud

- The models are the chat models that the cloud lists for the key.
- These clouds send the whole answer at once, except Anthropic. A streamed request shows output when the model has finished.
- OpenAI takes the full set of request features. The other clouds take tools, JSON mode, `top_p` and stop sequences only.
- The exchange offers a model only when it knows the maker from the name. A name such as `meta-llama/Llama-3.3-70B-Instruct-Turbo` waits until an operator links it to a model.

## What a request costs

The cloud bills you at your own agreement, so the supplier charge is zero. The exchange computes its fee on the charge at the list price of the model, which the maker publishes. The same list price ranks your offer against the market. A cheaper market offer can win.

A model with no list price pays the token floor. See [Fees](https://inference.ai.exchange/docs/fees.md). The receipt shows the list price charge in `byok.list_charge_usd`.

## Control a key

Change the settings in the console, or with `PATCH /v1/workspaces/{slug}/byok/grants/{id}`. A field that you leave out stays as it is.

| Setting           | Effect                                                                                                                                                                                                                   |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `model_scope`     | The models that the key may serve, by `upstream_model`. `null` allows all. An empty list is refused.                                                                                                                     |
| `api_key_scope`   | The API keys of your workspace that may use the key. `null` allows all. A job with no API key cannot use a scoped key.                                                                                                   |
| `retention_claim` | What you state about how the cloud keeps your prompts: `default`, `zero` or `keeps`. See [Data handling](https://inference.ai.exchange/docs/data-handling.md).                                                                                            |
| `limits`          | `max_parallel`, `rpm` and `tpm` (any 60 seconds), `budget_tokens` with `budget_period` (`day` or `month`), `spend_day_nanos` and `spend_month_nanos` (nano-USD at list price, per UTC day or month). `null` clears them. |

A request with `exchange.privacy.retention` set to `none` goes to your key only when every key that can serve the model has the claim `zero`. With no claim, only Bedrock counts as zero retention. It does not count for Claude Fable or for OpenAI models other than gpt-oss, because AWS keeps that traffic for up to 30 days. A claim of `keeps` never counts.

`GET …/byok/grants/{id}/usage` shows today's tokens and requests, and the use of each limit.

## When your account cannot serve

A limit, a refused key or a cloud error can fail a request. Set a routing policy for each cloud with `PUT /v1/workspaces/{slug}/byok/routing/{upstream}` and a body such as `{"on_failure": "fail"}`. Read it with `GET`. For Azure, `{upstream}` is `azure_openai`.

| `on_failure` | Effect                                                          |
| ------------ | --------------------------------------------------------------- |
| `market`     | The default. The router sends the job to the next market offer. |
| `fail`       | The job ends with an error. Nothing goes to the market.         |

A fallback happens only before the cloud sends any output. After the first byte, the job stays on your account. A job that falls back is charged as a market job.

`GET /v1/workspaces/{slug}/byok/requests` lists the newest jobs that had a BYOK leg. Each entry has the outcome, whether `byok` or the `market` served it, the tokens, the charge, and `fallback_reason` when the market served a job.

## Errors

| Status and code         | Meaning                                                                        |
| ----------------------- | ------------------------------------------------------------------------------ |
| `400 invalid_grant`     | The secret lacks a field or has a value that the cloud cannot use.             |
| `400 admin_key_refused` | The Anthropic key is an Admin key. Create an API key in the Claude Console.    |
| `400 invalid_settings`  | A setting has a value that is not valid.                                       |
| `403 upstream_disabled` | An operator turned this cloud off.                                             |
| `404 no_grant`          | The key does not exist in your workspace.                                      |
| `409 grant_exists`      | The workspace has a live key of this kind for this cloud. Rotate or revoke it. |

To sell through BYOK, see [Sell with bring your own key](https://inference.ai.exchange/docs/provider-byok.md).
