Skip to main content
v1.5.0 introduces several breaking changes across provider key configuration, Virtual Key semantics, the Go SDK, and the REST API. This page consolidates every breaking change with before/after examples and a migration checklist.
Make a database backup before upgrading. Automatic database migrations run on startup and are not revertible. A backup is the only way to restore a previous state if anything goes wrong. A database successfully migrated to v1.5.0 cannot be used to run v1.4.x.

Automatic Database Migration

If you are running Bifrost with a database (SQLite or Postgres), existing data is automatically migrated on startup. You do not need to manually update your database records. The following automatic migrations run on upgrade:
  • Provider keys with models: [] are converted to models: ["*"]
  • Virtual Key provider configs with allowed_models: [] are converted to allowed_models: ["*"]
  • Virtual Keys with no provider_configs are backfilled with all currently configured providers (allowed_models: ["*"], key_ids: ["*"])
  • Virtual Keys with no mcp_configs are backfilled with all currently connected MCP clients (tools_to_execute: ["*"])
  • Per-provider deployments maps (Azure, Bedrock, Vertex, Replicate) are migrated into the unified aliases field
The automatic migration only protects your existing data. Any new configuration created after upgrading — via config.json or the REST API — must follow the new semantics described below.

Breaking Change 1: Empty Array Now Means “Deny All”

v1.5.0 flips the meaning of empty arrays across all allow-list fields:
What you writev1.4.x meaningv1.5.0 meaning
[] (empty array)Allow allAllow none
["*"] (wildcard)Not applicableAllow all
["a", "b"]Only a and bOnly a and b (unchanged)
This affects four fields:
FieldWhere
modelsProvider key
allowed_modelsVirtual Key provider config
key_idsVirtual Key provider config
tools_to_executeVirtual Key MCP config

Provider key models

Before:
{ "value": "env.OPENAI_API_KEY", "models": [] }
models: [] → key served all models After:
{ "value": "env.OPENAI_API_KEY", "models": ["*"] }

Virtual Key allowed_models

Before:
{ "provider": "openai", "weight": 1.0 }
Missing allowed_models → all models allowed After:
{ "provider": "openai", "allowed_models": ["*"], "key_ids": ["*"], "weight": 1.0 }

Virtual Key MCP tools_to_execute

Before:
{ "mcp_client_name": "my-tools", "tools_to_execute": [] }
After:
{ "mcp_client_name": "my-tools", "tools_to_execute": ["*"] }

Breaking Change 2: allowed_keys Renamed to key_ids

The field used to restrict which provider API keys a Virtual Key can use has been renamed from allowed_keys to key_ids. The deny-by-default rule also applies — omitting the field or setting it to [] now blocks all keys.
Unlike allowed_models, there is no automatic database migration for key_ids. An empty or omitted key_ids disables all key selection. You must explicitly use ["*"] to restore allow-all behavior.
Before:
{ "provider": "openai", "allowed_keys": ["key-prod-001"], "weight": 1.0 }
After:
{ "provider": "openai", "key_ids": ["key-prod-001"], "allowed_models": ["*"], "weight": 1.0 }
To allow all keys:
{ "provider": "openai", "key_ids": ["*"], "allowed_models": ["*"], "weight": 1.0 }

Breaking Change 3: Virtual Key provider_configs is Deny-by-Default

In v1.4.x, a Virtual Key with no provider_configs had access to all providers. In v1.5.0, it blocks all providers. Before: "provider_configs": [] → access to all providers After: "provider_configs": [] → no provider access To allow all providers, list each one explicitly:
{
  "provider_configs": [
    { "provider": "openai",    "allowed_models": ["*"], "key_ids": ["*"], "weight": 1.0 },
    { "provider": "anthropic", "allowed_models": ["*"], "key_ids": ["*"], "weight": 1.0 }
  ]
}
The automatic migration backfills all currently configured providers into any VK that has an empty provider_configs. However, any VK created after upgrading must include explicit provider configs.

Breaking Change 4: WhiteList Validation

Two new validation rules are enforced on all allow-list fields. The API returns HTTP 400 if either is violated. Rule 1: Wildcard cannot be mixed with other values
// ❌ Invalid
{ "allowed_models": ["*", "gpt-4o"] }

