> ## Documentation Index
> Fetch the complete documentation index at: https://docs.routerbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# BYOK

> Bring Your Own Key — register upstream provider credentials so RouterBase uses your account to call OpenAI / Anthropic / Google on your behalf.

**BYOK** (Bring Your Own Key) lets you register your own upstream credential for a supported provider (OpenAI, Anthropic, Google). Once registered, RouterBase uses it for every request routed through that provider — your upstream account is billed directly; RouterBase never charges you for BYOK calls.

**This is data, not a caller token.** You never present a BYOK credential to RouterBase in an `Authorization` header. You register it once via the endpoints below; RouterBase uses it silently at request time.

**Authentication for these endpoints:** JWT (logged-in dashboard session) or an API Key.

## Runtime Behaviour

When a call to `/v1/chat/completions` (or images / videos / audio) resolves to a provider you have a BYOK credential for:

1. Candidates are ordered `priority DESC, created_at DESC`. `disabled=true` rows are excluded.
2. Each candidate is tried once. On success, `last_used_at` advances and `last_error` clears.
3. On failure, `last_error` is recorded and the next candidate is tried.
4. If no candidate succeeds:
   * If **any** of your rows for that provider has `always_use=true` → the upstream error is returned. No platform-key fallback.
   * Otherwise → RouterBase falls back to its platform credential for that provider.

## List Provider Keys

```
GET https://routerbase.com/api/v1/byok
```

### Query Parameters

<ParamField query="provider" type="string">
  Filter to a single provider: `openai`, `anthropic`, or `google`.
</ParamField>

### Response

```json theme={null}
[
  {
    "id": "01J...",
    "provider": "openai",
    "label": "My OpenAI (prod)",
    "api_key_prefix": "sk-proj-…",
    "base_url": null,
    "config_json": null,
    "always_use": false,
    "disabled": false,
    "priority": 0,
    "last_used_at": "2026-04-23T12:00:00Z",
    "last_error": null,
    "created_at": "2026-04-22T09:00:00Z",
    "updated_at": "2026-04-23T12:00:00Z"
  }
]
```

The plaintext `api_key` is never returned. `config_json` sensitive fields (`secretAccessKey`, `private_key`, `api_key`, `token`, etc.) are masked to `"***"`.

***

## Create Provider Key

```
POST https://routerbase.com/api/v1/byok
```

### Request Body

<ParamField body="provider" type="string" required>
  One of `openai`, `anthropic`, `google`.
</ParamField>

<ParamField body="label" type="string" required>
  1–100 chars. User-facing name, e.g. "Personal OpenAI (prod)".
</ParamField>

<ParamField body="api_key" type="string">
  The upstream credential. Required unless `config_json` carries it (e.g. Vertex service-account JSON).
</ParamField>

<ParamField body="base_url" type="string">
  Optional override for the upstream base URL. Must be HTTPS.
</ParamField>

<ParamField body="config_json" type="object">
  Provider-specific extras (e.g. Azure `{endpoint_url, deployment_id}`, Bedrock `{region, …}`, Vertex service-account JSON + `region`). Secret fields inside this object are masked in all read responses.
</ParamField>

<ParamField body="always_use" type="boolean" default="false">
  When `true`, disables platform-key fallback for this provider if every BYOK candidate fails.
</ParamField>

<ParamField body="priority" type="number" default="0">
  Clamped to `[-1000, 1000]`. Higher wins when multiple rows exist for the same `(user, provider)`. Ties broken by `created_at DESC`.
</ParamField>

### Example

```bash theme={null}
curl -X POST https://routerbase.com/api/v1/byok \
  -H "Authorization: Bearer <JWT>" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "openai",
    "label": "My OpenAI (prod)",
    "api_key": "sk-proj-xxxxxxxxxxxx",
    "always_use": true
  }'
```

***

## Update Provider Key

```
PUT https://routerbase.com/api/v1/byok/{id}
```

Any subset of:

<ParamField body="label" type="string" />

<ParamField body="api_key" type="string" />

<ParamField body="base_url" type="string" />

<ParamField body="config_json" type="object" />

<ParamField body="always_use" type="boolean" />

<ParamField body="disabled" type="boolean">
  Pause the credential without losing it. `true` excludes it from the candidate list.
</ParamField>

<ParamField body="priority" type="number" />

***

## Delete Provider Key

```
DELETE https://routerbase.com/api/v1/byok/{id}
```

Returns `204`. The next inference call to this provider skips the deleted row.

***

## Rotating a Credential

The safe pattern is **add new, delete old**:

```bash theme={null}
# 1. Add the new credential (will be tried first due to higher created_at)
curl -X POST .../byok -d '{"provider":"openai","label":"prod-2026-04","api_key":"sk-proj-NEW"}'

# 2. Verify by making a normal /v1/chat/completions call — check `last_used_at` on the new row

# 3. Delete the old credential
curl -X DELETE .../byok/<old-id>
```
