Skip to content

Model Allowlist

The model allowlist lets operators enable or disable specific models for all API keys at once. A model disabled here is blocked regardless of per-key allowed_models settings.

GET https://api.bve.me/admin/model-allowlist
Authorization: Bearer admin_bve_YOUR_ADMIN_KEY

Returns all registered model entries, annotated with BVE registry metadata.

ParameterTypeDescription
enabled"true" | "false"Filter to only allowed (true) or only blocked (false) entries. Omit to return all entries. Returns 400 for any other value.
searchstringCase-insensitive substring search on the model ID. Only entries whose model ID contains the search string are returned. Combine with ?enabled= to filter by both name and status. An empty string is treated as no filter.
{
"models": [
{
"model": "gpt-4o",
"enabled": true,
"created_at": "2026-05-21T11:00:00.000Z",
"bve_category": "chat",
"bve_provider": "openai",
"bve_reasoning": false,
"bve_vision": true,
"bve_web_search": false,
"bve_audio_input": false,
"bve_tool_use": true,
"bve_json_mode": true,
"bve_thinking": false,
"bve_computer_use": false,
"registry_availability": "callable",
"registry_working": true,
"registry_broken": false
},
{
"model": "gpt-4o-mini",
"enabled": false,
"created_at": "2026-05-21T12:00:00.000Z",
"bve_category": "chat",
"bve_provider": "openai",
"bve_reasoning": false,
"bve_vision": true,
"bve_web_search": false,
"bve_audio_input": false,
"bve_tool_use": true,
"bve_json_mode": true,
"bve_thinking": false,
"bve_computer_use": false,
"registry_availability": "callable",
"registry_working": true,
"registry_broken": false
}
]
}
FieldTypeDescription
modelstringModel ID (unique)
enabledbooleantrue = model is permitted; false = model is blocked
created_atstringISO 8601 timestamp of when the entry was first registered
bve_categorystring | nullModel type: chat, embedding, image, tts, transcription, ocr, or null if unrecognized
bve_providerstring | nullInferred upstream creator: openai, anthropic, google, meta, mistral, cohere, cursor, deepseek, wasikan, or null if unrecognized
bve_reasoningbooleantrue for reasoning/thinking models (o3, o3-mini, o4-mini and dated variants)
bve_visionbooleantrue for models that accept image inputs in chat requests (e.g. gpt-4o, claude-sonnet-4, gemini-2.0-flash); false for text-only or image-generation models
bve_web_searchbooleantrue for models with native web_search_options support (gpt-4o-search-preview, gpt-4.1 family); false for all others
bve_audio_inputbooleantrue for models that accept audio content blocks as inline input in POST /v1/chat/completions (gpt-4o-audio-preview, gpt-4o-mini-audio-preview families); false for all others
bve_tool_usebooleantrue for models that accept the tools parameter for function calling in POST /v1/chat/completions; false for embedding, TTS, STT, image-generation, and legacy completion-only models
bve_json_modebooleantrue for models that support "response_format": { "type": "json_object" } or structured output in chat completions; false for embedding, TTS, STT, image-generation, and non-JSON-capable models
bve_thinkingbooleantrue for models that support the thinking parameter for extended thinking (e.g. claude-3-7-sonnet and later Anthropic models with extended thinking enabled); false for all others
bve_computer_usebooleantrue for models that support Anthropic computer use built-in tool types in POST /v1/messages; false for all others
registry_availabilitystringDefault gateway availability from the local registry + live Fuelix snapshot: callable, listed_unavailable, registry_broken, snapshot_excluded, or unknown
registry_workingbooleantrue if the model is in the gateway’s static working-models registry
registry_brokenbooleantrue if the model is flagged in the gateway’s known-broken list
Terminal window
curl "https://api.bve.me/admin/model-allowlist" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"
Terminal window
curl "https://api.bve.me/admin/model-allowlist?enabled=false" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"
Terminal window
curl "https://api.bve.me/admin/model-allowlist?enabled=true" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"
Terminal window
# All entries whose model ID contains "gpt"
curl "https://api.bve.me/admin/model-allowlist?search=gpt" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"
# Combine search with enabled filter: blocked Claude models only
curl "https://api.bve.me/admin/model-allowlist?search=claude&enabled=false" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"
GET https://api.bve.me/admin/model-allowlist/:model
Authorization: Bearer admin_bve_YOUR_ADMIN_KEY