// ✅ Valid
{ "allowed_models": ["*"] }
Rule 2: No duplicate values
// ❌ Invalid
{ "allowed_models": ["gpt-4o", "gpt-4o"] }
Applies to: models, allowed_models, key_ids, tools_to_execute, tools_to_auto_execute, allowed_extra_headers.

Breaking Change 5: weight is Now Nullable

The weight field on a Virtual Key provider config was previously a required float64. It is now an optional *float64.
  • weight: 0.5 — provider participates in weighted load balancing
  • weight: null / omitted — provider is accessible for direct routing but excluded from weighted selection
API response change: weight may now be null. Update any client code that assumes it is always a number.

Breaking Change 6: Provider Keys API Separated

Provider key management now has dedicated endpoints. The keys field has been removed from all provider API requests and responses.

What changed

Before (v1.4.x)After (v1.5.0)
GET /api/providers/{p} returns keyskeys field removed from provider response
POST /api/providers accepts keyskeys field ignored — create keys separately
PUT /api/providers/{p} accepts keyskeys field ignored — update keys via dedicated endpoints

New endpoints

MethodEndpointDescription
GET/api/providers/{provider}/keysList all keys
GET/api/providers/{provider}/keys/{key_id}Get a single key
POST/api/providers/{provider}/keysCreate a key
PUT/api/providers/{provider}/keys/{key_id}Update a key
DELETE/api/providers/{provider}/keys/{key_id}Delete a key

How to update

Creating a provider with keys: Before:
curl -X POST localhost:8080/api/providers -d '{
  "provider": "openai",
  "keys": [{"name": "main", "value": "sk-..."}]
}'
After: Create provider first, then add keys:
curl -X POST localhost:8080/api/providers -d '{"provider": "openai"}'
curl -X POST localhost:8080/api/providers/openai/keys -d '{"name": "main", "value": "sk-..."}'
Reading keys: Before: curl localhost:8080/api/providers/openai | jq '.keys' After: curl localhost:8080/api/providers/openai/keys | jq '.keys' Updating / deleting keys: Before: Bulk replace via provider update:
curl -X PUT localhost:8080/api/providers/openai -d '{"keys": [{"id": "key-1", "value": "sk-new"}]}'
After: Individual key operations:
curl -X PUT localhost:8080/api/providers/openai/keys/key-1 -d '{"name": "updated", "value": "sk-new"}'
curl -X DELETE localhost:8080/api/providers/openai/keys/key-2

Breaking Change 7: Compact Plugin Restructured

The enable_litellm_fallbacks option has been removed and replaced with three granular options. Before:
{ "compat": { "enable_litellm_fallbacks": true } }
After:
{
  "compat": {
    "convert_text_to_chat": true,
    "convert_chat_to_responses": true,
    "should_drop_params": true
  }
}
Old optionNew optionDescription
enable_litellm_fallbacksconvert_text_to_chatText completion → chat completion fallback
(new)convert_chat_to_responsesChat completion → Responses API fallback
(new)should_drop_paramsDrop unsupported OpenAI-compatible params
Response field changes:
FieldChange
extra_fields.litellm_compatRemoved
extra_fields.dropped_compat_plugin_paramsAdded — lists params dropped by this plugin
extra_fields.converted_request_typeAdded — the request type it was converted to

Breaking Change 8: Replicate Image Edits Removed from Generations Endpoint

The /v1/images/generations endpoint on the Replicate provider no longer accepts image editing parameters (source image, mask). It now only handles text-to-image generation. If you were passing image editing parameters to /v1/images/generations on Replicate, switch to /v1/images/edits.
Support for image editing via /v1/images/edits on Replicate is also being removed in a follow-up release. Plan to migrate to an alternative provider.

Breaking Change 9: Provider deployments Removed — Migrate to aliases

The per-provider deployments map has been removed from azure_key_config, vertex_key_config, bedrock_key_config, and replicate_key_config. A single top-level aliases field on each key replaces all of them. Aliases work across all providers and map any model name to a provider-specific identifier (deployment name, inference profile ARN, fine-tuned model ID, etc.). The database migration runs automatically on startup, migrating existing deployment data into aliases. Only config.json files need to be updated manually.

