Skip to content

API reference — Model catalog

The model catalog is the registry of AI models available in Arbitex. Each entry maps a provider (e.g., anthropic, openai) and a model ID (e.g., claude-3-5-sonnet-20241022) to a set of capabilities and cost metadata. Models must be in the catalog (and have is_active: true) before they can be referenced in routing rules or API requests.

All model catalog endpoints are admin-only. Authentication: Authorization: Bearer arb_live_<admin-key>.

Base path: GET|POST|PUT|DELETE /api/admin/models/catalog


FieldTypeDescription
idUUIDInternal record identifier
providerstringProvider name (e.g., anthropic, openai, azure)
model_idstringProvider-specific model identifier
display_namestringHuman-readable name for UI display
is_activebooleanWhether the model is available for routing
is_defaultbooleanWhether this is the default model for its provider
capabilitiesobjectModel capability flags (see below)
cost_per_input_tokenfloatCost per input token in USD (nullable)
cost_per_output_tokenfloatCost per output token in USD (nullable)
created_atdatetimeISO 8601 creation timestamp

Capabilities object:

FieldTypeDescription
streamingbooleanSupports streaming responses
function_callingbooleanSupports function/tool calling
visionbooleanSupports image inputs
structured_outputbooleanSupports structured JSON output
embeddingsbooleanSupports embeddings generation
max_context_windowintegerMaximum context window in tokens

Returned by /discover — includes catalog membership status:

FieldTypeDescription
providerstringProvider name
model_idstringProvider-specific model ID
display_namestringHuman-readable name
max_tokensintegerMaximum context window
supports_streamingbooleanStreaming support
already_in_catalogbooleanWhether this model is already in the catalog

GET /api/admin/models/catalog/

Returns paginated ModelConfig records with optional filtering.

Query parameters:

ParameterTypeDefaultDescription
pageinteger1Page number (1-based)
page_sizeinteger20Records per page (1–200)
searchstringCase-insensitive substring match against display_name and model_id
providerstringExact provider name filter
is_activebooleanFilter by active status

Request:

Terminal window
GET /api/admin/models/catalog/?provider=anthropic&is_active=true
Authorization: Bearer arb_live_your-admin-key

Response (200):

{
"items": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"provider": "anthropic",
"model_id": "claude-3-5-sonnet-20241022",
"display_name": "Claude 3.5 Sonnet",
"is_active": true,
"is_default": false,
"capabilities": {
"streaming": true,
"function_calling": true,
"vision": true,
"structured_output": true,
"embeddings": false,
"max_context_window": 200000
},
"cost_per_input_token": 0.000003,
"cost_per_output_token": 0.000015,
"created_at": "2026-03-01T00:00:00Z"
}
],
"total": 12,
"page": 1,
"page_size": 20
}

POST /api/admin/models/catalog/

Creates a new ModelConfig record. Returns 409 Conflict if a record with the same provider + model_id already exists.

Request body:

FieldRequiredDescription
providerYesProvider name
model_idYesProvider-specific model ID
display_nameYesHuman-readable name
is_activeNoDefault: true
capabilitiesNoCapability flags object
cost_per_input_tokenNoCost per input token in USD
cost_per_output_tokenNoCost per output token in USD

Request:

Terminal window
POST /api/admin/models/catalog/
Authorization: Bearer arb_live_your-admin-key
Content-Type: application/json
{
"provider": "openai",
"model_id": "gpt-4o-mini",
"display_name": "GPT-4o mini",
"is_active": true,
"capabilities": {
"streaming": true,
"function_calling": true,
"vision": true,
"structured_output": true,
"embeddings": false,
"max_context_window": 128000
},
"cost_per_input_token": 0.00000015,
"cost_per_output_token": 0.0000006
}

Response (201 Created): Returns the created ModelConfig object.

Error (409 Conflict):

{ "detail": "A catalog entry for provider 'openai' and model_id 'gpt-4o-mini' already exists." }