Returns allowlist status and registry metadata for one model. Always returns 200 — there is no 404 response even if the model is unknown or unregistered.

ParameterDescription
modelThe model ID to inspect (URL-encode if it contains slashes)

Response (200) — registered working model

Section titled “Response (200) — registered working model”
{
"model": "gpt-4o",
"available": true,
"category": "chat",
"bve_category": "chat",
"bve_provider": "openai",
"bve_reasoning": false,
"bve_vision": true,
"bve_web_search": false,
"bve_audio_input": false,
"bve_tool_use": true,
"bve_json_mode": true,
"bve_thinking": false,
"bve_computer_use": false,
"registry": {
"availability": "callable",
"working": true,
"broken": false
},
"allowlist": {
"enabled": true,
"created_at": "2026-05-21T11:00:00.000Z"
}
}
{
"model": "o3-mini",
"available": true,
"category": "reasoning",
"bve_category": "chat",
"bve_provider": "openai",
"bve_reasoning": true,
"bve_vision": false,
"bve_web_search": false,
"bve_audio_input": false,
"bve_tool_use": true,
"bve_json_mode": false,
"bve_thinking": false,
"bve_computer_use": false,
"registry": {
"availability": "callable",
"working": true,
"broken": false
},
"allowlist": null
}

Response (200) — unregistered or unknown model

Section titled “Response (200) — unregistered or unknown model”

For a model that has never been registered in the global allowlist, allowlist is null:

{
"model": "some-new-model",
"available": false,
"category": null,
"bve_category": null,
"bve_provider": null,
"bve_reasoning": false,
"bve_vision": false,
"bve_web_search": false,
"bve_audio_input": false,
"bve_tool_use": true,
"bve_json_mode": false,
"bve_thinking": false,
"bve_computer_use": false,
"registry": {
"availability": "unknown",
"working": false,
"broken": false
},
"allowlist": null
}
FieldTypeDescription
modelstringThe queried model ID
availablebooleantrue if the model is usable — see availability logic below
categorystring | nullModel type from the registry (may differ from bve_category for legacy reasons)
bve_categorystring | nullCanonical BVE category: chat, embedding, image, tts, transcription, ocr, or null if unrecognized
bve_providerstring | nullInferred model creator: openai, anthropic, google, meta, mistral, cohere, cursor, deepseek, wasikan, or null if unrecognized
bve_reasoningbooleantrue for reasoning/thinking models (o3, o3-mini, o4-mini and dated variants)
bve_visionbooleantrue for models that accept image inputs in chat requests (e.g. gpt-4o, claude-sonnet-4, gemini-2.0-flash); false for text-only or image-generation models
bve_web_searchbooleantrue for models with native web_search_options support (gpt-4o-search-preview, gpt-4.1 family); false for all others
bve_audio_inputbooleantrue for models that accept audio content blocks as inline input in POST /v1/chat/completions (gpt-4o-audio-preview, gpt-4o-mini-audio-preview families); false for all others
bve_tool_usebooleantrue for models that accept the tools parameter for function calling in POST /v1/chat/completions; false for embedding, TTS, STT, image-generation, and legacy completion-only models
bve_json_modebooleantrue for models that support "response_format": { "type": "json_object" } or structured output in chat completions; false for non-JSON-capable models
bve_thinkingbooleantrue for models that support the thinking parameter for extended thinking (Anthropic claude-3-7-sonnet and later); false for all others
bve_computer_usebooleantrue for models that support Anthropic computer use built-in tool types in POST /v1/messages; false for all others
registry.availabilitystringDefault gateway availability from the local registry + live Fuelix snapshot before any D1 override: callable, listed_unavailable, registry_broken, snapshot_excluded, or unknown
registry.workingbooleantrue if the model is in the gateway’s static working-models registry
registry.brokenbooleantrue if the model is in the gateway’s known-broken list
allowlistobject | nullThe D1 allowlist entry if present; null if the model has never been registered
allowlist.enabledbooleantrue = globally permitted; false = globally blocked
allowlist.created_atstringISO 8601 timestamp of when the entry was first registered