Azure

Before:
{
  "providers": {
    "azure": {
      "keys": [{
        "value": "env.AZURE_API_KEY",
        "azure_key_config": {
          "endpoint": "env.AZURE_ENDPOINT",
          "deployments": {
            "gpt-4o": "my-gpt4o-deployment",
            "gpt-4o-mini": "my-mini-deployment"
          }
        }
      }]
    }
  }
}
After:
{
  "providers": {
    "azure": {
      "keys": [{
        "value": "env.AZURE_API_KEY",
        "azure_key_config": {
          "endpoint": "env.AZURE_ENDPOINT"
        },
        "aliases": {
          "gpt-4o": "my-gpt4o-deployment",
          "gpt-4o-mini": "my-mini-deployment"
        }
      }]
    }
  }
}

Bedrock

Before:
{
  "bedrock_key_config": {
    "region": "env.AWS_REGION",
    "deployments": {
      "claude-3-5-sonnet": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0"
    }
  }
}
After:
{
  "bedrock_key_config": {
    "region": "env.AWS_REGION"
  },
  "aliases": {
    "claude-3-5-sonnet": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0"
  }
}

Vertex

Before:
{
  "vertex_key_config": {
    "project_id": "env.VERTEX_PROJECT_ID",
    "project_number": "env.VERTEX_PROJECT_NUMBER",
    "region": "env.VERTEX_REGION",
    "auth_credentials": "env.VERTEX_AUTH_CREDENTIALS",
    "deployments": {
      "gemini-2.0-flash": "projects/my-project/locations/us-central1/endpoints/123456"
    }
  }
}
After:
{
  "vertex_key_config": {
    "project_id": "env.VERTEX_PROJECT_ID",
    "project_number": "env.VERTEX_PROJECT_NUMBER",
    "region": "env.VERTEX_REGION",
    "auth_credentials": "env.VERTEX_AUTH_CREDENTIALS"
  },
  "aliases": {
    "gemini-2.0-flash": "projects/my-project/locations/us-central1/endpoints/123456"
  }
}

Replicate

The Replicate key config is also restructured. The deployments map is gone. A new boolean use_deployments_endpoint controls whether requests are routed through the Deployments API (private, fixed hardware) or the standard Models API. Before:
{
  "replicate_key_config": {
    "deployments": {
      "my-model": "owner/model-name/version-hash"
    }
  }
}
After:
{
  "replicate_key_config": {
    "use_deployments_endpoint": true
  },
  "aliases": {
    "my-model": "owner/model-name"
  }
}
Old fieldNew fieldNotes
replicate_key_config.deploymentsRemovedUse top-level aliases
(new)replicate_key_config.use_deployments_endpointbool, default false

Breaking Change 10: Go SDK — ExtraFields Model Fields Renamed

ModelRequested string has been replaced by two fields on BifrostResponseExtraFields and BifrostErrorExtraFields. Before:
model := response.ExtraFields.ModelRequested
After:
// The alias the caller passed as "model" in the request
original := response.ExtraFields.OriginalModelRequested

// The actual identifier sent to the provider API
// Equals OriginalModelRequested when no alias is configured
resolved := response.ExtraFields.ResolvedModelUsed
The same rename applies to BifrostErrorExtraFields. JSON tag changes:
OldNew
"model_requested""original_model_requested" + "resolved_model_used"

Breaking Change 11: Go SDK — StreamAccumulatorResult Field Renamed

Model string has been replaced by two fields on StreamAccumulatorResult (returned by tracer streaming accumulation methods). Before:
result.Model
After:
result.RequestedModel // original alias from the caller
result.ResolvedModel  // actual model identifier used by the provider

Opting Out: version: 1 Compatibility Mode