GET /api/admin/models/catalog/{model_config_id}

Response (200): Returns the matching ModelConfig object.

Error (404 Not Found):

{ "detail": "Model catalog entry not found" }

PUT /api/admin/models/catalog/{model_config_id}

Partial update — only non-null fields are applied.

Updatable fields: display_name, is_active, is_default, capabilities, cost_per_input_token, cost_per_output_token.

Request:

Terminal window
PUT /api/admin/models/catalog/3fa85f64-5717-4562-b3fc-2c963f66afa6
Authorization: Bearer arb_live_your-admin-key
Content-Type: application/json
{
"is_active": false,
"cost_per_output_token": 0.000018
}

Response (200): Returns the updated ModelConfig object.


DELETE /api/admin/models/catalog/{model_config_id}

Permanently removes the catalog entry.

Response: 204 No Content

Error (404 Not Found): Entry not found.


GET /api/admin/models/catalog/discover

Queries all registered provider adapters for their available models and returns the results annotated with already_in_catalog. Providers that are unavailable or return an error are skipped (no failure — the response includes results from available providers only).

Request:

Terminal window
GET /api/admin/models/catalog/discover
Authorization: Bearer arb_live_your-admin-key

Response (200):

[
{
"provider": "anthropic",
"model_id": "claude-opus-4-6",
"display_name": "Claude Opus 4.6",
"max_tokens": 200000,
"supports_streaming": true,
"already_in_catalog": false
},
{
"provider": "anthropic",
"model_id": "claude-3-5-sonnet-20241022",
"display_name": "Claude 3.5 Sonnet",
"max_tokens": 200000,
"supports_streaming": true,
"already_in_catalog": true
}
]

Use this endpoint to identify new provider models that have not yet been imported into the catalog.


POST /api/admin/models/catalog/sync

Queries all registered provider adapters (same as /discover) and creates new catalog entries for any provider+model_id pairs not already in the catalog. Existing entries are left unchanged. The operation is idempotent.

Request:

Terminal window
POST /api/admin/models/catalog/sync
Authorization: Bearer arb_live_your-admin-key

Response (200): Returns the list of newly created ModelConfig records. An empty array means all discovered models were already in the catalog.

[
{
"id": "abc12345-...",
"provider": "anthropic",
"model_id": "claude-opus-4-6",
"display_name": "Claude Opus 4.6",
"is_active": true,
"is_default": false,
"capabilities": {
"streaming": true,
"function_calling": false,
"vision": false,
"structured_output": false,
"embeddings": false,
"max_context_window": 200000
},
"cost_per_input_token": null,
"cost_per_output_token": null,
"created_at": "2026-03-12T14:00:00Z"
}
]

PATCH /api/admin/models/catalog/bulk

Sets is_active on multiple catalog entries in a single operation. UUIDs that do not match any record are silently ignored.

Request body:

FieldTypeRequiredDescription
model_idsUUID[]YesList of ModelConfig record UUIDs to update
is_activebooleanYesTarget active state

Request:

Terminal window
PATCH /api/admin/models/catalog/bulk
Authorization: Bearer arb_live_your-admin-key
Content-Type: application/json
{
"model_ids": [
"3fa85f64-5717-4562-b3fc-2c963f66afa6",
"7c8d9e0f-1234-5678-abcd-ef0123456789"
],
"is_active": false
}

Response (200): Returns the list of updated ModelConfig records.


  1. Configure the provider adapter with credentials in the Platform environment.
  2. Call GET /discover to see available models.
  3. Call POST /sync to import them all.
  4. Update cost metadata for billing accuracy: PUT /catalog/{id} with cost_per_input_token and cost_per_output_token.
  5. Verify models appear as routing targets in the admin console.

When a provider retires a model:

  1. PUT /catalog/{id} with { "is_active": false } — existing routing rules will fail over to alternatives.
  2. Update routing rules that reference the deprecated model.
  3. Optionally DELETE /catalog/{id} to remove the record.