available: true requires both of the following:

  • The model is not globally blocked (allowlist is absent or allowlist.enabled: true)
  • The model is callable by default (registry.availability: "callable") or Fuelix /models still lists it live for the current account while the local registry remains unclassified (registry.availability: "unknown")

allowlist.enabled: true no longer widens availability by itself. It keeps the row out of the global-block path, but the model must still be callable in the local snapshot or currently listed by the live Fuelix catalog for the active account. It does not override registry_broken, listed_unavailable, or snapshot_excluded.

Use this endpoint to check why a model is blocked before attempting to re-enable it via POST /admin/model-allowlist.

Using bve_reasoning to detect reasoning models

Section titled “Using bve_reasoning to detect reasoning models”

bve_reasoning: true means the model supports reasoning_effort (and the thinking block for Anthropic extended-thinking variants). Use this field to gate UI controls or API clients that conditionally add reasoning_effort without hard-coding model name lists.

Using bve_vision to detect vision-capable models

Section titled “Using bve_vision to detect vision-capable models”

bve_vision: true means the model accepts image_url content blocks in chat completion messages — it can analyse images sent alongside text. Use this field to conditionally enable image upload controls in your UI without maintaining your own model name list. Image-generation models (e.g. imagen-3, gpt-image-1) always have bve_vision: false — they produce images rather than accept them as input.

Using bve_web_search to detect native web search support

Section titled “Using bve_web_search to detect native web search support”

bve_web_search: true means the model natively processes the web_search_options parameter in POST /v1/chat/completions to perform live web searches before generating a response. Currently covers the gpt-4o-search-preview, gpt-4o-mini-search-preview, and gpt-4.1 families (including gpt-4.1-mini and gpt-4.1-nano).

Using bve_audio_input to detect inline audio input support

Section titled “Using bve_audio_input to detect inline audio input support”

bve_audio_input: true means the model accepts input_audio content blocks — raw Base64-encoded audio data — as inline input in POST /v1/chat/completions messages. Distinct from TTS models (which generate audio at /v1/audio/speech) and STT models (which transcribe audio files at /v1/audio/transcriptions). Currently covers the gpt-4o-audio-preview and gpt-4o-mini-audio-preview families.

Using bve_tool_use to detect function calling support

Section titled “Using bve_tool_use to detect function calling support”

bve_tool_use: true means the model accepts the tools array parameter in POST /v1/chat/completions for structured function calling. All chat models and OCR models return true. Embedding, TTS, STT, image-generation, and legacy completion-only models return false — sending tools to these models would be rejected by the upstream provider.

Terminal window
curl "https://api.bve.me/admin/model-allowlist/gpt-4o" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"

cURL — inspect an unregistered or unknown model

Section titled “cURL — inspect an unregistered or unknown model”
Terminal window
curl "https://api.bve.me/admin/model-allowlist/some-custom-model" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"

Returns available: false and allowlist: null for models absent from both the static registry and D1. Historical D1 rows may still exist for stale models, but new writes now require the model to be present in the live Fuelix catalog for the current account.


POST https://api.bve.me/admin/model-allowlist
Authorization: Bearer admin_bve_YOUR_ADMIN_KEY
Content-Type: application/json

Creates a new entry or updates enabled if the model is already registered. This operation is idempotent — posting the same model twice simply updates it. The model value must be an exact live Fuelix model ID at write time.

{
"model": "gpt-4o-mini",
"enabled": false
}
FieldTypeRequiredDefaultDescription
modelstringYesExact live Fuelix model ID currently present in GET /v1/models
enabledbooleanNotrueWhether the model is permitted
{
"model": "gpt-4o-mini",
"enabled": false,
"created_at": "2026-05-21T12:00:00.000Z"
}
Terminal window
curl -X POST https://api.bve.me/admin/model-allowlist \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4o-mini", "enabled": false}'
Terminal window
curl -X POST https://api.bve.me/admin/model-allowlist \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4o-mini", "enabled": true}'
DELETE https://api.bve.me/admin/model-allowlist/:model
Authorization: Bearer admin_bve_YOUR_ADMIN_KEY