If you are not ready to adopt the new deny-by-default semantics, you can add a single field to config.json to restore v1.4.x behavior for all allow-list fields loaded from that file:
{
  "version": 1,
  "providers": { ... }
}
ValueBehavior
2 (default, omitted)v1.5.0 semantics — empty = deny all, ["*"] = allow all
1v1.4.x semantics — empty = allow all
What version: 1 normalizes at startup (before any other processing):
FieldWithout version: 1With version: 1
Provider key models: []Deny all modelsAllow all models (→ ["*"])
VK provider_configs: []No providers allowedAll configured providers added with allowed_models: ["*"]
VK provider config allowed_models: []Deny all modelsAllow all models (→ ["*"])
VK provider config key_ids: []No keys allowedAll keys allowed (→ key_ids: ["*"])
VK mcp_configs: []No MCP tools allowedAll configured MCP clients added with tools_to_execute: ["*"]
version: 1 only applies to configuration loaded from config.json. Virtual Keys created or updated via the REST API always use v1.5.0 semantics regardless of this setting. The automatic database migration that runs on startup is also unaffected.
version: 1 is a temporary compatibility shim. Plan to migrate your config.json to explicit ["*"] wildcards and remove the version field before the next major release.

Complete Migration Checklist

1

Backup your database

Make a copy of your config store database before starting the upgrade.
2

Update provider key models in config.json

Replace "models": [] or missing models fields with "models": ["*"] on every provider key.
3

Add allowed_models and key_ids to every VK provider config

Add "allowed_models": ["*"] and "key_ids": ["*"] to every provider_configs entry (or list specific values). Rename any allowed_keys fields to key_ids.
4

Ensure every VK has at least one provider config

Any Virtual Key with "provider_configs": [] or no provider_configs will block all traffic.
5

Update tools_to_execute for MCP configs

Replace "tools_to_execute": [] with "tools_to_execute": ["*"]. Ensure every VK that needs MCP access has at least one mcp_configs entry.
6

Handle nullable weight in API consumers

Update any client code that processes weight to accept null in addition to numbers.
7

Fix invalid WhiteList values

Ensure no list mixes "*" with specific values (e.g., ["*", "gpt-4o"]) and no list has duplicate entries.
8

Migrate key management to dedicated endpoints

Stop sending keys in provider create/update payloads and stop reading keys from provider responses. Use /api/providers/{provider}/keys for all key operations.
9

Update compact plugin config

Replace enable_litellm_fallbacks with the appropriate combination of convert_text_to_chat, convert_chat_to_responses, and should_drop_params.
10

Migrate provider deployments to aliases

Remove deployments from azure_key_config, vertex_key_config, bedrock_key_config, and replicate_key_config. Move those mappings to the top-level aliases field on each key. For Replicate, set use_deployments_endpoint: true if you were using the deployments endpoint.
11

Update Go SDK references to ExtraFields.ModelRequested

Replace ExtraFields.ModelRequested with ExtraFields.OriginalModelRequested (and optionally read ExtraFields.ResolvedModelUsed). Update JSON consumers reading "model_requested" to use "original_model_requested" and "resolved_model_used".
12

Update Go SDK references to StreamAccumulatorResult.Model

Replace .Model with .RequestedModel (and optionally .ResolvedModel) on any StreamAccumulatorResult usage.

Troubleshooting

All requests returning 403/blocked after upgrade A provider key has models: [], a Virtual Key has no provider_configs, or a provider config has allowed_models: []. Check Bifrost logs — a blocked request logs which rule denied it. Fix: add "models": ["*"] on provider keys, "allowed_models": ["*"] on VK provider configs. MCP tools not being injected / tool calls blocked The VK needs an mcp_configs entry for the MCP client with "tools_to_execute": ["*"] (or specific tools). API returning 400 on VK create/update A whitelist validation failure — either mixing "*" with specific values, or duplicate values in a list. “No keys available” or key selection errors A provider config with key_ids omitted or [] now blocks all keys (allow_all_keys: false). Add "key_ids": ["*"]. Provider create/update errors about keys field The keys field has been removed. Remove it from provider payloads and use /api/providers/{provider}/keys instead. Replicate requests failing after upgrade If you used replicate_key_config.deployments, move the mappings to the top-level aliases field and set use_deployments_endpoint: true if you were targeting the Deployments API. Go SDK compilation errors on ModelRequested or StreamAccumulatorResult.Model Rename to OriginalModelRequested/ResolvedModelUsed on ExtraFields, and RequestedModel/ResolvedModel on StreamAccumulatorResult.