Removes a model from the D1 global allowlist entirely. After deletion, the model is no longer explicitly tracked as globally allowed or blocked, but requests still remain subject to per-key allowlists and the live Fuelix-backed availability checks. This is also the cleanup path for historical D1 rows that no longer exist in the live Fuelix catalog.

ParameterDescription
modelThe model ID to remove (URL-encode if it contains slashes)
{
"deleted": true,
"model": "gpt-4o-mini"
}
{
"error": {
"message": "Model not found in allowlist",
"type": "invalid_request_error",
"code": "not_found"
}
}
Terminal window
curl -X DELETE "https://api.bve.me/admin/model-allowlist/gpt-4o-mini" \
-H "Authorization: Bearer admin_bve_YOUR_ADMIN_KEY"

The gateway caches allowlist lookups in memory to avoid a D1 query on every request. This uses a Stale-While-Revalidate (SWR) strategy with two TTL thresholds:

Cache typeSoft TTLHard TTL
Per-model lookup (request path)20 s30 s
Full allowlist (GET /v1/models filter)45 s60 s

How SWR works:

  • Within the soft TTL: the cached value is returned immediately (no D1 hit).
  • Between soft and hard TTL: the stale value is returned immediately, and a background D1 refresh is scheduled via ctx.waitUntil so the next request gets the fresh value.
  • Past the hard TTL: the cache entry is evicted and the next request blocks on a synchronous D1 query.

Operational implication: After you disable a model via POST /admin/model-allowlist, in-flight requests in warm isolates may still be accepted for up to 30 seconds before the cache expires. This is by design — it trades strict consistency for lower latency on every request.

If you need immediate enforcement, restart the Worker (via the Cloudflare dashboard or bunx wrangler deploy) to clear all isolate-level caches.

When a JSON request arrives at a /v1/* endpoint, the gateway applies two checks in order:

  1. Global allowlist — if the model appears in this registry with enabled: false, the request is rejected immediately with 403 model_not_available. This check runs for every key.

  2. Per-key allowlist — if the key has a non-null allowed_models array (set via POST /admin/api-keys or PATCH /admin/api-keys/:id), the requested model must match at least one entry in that list. Requests for unlisted models return 403 model_not_allowed.

  3. Default registry + live snapshot availability — if the model is registry_broken, listed_unavailable, or snapshot_excluded, the gateway rejects it with 403 model_not_available even if a D1 allow entry exists. For unknown models, the gateway only allows a D1 override when Fuelix /models currently lists that model live.

If neither check blocks the request, it is forwarded to Fuelix.

Older API keys may still contain allowed_models entries ending with * from before exact-live validation was enforced. The gateway continues to honor those already-stored prefixes at request time so existing keys do not break immediately.

New admin writes do not accept wildcard prefixes. POST /admin/api-keys, PATCH /admin/api-keys/:id, and key clone operations now require every allowed_models entry to be an exact model ID currently present in the live Fuelix /models catalog.

To clean up an older key:

  1. Read its current allowed_models.
  2. Expand each legacy prefix against the current live Fuelix /models response.
  3. Save the resulting exact model IDs back to the key, or set allowed_models to null / [] to remove the restriction entirely.
  • Models not registered in the global allowlist are not blocked by default — only explicitly registered and disabled models are blocked.
  • enabled: true is no longer a standalone routability override. It only prevents a global block; the model must still pass the live Fuelix-backed availability checks before requests can route.
  • New writes validate model IDs against the live Fuelix catalog before saving them. POST /admin/model-allowlist rejects models that are not currently listed by Fuelix for the active account, and it also fails closed when the live Fuelix catalog is unavailable.
  • Legacy wildcard prefixes may still appear on older API key records and continue to match at runtime until the key is normalized, but new admin writes reject them in favor of exact live Fuelix model IDs.
  • bve_category, bve_provider, bve_reasoning, and bve_vision on allowlist endpoints are derived from the gateway’s static registry and do not depend on the D1 allowlist state. They are present even for models with allowlist: null.