{ "components": { "schemas": { "AliasRequest": { "description": "Request to create or update an alias.", "properties": { "name": { "description": "Display name callers use as the model, e.g. 'fast-model'.", "title": "Name", "type": "string" }, "target": { "description": "Selector the alias resolves to, as 'provider:model' or 'instance:model'.", "title": "Target", "type": "string" } }, "required": [ "name", "target" ], "title": "AliasRequest", "type": "object" }, "AliasResponse": { "description": "A model alias and where it is defined.", "properties": { "created_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Created At" }, "name": { "title": "Name", "type": "string" }, "source": { "title": "Source", "type": "string" }, "target": { "title": "Target", "type": "string" }, "updated_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Updated At" } }, "required": [ "name", "target", "source" ], "title": "AliasResponse", "type": "object" }, "AudioSpeechRequest": { "description": "OpenAI-compatible audio speech (TTS) request.\n\nThe speech fields are derived from any-llm's ``AudioSpeechParams`` (see\n``_schema_derive``) so the schema cannot silently drop a param any-llm\nforwards. ``user`` is gateway-only (billing / auth scoping); it is not an\nany-llm param and is stripped before the request is forwarded.", "properties": { "input": { "title": "Input", "type": "string" }, "instructions": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Instructions" }, "model": { "title": "Model", "type": "string" }, "response_format": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Response Format" }, "speed": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Speed" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" }, "voice": { "title": "Voice", "type": "string" } }, "required": [ "model", "input", "voice" ], "title": "AudioSpeechRequest", "type": "object" }, "BatchRequestItem": { "properties": { "body": { "additionalProperties": true, "title": "Body", "type": "object" }, "custom_id": { "title": "Custom Id", "type": "string" } }, "required": [ "custom_id", "body" ], "title": "BatchRequestItem", "type": "object" }, "Body_create_file_v1_files_post": { "properties": { "file": { "contentMediaType": "application/octet-stream", "title": "File", "type": "string" }, "purpose": { "default": "user_data", "title": "Purpose", "type": "string" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "file" ], "title": "Body_create_file_v1_files_post", "type": "object" }, "Body_create_transcription_v1_audio_transcriptions_post": { "properties": { "file": { "contentMediaType": "application/octet-stream", "title": "File", "type": "string" }, "language": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Language" }, "model": { "title": "Model", "type": "string" }, "prompt": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Prompt" }, "response_format": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Response Format" }, "temperature": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Temperature" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "file", "model" ], "title": "Body_create_transcription_v1_audio_transcriptions_post", "type": "object" }, "BudgetResetLogResponse": { "description": "Response model for one budget reset event (per user).", "properties": { "budget_id": { "title": "Budget Id", "type": "string" }, "id": { "title": "Id", "type": "integer" }, "next_reset_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Next Reset At" }, "previous_spend": { "title": "Previous Spend", "type": "number" }, "reset_at": { "title": "Reset At", "type": "string" }, "user_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User Id" } }, "required": [ "id", "user_id", "budget_id", "previous_spend", "reset_at", "next_reset_at" ], "title": "BudgetResetLogResponse", "type": "object" }, "BudgetResponse": { "description": "Response model for budget information.\n\n``max_budget`` is the per-user spending limit, and multiple users can share\none budget, so the usage rollup is an aggregate over the users assigned to\nthis budget: how many there are and their combined ``spend`` / ``reserved``.\nAssigning users to a budget is done through the users API (dashboard support\nlands with user management), so a fresh gateway reports zeros here.", "properties": { "budget_duration_sec": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Budget Duration Sec" }, "budget_id": { "title": "Budget Id", "type": "string" }, "created_at": { "title": "Created At", "type": "string" }, "max_budget": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Max Budget" }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name" }, "total_reserved": { "default": 0.0, "title": "Total Reserved", "type": "number" }, "total_spend": { "default": 0.0, "title": "Total Spend", "type": "number" }, "updated_at": { "title": "Updated At", "type": "string" }, "user_count": { "default": 0, "title": "User Count", "type": "integer" } }, "required": [ "budget_id", "name", "max_budget", "budget_duration_sec", "created_at", "updated_at" ], "title": "BudgetResponse", "type": "object" }, "ChatCompletionRequest": { "description": "OpenAI-compatible chat completion request.\n\nThe completion-param fields are derived from any-llm's ``CompletionParams``\n(see ``_schema_derive``) so the schema cannot silently drop a param any-llm\nforwards. Fields below either tighten a derived field (``messages``,\n``response_format``) or add gateway-internal behavior (``mcp_servers``,\n``mcp_server_ids``, ``guardrails``, ``tools_header``, ``max_tool_iterations``)\nthat is stripped before the request is forwarded upstream.", "properties": { "frequency_penalty": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Frequency Penalty" }, "guardrails": { "anyOf": [ { "items": { "$ref": "#/components/schemas/GuardrailConfig" }, "maxItems": 8, "type": "array" }, { "type": "null" } ], "title": "Guardrails" }, "logit_bias": { "anyOf": [ { "additionalProperties": { "type": "number" }, "type": "object" }, { "type": "null" } ], "title": "Logit Bias" }, "logprobs": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Logprobs" }, "max_completion_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Completion Tokens" }, "max_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Tokens" }, "max_tool_iterations": { "anyOf": [ { "maximum": 25.0, "minimum": 1.0, "type": "integer" }, { "type": "null" } ], "title": "Max Tool Iterations" }, "mcp_server_ids": { "anyOf": [ { "items": { "format": "uuid", "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Mcp Server Ids" }, "mcp_servers": { "anyOf": [ { "items": { "$ref": "#/components/schemas/McpServerConfig" }, "type": "array" }, { "type": "null" } ], "title": "Mcp Servers" }, "messages": { "items": { "additionalProperties": true, "type": "object" }, "minItems": 1, "title": "Messages", "type": "array" }, "model": { "title": "Model", "type": "string" }, "n": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "N" }, "parallel_tool_calls": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Parallel Tool Calls" }, "presence_penalty": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Presence Penalty" }, "reasoning_effort": { "anyOf": [ { "enum": [ "none", "minimal", "low", "medium", "high", "xhigh", "max", "auto" ], "type": "string" }, { "type": "null" } ], "default": "auto", "title": "Reasoning Effort" }, "response_format": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Response Format" }, "seed": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Seed" }, "session_label": { "anyOf": [ { "maxLength": 255, "type": "string" }, { "type": "null" } ], "description": "Optional caller-supplied label for cost attribution (per run, experiment, or conversation). In hybrid mode it is forwarded onto the platform usage report so spend can be sliced by session without standing up OpenTelemetry. Stripped before the request is forwarded upstream to the provider. Has no effect in standalone mode, where there is no platform to report it to.", "title": "Session Label" }, "stop": { "anyOf": [ { "type": "string" }, { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Stop" }, "stream": { "default": false, "title": "Stream", "type": "boolean" }, "stream_options": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Stream Options" }, "temperature": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Temperature" }, "tool_choice": { "anyOf": [ { "type": "string" }, { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Tool Choice" }, "tools": { "anyOf": [ { "items": { "anyOf": [ { "additionalProperties": true, "type": "object" }, {} ] }, "type": "array" }, { "type": "null" } ], "title": "Tools" }, "tools_header": { "anyOf": [ { "maxLength": 4000, "type": "string" }, { "type": "null" } ], "description": "Optional override for the lead-in that the gateway prepends before the per-tool hint block in the system message. Useful for expressing global tool-selection policy (e.g. 'prefer MCP tools over code_execution'). Falls back to OTARI_TOOLS_HEADER env, then to the built-in default.", "title": "Tools Header" }, "top_logprobs": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Top Logprobs" }, "top_p": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Top P" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "model", "messages" ], "title": "ChatCompletionRequest", "type": "object" }, "ConfigField": { "description": "One effective config value surfaced to the dashboard's config viewer.", "properties": { "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description" }, "exclusive_minimum": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Exclusive Minimum" }, "group": { "title": "Group", "type": "string" }, "key": { "title": "Key", "type": "string" }, "minimum": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Minimum" }, "options": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Options" }, "settable": { "title": "Settable", "type": "boolean" }, "type": { "enum": [ "bool", "int", "float", "str", "list" ], "title": "Type", "type": "string" }, "value": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "type": "string" }, { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Value" } }, "required": [ "key", "value", "type", "settable", "group" ], "title": "ConfigField", "type": "object" }, "CountTokensRequest": { "description": "Anthropic ``/v1/messages/count_tokens`` request.\n\nA subset of :class:`MessagesRequest`: the input fields that affect the token\ncount, minus ``max_tokens`` and the streaming/sampling controls, since the\nendpoint only counts input tokens. Clients such as Claude Code call this on\nevery turn to keep their prompt within the model's context window.", "properties": { "cache_control": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Cache Control" }, "messages": { "items": { "additionalProperties": true, "type": "object" }, "minItems": 1, "title": "Messages", "type": "array" }, "metadata": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Metadata" }, "model": { "title": "Model", "type": "string" }, "system": { "anyOf": [ { "type": "string" }, { "items": { "additionalProperties": true, "type": "object" }, "type": "array" }, { "type": "null" } ], "title": "System" }, "thinking": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Thinking" }, "tool_choice": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Tool Choice" }, "tools": { "anyOf": [ { "items": { "additionalProperties": true, "type": "object" }, "type": "array" }, { "type": "null" } ], "title": "Tools" } }, "required": [ "model", "messages" ], "title": "CountTokensRequest", "type": "object" }, "CountTokensResponse": { "description": "Anthropic ``/v1/messages/count_tokens`` response.", "properties": { "input_tokens": { "title": "Input Tokens", "type": "integer" } }, "required": [ "input_tokens" ], "title": "CountTokensResponse", "type": "object" }, "CreateBatchRequest": { "properties": { "completion_window": { "default": "24h", "title": "Completion Window", "type": "string" }, "metadata": { "anyOf": [ { "additionalProperties": { "type": "string" }, "type": "object" }, { "type": "null" } ], "title": "Metadata" }, "model": { "title": "Model", "type": "string" }, "requests": { "items": { "$ref": "#/components/schemas/BatchRequestItem" }, "maxItems": 10000, "minItems": 1, "title": "Requests", "type": "array" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "model", "requests" ], "title": "CreateBatchRequest", "type": "object" }, "CreateBudgetRequest": { "description": "Request model for creating a new budget.", "properties": { "budget_duration_sec": { "anyOf": [ { "exclusiveMinimum": 0.0, "type": "integer" }, { "type": "null" } ], "description": "Budget duration in seconds (e.g., 86400 for daily, 604800 for weekly)", "title": "Budget Duration Sec" }, "max_budget": { "anyOf": [ { "minimum": 0.0, "type": "number" }, { "type": "null" } ], "description": "Maximum spending limit", "title": "Max Budget" }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Admin-facing label for the budget", "title": "Name" } }, "title": "CreateBudgetRequest", "type": "object" }, "CreateKeyRequest": { "description": "Request model for creating a new API key.", "properties": { "allowed_models": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "description": "Model allow-list: null = any model, [] = deny all, or canonical instance:model entries (with instance:* / instance:prefix* wildcards).", "title": "Allowed Models" }, "expires_at": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Optional expiration timestamp", "title": "Expires At" }, "key_name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional name for the key", "title": "Key Name" }, "metadata": { "additionalProperties": true, "description": "Optional metadata", "title": "Metadata", "type": "object" }, "user_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional user ID to associate with this key", "title": "User Id" } }, "title": "CreateKeyRequest", "type": "object" }, "CreateKeyResponse": { "description": "Response model for creating a new API key.", "properties": { "allowed_models": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Models" }, "created_at": { "title": "Created At", "type": "string" }, "expires_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Expires At" }, "id": { "title": "Id", "type": "string" }, "is_active": { "title": "Is Active", "type": "boolean" }, "key": { "title": "Key", "type": "string" }, "key_name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Key Name" }, "key_prefix": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Key Prefix" }, "metadata": { "additionalProperties": true, "title": "Metadata", "type": "object" }, "user_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User Id" } }, "required": [ "id", "key", "key_prefix", "key_name", "user_id", "created_at", "expires_at", "is_active", "allowed_models", "metadata" ], "title": "CreateKeyResponse", "type": "object" }, "CreateStoredProviderRequest": { "description": "Create a stored provider. ``api_key`` is write-only and requires OTARI_SECRET_KEY.", "properties": { "api_base": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Base" }, "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Provider API key. Stored encrypted; never returned.", "title": "Api Key" }, "client_args": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Client Args" }, "instance": { "description": "Routing key, e.g. 'openai' or a named instance like 'home_lab'.", "minLength": 1, "title": "Instance", "type": "string" }, "provider_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "any-llm implementation when the instance name is not itself one.", "title": "Provider Type" } }, "required": [ "instance" ], "title": "CreateStoredProviderRequest", "type": "object" }, "CreateUserRequest": { "description": "Request model for creating a new user.", "properties": { "alias": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional admin-facing alias", "title": "Alias" }, "allowed_models": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "description": "Default model access-list this user's keys inherit; null = unrestricted, [] = deny all", "title": "Allowed Models" }, "blocked": { "default": false, "description": "Whether user is blocked", "title": "Blocked", "type": "boolean" }, "budget_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional budget ID", "title": "Budget Id" }, "metadata": { "additionalProperties": true, "description": "Optional metadata", "title": "Metadata", "type": "object" }, "user_id": { "description": "Unique user identifier", "title": "User Id", "type": "string" } }, "required": [ "user_id" ], "title": "CreateUserRequest", "type": "object" }, "DiscoverableModel": { "description": "A model one provider instance reports as available.", "properties": { "id": { "description": "Bare model id as the provider reports it.", "title": "Id", "type": "string" }, "key": { "description": "Selector to send as `model`, in `instance:model` form.", "title": "Key", "type": "string" } }, "required": [ "id", "key" ], "title": "DiscoverableModel", "type": "object" }, "DiscoverableModelsResponse": { "description": "Per-provider discovery results for operator model selection.", "properties": { "providers": { "items": { "$ref": "#/components/schemas/DiscoverableProvider" }, "title": "Providers", "type": "array" } }, "required": [ "providers" ], "title": "DiscoverableModelsResponse", "type": "object" }, "DiscoverableProvider": { "description": "One provider instance's discovery result.", "properties": { "error": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Why discovery failed. Null when `ok` is true.", "title": "Error" }, "models": { "items": { "$ref": "#/components/schemas/DiscoverableModel" }, "title": "Models", "type": "array" }, "ok": { "description": "False when this instance could not be queried.", "title": "Ok", "type": "boolean" }, "provider": { "title": "Provider", "type": "string" } }, "required": [ "provider", "ok", "models" ], "title": "DiscoverableProvider", "type": "object" }, "EmbeddingRequest": { "description": "OpenAI-compatible embedding request.", "properties": { "dimensions": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Dimensions" }, "encoding_format": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Encoding Format" }, "input": { "anyOf": [ { "type": "string" }, { "items": { "type": "string" }, "type": "array" } ], "description": "Input text to embed", "title": "Input" }, "model": { "title": "Model", "type": "string" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "model", "input" ], "title": "EmbeddingRequest", "type": "object" }, "GatewaySettings": { "description": "Operator-facing runtime settings surfaced to the dashboard.\n\nThe top-level flags are kept for the callers that read them directly\n(pricing warnings, the models/providers pages); ``config`` is the full\nread-only view with the settable/startup-only marking.", "properties": { "config": { "items": { "$ref": "#/components/schemas/ConfigField" }, "title": "Config", "type": "array" }, "default_pricing": { "title": "Default Pricing", "type": "boolean" }, "master_key_source": { "description": "Whether the dashboard master key is configured at startup or generated and stored by Otari.", "enum": [ "configured", "generated" ], "title": "Master Key Source", "type": "string" }, "mode": { "title": "Mode", "type": "string" }, "model_discovery": { "title": "Model Discovery", "type": "boolean" }, "require_pricing": { "title": "Require Pricing", "type": "boolean" }, "version": { "title": "Version", "type": "string" } }, "required": [ "mode", "version", "model_discovery", "default_pricing", "require_pricing", "master_key_source", "config" ], "title": "GatewaySettings", "type": "object" }, "GuardrailConfig": { "description": "A single guardrail check the caller wants the gateway to enforce.\n\nURL safety: when ``url`` is supplied it is validated by\n:func:`gateway.services.guardrails.run_input_guardrails` (not here at parse\ntime \u2014 the check does a DNS lookup that must be awaited) with the same\nSSRF guard used for MCP server URLs (loopback allowed by default for\nsame-host sidecars; gated by ``OTARI_MCP_ALLOW_LOOPBACK`` /\n``OTARI_MCP_ALLOW_PRIVATE_HOSTS``). Most deployments omit ``url`` and rely\non the operator-set ``OTARI_GUARDRAILS_URL`` instead.", "properties": { "mode": { "default": "monitor", "enum": [ "block", "monitor" ], "title": "Mode", "type": "string" }, "on": { "items": { "enum": [ "input", "output" ], "type": "string" }, "title": "On", "type": "array" }, "profile": { "maxLength": 128, "minLength": 1, "title": "Profile", "type": "string" }, "url": { "anyOf": [ { "minLength": 1, "type": "string" }, { "type": "null" } ], "title": "Url" }, "validate_kwargs": { "additionalProperties": true, "title": "Validate Kwargs", "type": "object" } }, "required": [ "profile" ], "title": "GuardrailConfig", "type": "object" }, "HTTPValidationError": { "properties": { "detail": { "items": { "$ref": "#/components/schemas/ValidationError" }, "title": "Detail", "type": "array" } }, "title": "HTTPValidationError", "type": "object" }, "ImageGenerationRequest": { "description": "OpenAI-compatible image generation request.\n\nFields are derived from any-llm's ``ImageGenerationParams`` (see\n``_schema_derive``) so the schema cannot silently drop a param any-llm\nforwards.", "properties": { "model": { "title": "Model", "type": "string" }, "n": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "N" }, "prompt": { "title": "Prompt", "type": "string" }, "quality": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Quality" }, "response_format": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Response Format" }, "size": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Size" }, "style": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Style" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "model", "prompt" ], "title": "ImageGenerationRequest", "type": "object" }, "KeyInfo": { "description": "Response model for key information.", "properties": { "allowed_models": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Models" }, "created_at": { "title": "Created At", "type": "string" }, "expires_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Expires At" }, "id": { "title": "Id", "type": "string" }, "is_active": { "title": "Is Active", "type": "boolean" }, "key_name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Key Name" }, "key_prefix": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Key Prefix" }, "last_used_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Last Used At" }, "metadata": { "additionalProperties": true, "title": "Metadata", "type": "object" }, "user_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User Id" } }, "required": [ "id", "key_prefix", "key_name", "user_id", "created_at", "last_used_at", "expires_at", "is_active", "allowed_models", "metadata" ], "title": "KeyInfo", "type": "object" }, "KnownProviderSchema": { "description": "A provider the add-provider picker can offer, with autofill hints.", "properties": { "default_api_base": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Built-in endpoint; blank means the SDK's default.", "title": "Default Api Base" }, "env_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Env var the SDK reads this provider's key from.", "title": "Env Key" }, "env_key_present": { "default": false, "description": "True when env_key is already set on the server, so a pasted key is optional (env fallback).", "title": "Env Key Present", "type": "boolean" }, "id": { "description": "any-llm provider id, used as the default instance name.", "title": "Id", "type": "string" }, "name": { "description": "Human-friendly display name.", "title": "Name", "type": "string" }, "requires_api_key": { "description": "False for keyless local backends (Ollama, llama.cpp).", "title": "Requires Api Key", "type": "boolean" } }, "required": [ "id", "name", "requires_api_key" ], "title": "KnownProviderSchema", "type": "object" }, "McpServerConfig": { "description": "Inline MCP server configuration accepted on the chat completions request.\n\nStreamable HTTP transport. The `url` must be reachable from the gateway process.\n\nURL safety (SSRF guard against private/link-local/reserved IP ranges, plus\nrejecting plain ``http://`` when ``authorization_token`` is set) is\nenforced by :func:`gateway.services.url_safety.validate_mcp_url`, called\nfrom the async request pipeline (``prepare_gateway_tools``) rather than\nhere at parse time: the safety check does a DNS lookup, which must be\nawaited so it can't block the event loop, and Pydantic validators run\nsynchronously during request-body parsing.", "properties": { "allowed_tools": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Tools" }, "authorization_token": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Authorization Token" }, "name": { "maxLength": 128, "minLength": 1, "title": "Name", "type": "string" }, "purpose_hint": { "anyOf": [ { "maxLength": 2000, "type": "string" }, { "type": "null" } ], "title": "Purpose Hint" }, "url": { "minLength": 1, "title": "Url", "type": "string" } }, "required": [ "name", "url" ], "title": "McpServerConfig", "type": "object" }, "MessagesRequest": { "description": "Anthropic Messages API-compatible request.\n\nThe wire fields are derived from any-llm's ``MessagesParams`` (see\n``_schema_derive``) so the schema cannot silently drop a param any-llm\nforwards. Gateway-internal fields (``mcp_servers``, ``mcp_server_ids``,\n``guardrails``, ``tools_header``, ``max_tool_iterations``) opt the request\ninto gateway-managed MCP / sandbox / web_search / guardrails without\nchanging the upstream wire shape. They're stripped before the request is\nforwarded.", "properties": { "cache_control": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Cache Control" }, "guardrails": { "anyOf": [ { "items": { "$ref": "#/components/schemas/GuardrailConfig" }, "maxItems": 8, "type": "array" }, { "type": "null" } ], "title": "Guardrails" }, "max_tokens": { "title": "Max Tokens", "type": "integer" }, "max_tool_iterations": { "anyOf": [ { "maximum": 25.0, "minimum": 1.0, "type": "integer" }, { "type": "null" } ], "title": "Max Tool Iterations" }, "mcp_server_ids": { "anyOf": [ { "items": { "format": "uuid", "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Mcp Server Ids" }, "mcp_servers": { "anyOf": [ { "items": { "$ref": "#/components/schemas/McpServerConfig" }, "type": "array" }, { "type": "null" } ], "title": "Mcp Servers" }, "messages": { "items": { "additionalProperties": true, "type": "object" }, "minItems": 1, "title": "Messages", "type": "array" }, "metadata": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Metadata" }, "model": { "title": "Model", "type": "string" }, "output_format": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Output Format" }, "session_label": { "anyOf": [ { "maxLength": 255, "type": "string" }, { "type": "null" } ], "description": "Optional caller-supplied label for cost attribution (per run, experiment, or conversation). In hybrid mode it is forwarded onto the platform usage report so spend can be sliced by session without standing up OpenTelemetry. Stripped before the request is forwarded upstream to the provider. Has no effect in standalone mode, where there is no platform to report it to.", "title": "Session Label" }, "stop_sequences": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Stop Sequences" }, "stream": { "default": false, "title": "Stream", "type": "boolean" }, "system": { "anyOf": [ { "type": "string" }, { "items": { "additionalProperties": true, "type": "object" }, "type": "array" }, { "type": "null" } ], "title": "System" }, "temperature": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Temperature" }, "thinking": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Thinking" }, "tool_choice": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Tool Choice" }, "tools": { "anyOf": [ { "items": { "additionalProperties": true, "type": "object" }, "type": "array" }, { "type": "null" } ], "title": "Tools" }, "tools_header": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tools Header" }, "top_k": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Top K" }, "top_p": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Top P" } }, "required": [ "model", "messages", "max_tokens" ], "title": "MessagesRequest", "type": "object" }, "ModelListResponse": { "description": "OpenAI-compatible model list response.", "properties": { "data": { "items": { "$ref": "#/components/schemas/ModelObject" }, "title": "Data", "type": "array" }, "object": { "default": "list", "title": "Object", "type": "string" } }, "required": [ "data" ], "title": "ModelListResponse", "type": "object" }, "ModelMetadata": { "description": "models.dev metadata for one model, for the dashboard's detail view.", "properties": { "attachment": { "default": false, "title": "Attachment", "type": "boolean" }, "context_window": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Context Window" }, "cost_input": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cost Input" }, "cost_output": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cost Output" }, "deprecated": { "default": false, "title": "Deprecated", "type": "boolean" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description" }, "family": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Family" }, "input_modalities": { "items": { "type": "string" }, "title": "Input Modalities", "type": "array" }, "knowledge_cutoff": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Knowledge Cutoff" }, "last_updated": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Last Updated" }, "max_output_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Output Tokens" }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name" }, "open_weights": { "default": false, "title": "Open Weights", "type": "boolean" }, "output_modalities": { "items": { "type": "string" }, "title": "Output Modalities", "type": "array" }, "reasoning": { "default": false, "title": "Reasoning", "type": "boolean" }, "release_date": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Release Date" }, "structured_output": { "default": false, "title": "Structured Output", "type": "boolean" }, "temperature": { "default": false, "title": "Temperature", "type": "boolean" }, "tool_call": { "default": false, "title": "Tool Call", "type": "boolean" } }, "title": "ModelMetadata", "type": "object" }, "ModelMetadataResponse": { "description": "models.dev metadata keyed by ``provider:model``.", "properties": { "available": { "description": "False when metadata could not be loaded (enrichment disabled or models.dev unreachable).", "title": "Available", "type": "boolean" }, "models": { "additionalProperties": { "$ref": "#/components/schemas/ModelMetadata" }, "title": "Models", "type": "object" }, "source": { "default": "models.dev", "title": "Source", "type": "string" } }, "required": [ "available" ], "title": "ModelMetadataResponse", "type": "object" }, "ModelObject": { "description": "OpenAI-compatible model object.", "properties": { "context_window": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Context Window" }, "created": { "title": "Created", "type": "integer" }, "id": { "title": "Id", "type": "string" }, "object": { "default": "model", "title": "Object", "type": "string" }, "owned_by": { "title": "Owned By", "type": "string" }, "pricing": { "anyOf": [ { "$ref": "#/components/schemas/ModelPricingInfo" }, { "type": "null" } ] }, "pricing_source": { "default": "none", "title": "Pricing Source", "type": "string" } }, "required": [ "id", "created", "owned_by" ], "title": "ModelObject", "type": "object" }, "ModelPricingInfo": { "description": "Pricing information for a model.", "properties": { "cache_read_price_per_million": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cache Read Price Per Million" }, "cache_write_price_per_million": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cache Write Price Per Million" }, "input_price_per_million": { "title": "Input Price Per Million", "type": "number" }, "output_price_per_million": { "title": "Output Price Per Million", "type": "number" } }, "required": [ "input_price_per_million", "output_price_per_million" ], "title": "ModelPricingInfo", "type": "object" }, "ModerationRequest": { "description": "OpenAI-compatible moderation request.", "properties": { "input": { "anyOf": [ { "type": "string" }, { "items": { "type": "string" }, "type": "array" }, { "items": { "additionalProperties": true, "type": "object" }, "type": "array" } ], "description": "Text, list of texts, or list of content-part dicts to moderate", "title": "Input" }, "model": { "title": "Model", "type": "string" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "model", "input" ], "title": "ModerationRequest", "type": "object" }, "ModerationResponse": { "description": "Normalized moderation response across providers.", "properties": { "id": { "title": "Id", "type": "string" }, "model": { "title": "Model", "type": "string" }, "results": { "items": { "$ref": "#/components/schemas/ModerationResult" }, "title": "Results", "type": "array" } }, "required": [ "id", "model", "results" ], "title": "ModerationResponse", "type": "object" }, "ModerationResult": { "description": "A single moderation decision, typically one per input item.", "properties": { "categories": { "additionalProperties": { "type": "boolean" }, "title": "Categories", "type": "object" }, "category_applied_input_types": { "anyOf": [ { "additionalProperties": { "items": { "type": "string" }, "type": "array" }, "type": "object" }, { "type": "null" } ], "title": "Category Applied Input Types" }, "category_scores": { "additionalProperties": { "type": "number" }, "title": "Category Scores", "type": "object" }, "flagged": { "title": "Flagged", "type": "boolean" }, "provider_raw": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Provider Raw" } }, "required": [ "flagged" ], "title": "ModerationResult", "type": "object" }, "PricingRefreshChangeResponse": { "description": "One default model price changed by a pending refresh.", "properties": { "change": { "title": "Change", "type": "string" }, "model_key": { "title": "Model Key", "type": "string" } }, "required": [ "model_key", "change" ], "title": "PricingRefreshChangeResponse", "type": "object" }, "PricingRefreshConfirmationResponse": { "description": "Result of activating a reviewed genai-prices refresh.", "properties": { "applied": { "default": true, "title": "Applied", "type": "boolean" } }, "title": "PricingRefreshConfirmationResponse", "type": "object" }, "PricingRefreshPreviewResponse": { "description": "Reviewable summary of a pending genai-prices refresh.", "properties": { "added_count": { "title": "Added Count", "type": "integer" }, "changed_count": { "title": "Changed Count", "type": "integer" }, "changes": { "items": { "$ref": "#/components/schemas/PricingRefreshChangeResponse" }, "title": "Changes", "type": "array" }, "changes_truncated": { "title": "Changes Truncated", "type": "boolean" }, "fetched_at": { "format": "date-time", "title": "Fetched At", "type": "string" }, "protected_model_count": { "title": "Protected Model Count", "type": "integer" }, "removed_count": { "title": "Removed Count", "type": "integer" } }, "required": [ "fetched_at", "added_count", "changed_count", "removed_count", "protected_model_count", "changes", "changes_truncated" ], "title": "PricingRefreshPreviewResponse", "type": "object" }, "PricingResponse": { "description": "Response model for model pricing.", "properties": { "cache_read_price_per_million": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cache Read Price Per Million" }, "cache_write_price_per_million": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cache Write Price Per Million" }, "created_at": { "title": "Created At", "type": "string" }, "effective_at": { "title": "Effective At", "type": "string" }, "input_price_per_million": { "title": "Input Price Per Million", "type": "number" }, "model_key": { "title": "Model Key", "type": "string" }, "output_price_per_million": { "title": "Output Price Per Million", "type": "number" }, "updated_at": { "title": "Updated At", "type": "string" } }, "required": [ "model_key", "effective_at", "input_price_per_million", "output_price_per_million", "cache_read_price_per_million", "cache_write_price_per_million", "created_at", "updated_at" ], "title": "PricingResponse", "type": "object" }, "ProviderCapabilitiesSchema": { "description": "Curated capability flags for a provider.", "properties": { "audio": { "title": "Audio", "type": "boolean" }, "embeddings": { "title": "Embeddings", "type": "boolean" }, "image_generation": { "title": "Image Generation", "type": "boolean" }, "list_models": { "title": "List Models", "type": "boolean" }, "moderation": { "title": "Moderation", "type": "boolean" }, "pdf": { "title": "Pdf", "type": "boolean" }, "reasoning": { "title": "Reasoning", "type": "boolean" }, "rerank": { "title": "Rerank", "type": "boolean" }, "responses_api": { "title": "Responses Api", "type": "boolean" }, "streaming": { "title": "Streaming", "type": "boolean" }, "vision": { "title": "Vision", "type": "boolean" } }, "required": [ "streaming", "reasoning", "vision", "pdf", "embeddings", "image_generation", "audio", "rerank", "responses_api", "moderation", "list_models" ], "title": "ProviderCapabilitiesSchema", "type": "object" }, "ProviderHealthResponse": { "description": "Provider connectivity across the whole gateway, for the health monitor.\n\nCarries per-provider results plus the ``healthy`` / ``total`` counts and the\nmost recent ``checked_at`` so the overview page can render a summary tile\nwithout re-deriving them.", "properties": { "checked_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "ISO 8601 time of the most recent per-provider check (null if none yet).", "title": "Checked At" }, "healthy": { "description": "How many providers are currently reachable.", "title": "Healthy", "type": "integer" }, "providers": { "items": { "$ref": "#/components/schemas/ProviderHealthSchema" }, "title": "Providers", "type": "array" }, "total": { "description": "How many providers are configured.", "title": "Total", "type": "integer" } }, "required": [ "providers", "healthy", "total" ], "title": "ProviderHealthResponse", "type": "object" }, "ProviderHealthSchema": { "description": "One provider instance's reachability, from the model-discovery test path.", "properties": { "checked_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "ISO 8601 wall-clock time the provider's reachability was last checked (null if never).", "title": "Checked At" }, "error": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Sanitized provider error when unreachable.", "title": "Error" }, "instance": { "title": "Instance", "type": "string" }, "model_count": { "description": "Number of models the last successful listing returned.", "title": "Model Count", "type": "integer" }, "ok": { "description": "True when the provider's credentials could list models.", "title": "Ok", "type": "boolean" } }, "required": [ "instance", "ok", "model_count" ], "title": "ProviderHealthSchema", "type": "object" }, "ProviderInfoSchema": { "description": "Static, network-free metadata for one configured provider instance.", "properties": { "capabilities": { "$ref": "#/components/schemas/ProviderCapabilitiesSchema" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description" }, "doc_url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Doc Url" }, "env_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Env var the credential is read from.", "title": "Env Key" }, "instance": { "description": "Configured provider key (may differ from the type).", "title": "Instance", "type": "string" }, "name": { "description": "Human-friendly provider name.", "title": "Name", "type": "string" }, "pricing_urls": { "items": { "type": "string" }, "title": "Pricing Urls", "type": "array" }, "provider_type": { "description": "Underlying any-llm provider type.", "title": "Provider Type", "type": "string" } }, "required": [ "instance", "provider_type", "name", "capabilities" ], "title": "ProviderInfoSchema", "type": "object" }, "ProvidersResponse": { "description": "Metadata for every configured provider.", "properties": { "providers": { "items": { "$ref": "#/components/schemas/ProviderInfoSchema" }, "title": "Providers", "type": "array" } }, "required": [ "providers" ], "title": "ProvidersResponse", "type": "object" }, "ReencryptProviderCredentialsResponse": { "description": "Result of re-encrypting stored provider keys with the primary secret key.", "properties": { "reencrypted": { "description": "Number of stored provider keys re-encrypted.", "title": "Reencrypted", "type": "integer" }, "unreadable": { "description": "Number of encrypted keys left untouched because they could not be decrypted.", "title": "Unreadable", "type": "integer" } }, "required": [ "reencrypted", "unreadable" ], "title": "ReencryptProviderCredentialsResponse", "type": "object" }, "RerankRequest": { "description": "Rerank request.", "properties": { "documents": { "description": "List of document strings to rerank", "items": { "type": "string" }, "minItems": 1, "title": "Documents", "type": "array" }, "max_tokens_per_doc": { "anyOf": [ { "exclusiveMinimum": 0.0, "type": "integer" }, { "type": "null" } ], "description": "Per-document truncation limit", "title": "Max Tokens Per Doc" }, "model": { "description": "Provider-prefixed model ID, e.g. 'cohere:rerank-v3.5'", "title": "Model", "type": "string" }, "query": { "description": "The search query to rerank documents against", "title": "Query", "type": "string" }, "top_n": { "anyOf": [ { "exclusiveMinimum": 0.0, "type": "integer" }, { "type": "null" } ], "description": "Maximum number of results to return", "title": "Top N" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "User ID for usage attribution", "title": "User" } }, "required": [ "model", "query", "documents" ], "title": "RerankRequest", "type": "object" }, "ResponsesRequest": { "additionalProperties": true, "description": "OpenAI Responses API-compatible request.\n\nThe wire fields are derived from any-llm's ``ResponsesParams`` (see\n``_schema_derive``) so the schema cannot silently drop a param any-llm\nforwards. Gateway-internal fields (``mcp_servers``, ``mcp_server_ids``,\n``guardrails``, ``tools_header``, ``max_tool_iterations``) opt the request\ninto gateway-managed MCP / sandbox / web_search / guardrails without\nchanging the upstream wire shape. They're stripped before the request is\nforwarded.", "properties": { "background": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Background" }, "conversation": { "anyOf": [ { "type": "string" }, { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Conversation" }, "frequency_penalty": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Frequency Penalty" }, "guardrails": { "anyOf": [ { "items": { "$ref": "#/components/schemas/GuardrailConfig" }, "maxItems": 8, "type": "array" }, { "type": "null" } ], "title": "Guardrails" }, "include": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Include" }, "input": { "title": "Input" }, "instructions": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Instructions" }, "max_output_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Output Tokens" }, "max_tool_calls": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Tool Calls" }, "max_tool_iterations": { "anyOf": [ { "maximum": 25.0, "minimum": 1.0, "type": "integer" }, { "type": "null" } ], "title": "Max Tool Iterations" }, "mcp_server_ids": { "anyOf": [ { "items": { "format": "uuid", "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Mcp Server Ids" }, "mcp_servers": { "anyOf": [ { "items": { "$ref": "#/components/schemas/McpServerConfig" }, "type": "array" }, { "type": "null" } ], "title": "Mcp Servers" }, "metadata": { "anyOf": [ { "additionalProperties": { "type": "string" }, "type": "object" }, { "type": "null" } ], "title": "Metadata" }, "model": { "title": "Model", "type": "string" }, "parallel_tool_calls": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Parallel Tool Calls" }, "presence_penalty": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Presence Penalty" }, "previous_response_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Previous Response Id" }, "prompt_cache_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Prompt Cache Key" }, "prompt_cache_retention": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Prompt Cache Retention" }, "reasoning": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Reasoning" }, "response_format": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Response Format" }, "safety_identifier": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Safety Identifier" }, "service_tier": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Service Tier" }, "session_label": { "anyOf": [ { "maxLength": 255, "type": "string" }, { "type": "null" } ], "description": "Optional caller-supplied label for cost attribution (per run, experiment, or conversation). In hybrid mode it is forwarded onto the platform usage report so spend can be sliced by session without standing up OpenTelemetry. Stripped before the request is forwarded upstream to the provider. Has no effect in standalone mode, where there is no platform to report it to.", "title": "Session Label" }, "store": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Store" }, "stream": { "default": false, "title": "Stream", "type": "boolean" }, "stream_options": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Stream Options" }, "temperature": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Temperature" }, "text": { "anyOf": [ {}, { "type": "null" } ], "title": "Text" }, "tool_choice": { "anyOf": [ { "type": "string" }, { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Tool Choice" }, "tools": { "anyOf": [ { "items": { "additionalProperties": true, "type": "object" }, "type": "array" }, { "type": "null" } ], "title": "Tools" }, "tools_header": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tools Header" }, "top_logprobs": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Top Logprobs" }, "top_p": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Top P" }, "truncation": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Truncation" }, "user": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, "required": [ "model", "input" ], "title": "ResponsesRequest", "type": "object" }, "RotateMasterKeyResponse": { "description": "A newly generated dashboard master key, returned once.", "properties": { "master_key": { "description": "The new plaintext master key. Store it now; it is never returned again.", "title": "Master Key", "type": "string" } }, "required": [ "master_key" ], "title": "RotateMasterKeyResponse", "type": "object" }, "SetPricingRequest": { "description": "Request model for setting model pricing.", "properties": { "cache_read_price_per_million": { "anyOf": [ { "minimum": 0.0, "type": "number" }, { "type": "null" } ], "description": "Price per 1M cached-input tokens", "title": "Cache Read Price Per Million" }, "cache_write_price_per_million": { "anyOf": [ { "minimum": 0.0, "type": "number" }, { "type": "null" } ], "description": "Price per 1M cache-write (creation) tokens", "title": "Cache Write Price Per Million" }, "effective_at": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "ISO 8601 datetime from which this price applies. Defaults to now if omitted.", "title": "Effective At" }, "input_price_per_million": { "description": "Price per 1M input tokens", "minimum": 0.0, "title": "Input Price Per Million", "type": "number" }, "model_key": { "description": "Model identifier in format 'provider:model'", "title": "Model Key", "type": "string" }, "output_price_per_million": { "description": "Price per 1M output tokens", "minimum": 0.0, "title": "Output Price Per Million", "type": "number" } }, "required": [ "model_key", "input_price_per_million", "output_price_per_million" ], "title": "SetPricingRequest", "type": "object" }, "StoredProviderResponse": { "description": "A runtime-stored provider. The API key is never returned, only ``last4``.", "properties": { "api_base": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Base" }, "client_args": { "additionalProperties": true, "title": "Client Args", "type": "object" }, "created_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Created At" }, "decryptable": { "default": true, "title": "Decryptable", "type": "boolean" }, "instance": { "title": "Instance", "type": "string" }, "last4": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Last4" }, "provider_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Provider Type" }, "updated_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Updated At" } }, "required": [ "instance" ], "title": "StoredProviderResponse", "type": "object" }, "TestProviderRequest": { "description": "Credentials to test before saving (from the add-provider form).", "properties": { "api_base": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Base" }, "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Key" }, "client_args": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Client Args" }, "instance": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Provider/instance name; the impl when no provider_type.", "title": "Instance" }, "provider_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Provider Type" } }, "title": "TestProviderRequest", "type": "object" }, "TestProviderResponse": { "description": "Result of a live provider connection test.", "properties": { "error": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Error" }, "model_count": { "title": "Model Count", "type": "integer" }, "ok": { "title": "Ok", "type": "boolean" } }, "required": [ "ok", "model_count" ], "title": "TestProviderResponse", "type": "object" }, "TestServiceRequest": { "description": "A (typically unsaved) URL to probe for reachability.", "properties": { "url": { "title": "Url", "type": "string" } }, "required": [ "url" ], "title": "TestServiceRequest", "type": "object" }, "TestServiceResponse": { "properties": { "ok": { "title": "Ok", "type": "boolean" }, "reason": { "title": "Reason", "type": "string" } }, "required": [ "ok", "reason" ], "title": "TestServiceResponse", "type": "object" }, "ToolSettingField": { "description": "One editable tool/guardrail field surfaced to the dashboard.", "properties": { "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description" }, "key": { "title": "Key", "type": "string" }, "service": { "enum": [ "web_search", "sandbox", "guardrails" ], "title": "Service", "type": "string" }, "type": { "enum": [ "url", "str", "int", "bool" ], "title": "Type", "type": "string" }, "value": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "string" }, { "type": "null" } ], "title": "Value" } }, "required": [ "key", "service", "type", "value" ], "title": "ToolSettingField", "type": "object" }, "ToolSettingsResponse": { "description": "The effective value of every editable tool/guardrail field.", "properties": { "fields": { "items": { "$ref": "#/components/schemas/ToolSettingField" }, "title": "Fields", "type": "array" } }, "required": [ "fields" ], "title": "ToolSettingsResponse", "type": "object" }, "UpdateBudgetRequest": { "description": "Request model for updating a budget.", "properties": { "budget_duration_sec": { "anyOf": [ { "exclusiveMinimum": 0.0, "type": "integer" }, { "type": "null" } ], "title": "Budget Duration Sec" }, "max_budget": { "anyOf": [ { "minimum": 0.0, "type": "number" }, { "type": "null" } ], "title": "Max Budget" }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name" } }, "title": "UpdateBudgetRequest", "type": "object" }, "UpdateKeyRequest": { "description": "Request model for updating a key.", "properties": { "allowed_models": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Models" }, "expires_at": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "title": "Expires At" }, "is_active": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Is Active" }, "key_name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Key Name" }, "metadata": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Metadata" } }, "title": "UpdateKeyRequest", "type": "object" }, "UpdateSettingsRequest": { "description": "Change one or more runtime settings. Omitted fields are left unchanged.\n\nOnly the hot-changeable subset is accepted; startup-only fields are not\nsettable over the API (they are display-only in the dashboard).", "properties": { "budget_estimate_default_output_tokens": { "anyOf": [ { "minimum": 0.0, "type": "integer" }, { "type": "null" } ], "title": "Budget Estimate Default Output Tokens" }, "default_pricing": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Default Pricing" }, "file_understanding_enabled": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "File Understanding Enabled" }, "model_cache_ttl_seconds": { "anyOf": [ { "minimum": 0.0, "type": "integer" }, { "type": "null" } ], "title": "Model Cache Ttl Seconds" }, "model_discovery": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Model Discovery" }, "model_discovery_negative_ttl_seconds": { "anyOf": [ { "minimum": 0.0, "type": "number" }, { "type": "null" } ], "title": "Model Discovery Negative Ttl Seconds" }, "model_discovery_timeout_seconds": { "anyOf": [ { "exclusiveMinimum": 0.0, "type": "number" }, { "type": "null" } ], "title": "Model Discovery Timeout Seconds" }, "models_dev_cache_ttl_seconds": { "anyOf": [ { "minimum": 0.0, "type": "integer" }, { "type": "null" } ], "title": "Models Dev Cache Ttl Seconds" }, "models_dev_metadata": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Models Dev Metadata" }, "reject_user_mismatch": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Reject User Mismatch" }, "require_pricing": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Require Pricing" }, "stream_missing_usage_policy": { "anyOf": [ { "enum": [ "estimate", "fail", "allow_free" ], "type": "string" }, { "type": "null" } ], "title": "Stream Missing Usage Policy" }, "vision_describe_max_tokens": { "anyOf": [ { "exclusiveMinimum": 0.0, "type": "integer" }, { "type": "null" } ], "title": "Vision Describe Max Tokens" }, "vision_describe_model": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Vision Describe Model" }, "vision_strategy": { "anyOf": [ { "enum": [ "describe", "ocr", "off" ], "type": "string" }, { "type": "null" } ], "title": "Vision Strategy" } }, "title": "UpdateSettingsRequest", "type": "object" }, "UpdateStoredProviderRequest": { "description": "Update a stored provider. Omitted fields are unchanged; ``api_key`` rotates in place.", "properties": { "api_base": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Base" }, "api_key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "New API key. Omit to keep the existing one. Never returned.", "title": "Api Key" }, "client_args": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Client Args" }, "expected_updated_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optimistic concurrency: if set, the update 412s unless it matches the stored updated_at.", "title": "Expected Updated At" }, "provider_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Provider Type" } }, "title": "UpdateStoredProviderRequest", "type": "object" }, "UpdateToolSettingsRequest": { "description": "Change one or more tool settings. Omitted fields are left unchanged; an\nexplicit ``null`` clears a field back to the configured env/YAML default.", "example": { "web_search_max_results": 5, "web_search_url": "http://searxng:8080" }, "properties": { "guardrails_url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Guardrails Url" }, "sandbox_purpose_hint": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Sandbox Purpose Hint" }, "sandbox_url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Sandbox Url" }, "web_search_engines": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Web Search Engines" }, "web_search_extract": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Web Search Extract" }, "web_search_max_results": { "anyOf": [ { "minimum": 1.0, "type": "integer" }, { "type": "null" } ], "title": "Web Search Max Results" }, "web_search_purpose_hint": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Web Search Purpose Hint" }, "web_search_url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Web Search Url" } }, "title": "UpdateToolSettingsRequest", "type": "object" }, "UpdateUserRequest": { "description": "Request model for updating a user.", "properties": { "alias": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Alias" }, "allowed_models": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Models" }, "blocked": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Blocked" }, "budget_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Budget Id" }, "metadata": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Metadata" } }, "title": "UpdateUserRequest", "type": "object" }, "UsageCount": { "description": "Total number of usage logs matching a set of filters.", "properties": { "total": { "title": "Total", "type": "integer" } }, "required": [ "total" ], "title": "UsageCount", "type": "object" }, "UsageEntry": { "description": "A single usage log entry.", "properties": { "api_key_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Key Id" }, "cache_read_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Cache Read Tokens" }, "cache_write_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Cache Write Tokens" }, "completion_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Completion Tokens" }, "cost": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cost" }, "endpoint": { "title": "Endpoint", "type": "string" }, "error_message": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Error Message" }, "id": { "title": "Id", "type": "string" }, "latency_ms": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Latency Ms" }, "model": { "title": "Model", "type": "string" }, "prompt_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Prompt Tokens" }, "provider": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Provider" }, "status": { "title": "Status", "type": "string" }, "timestamp": { "title": "Timestamp", "type": "string" }, "total_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Total Tokens" }, "user_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User Id" } }, "required": [ "id", "user_id", "api_key_id", "timestamp", "model", "provider", "endpoint", "prompt_tokens", "completion_tokens", "total_tokens", "cache_read_tokens", "cache_write_tokens", "cost", "status", "error_message", "latency_ms" ], "title": "UsageEntry", "type": "object" }, "UsageGroupRow": { "description": "One breakdown row (a model, a user, or an API key).\n\n``key`` is None both for the synthesized fold row (``is_other=True``) and for a\nreal group whose column was NULL (e.g. usage from a since-deleted user, with\n``is_other=False``). ``is_other`` disambiguates the two so the UI does not\nmislabel deleted-user usage as the fold.", "properties": { "cost": { "title": "Cost", "type": "number" }, "is_other": { "default": false, "title": "Is Other", "type": "boolean" }, "key": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Key" }, "requests": { "title": "Requests", "type": "integer" }, "tokens": { "title": "Tokens", "type": "integer" } }, "required": [ "key", "cost", "tokens", "requests" ], "title": "UsageGroupRow", "type": "object" }, "UsageLogResponse": { "description": "Response model for usage log.", "properties": { "api_key_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Key Id" }, "completion_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Completion Tokens" }, "cost": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cost" }, "endpoint": { "title": "Endpoint", "type": "string" }, "error_message": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Error Message" }, "id": { "title": "Id", "type": "string" }, "latency_ms": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Latency Ms" }, "model": { "title": "Model", "type": "string" }, "prompt_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Prompt Tokens" }, "provider": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Provider" }, "status": { "title": "Status", "type": "string" }, "timestamp": { "title": "Timestamp", "type": "string" }, "total_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Total Tokens" }, "user_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User Id" } }, "required": [ "id", "user_id", "api_key_id", "timestamp", "model", "provider", "endpoint", "prompt_tokens", "completion_tokens", "total_tokens", "cost", "status", "error_message", "latency_ms" ], "title": "UsageLogResponse", "type": "object" }, "UsageSeriesPoint": { "description": "One time bucket. ``bucket_start`` is canonical ISO-8601 UTC (``...Z``),\nidentical across SQLite and PostgreSQL for the same underlying instant.", "properties": { "bucket_start": { "title": "Bucket Start", "type": "string" }, "cost": { "title": "Cost", "type": "number" }, "requests": { "title": "Requests", "type": "integer" }, "tokens": { "title": "Tokens", "type": "integer" } }, "required": [ "bucket_start", "cost", "tokens", "requests" ], "title": "UsageSeriesPoint", "type": "object" }, "UsageSummary": { "description": "Aggregate spend/volume for the Usage & analytics page.", "properties": { "bucket": { "enum": [ "hour", "day" ], "title": "Bucket", "type": "string" }, "by_api_key": { "items": { "$ref": "#/components/schemas/UsageGroupRow" }, "title": "By Api Key", "type": "array" }, "by_model": { "items": { "$ref": "#/components/schemas/UsageGroupRow" }, "title": "By Model", "type": "array" }, "by_user": { "items": { "$ref": "#/components/schemas/UsageGroupRow" }, "title": "By User", "type": "array" }, "end_date": { "title": "End Date", "type": "string" }, "series": { "items": { "$ref": "#/components/schemas/UsageSeriesPoint" }, "title": "Series", "type": "array" }, "start_date": { "title": "Start Date", "type": "string" }, "totals": { "$ref": "#/components/schemas/UsageTotals" } }, "required": [ "start_date", "end_date", "bucket", "totals", "by_model", "by_user", "by_api_key", "series" ], "title": "UsageSummary", "type": "object" }, "UsageTotals": { "description": "Grand totals over the filtered window.", "properties": { "avg_latency_ms": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Avg Latency Ms" }, "cache_read_tokens": { "title": "Cache Read Tokens", "type": "integer" }, "cache_write_tokens": { "title": "Cache Write Tokens", "type": "integer" }, "completion_tokens": { "title": "Completion Tokens", "type": "integer" }, "cost": { "title": "Cost", "type": "number" }, "error_count": { "title": "Error Count", "type": "integer" }, "prompt_tokens": { "title": "Prompt Tokens", "type": "integer" }, "request_count": { "title": "Request Count", "type": "integer" }, "total_tokens": { "title": "Total Tokens", "type": "integer" } }, "required": [ "cost", "prompt_tokens", "completion_tokens", "total_tokens", "cache_read_tokens", "cache_write_tokens", "request_count", "error_count", "avg_latency_ms" ], "title": "UsageTotals", "type": "object" }, "UserResponse": { "description": "Response model for user information.", "properties": { "alias": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Alias" }, "allowed_models": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Models" }, "blocked": { "title": "Blocked", "type": "boolean" }, "budget_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Budget Id" }, "budget_started_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Budget Started At" }, "created_at": { "title": "Created At", "type": "string" }, "metadata": { "additionalProperties": true, "title": "Metadata", "type": "object" }, "next_budget_reset_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Next Budget Reset At" }, "reserved": { "title": "Reserved", "type": "number" }, "spend": { "title": "Spend", "type": "number" }, "updated_at": { "title": "Updated At", "type": "string" }, "user_id": { "title": "User Id", "type": "string" } }, "required": [ "user_id", "alias", "spend", "reserved", "budget_id", "allowed_models", "budget_started_at", "next_budget_reset_at", "blocked", "created_at", "updated_at", "metadata" ], "title": "UserResponse", "type": "object" }, "ValidationError": { "properties": { "ctx": { "title": "Context", "type": "object" }, "input": { "title": "Input" }, "loc": { "items": { "anyOf": [ { "type": "string" }, { "type": "integer" } ] }, "title": "Location", "type": "array" }, "msg": { "title": "Message", "type": "string" }, "type": { "title": "Error Type", "type": "string" } }, "required": [ "loc", "msg", "type" ], "title": "ValidationError", "type": "object" } }, "securitySchemes": { "ApiKeyAuth": { "description": "Enter your API key here (sent as Otari-Key header).", "in": "header", "name": "Otari-Key", "type": "apiKey" }, "XApiKeyAuth": { "description": "Anthropic-native clients send credentials here (no Bearer prefix).", "in": "header", "name": "x-api-key", "type": "apiKey" } } }, "info": { "description": "Otari, an OpenAI-compatible LLM gateway with API key management", "title": "otari", "version": "0.0.0-dev" }, "openapi": "3.1.0", "paths": { "/health": { "get": { "description": "General health check endpoint.\n\nReturns basic health status. For infrastructure monitoring,\nuse /health/readiness or /health/liveness instead.", "operationId": "health_check_health_get", "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "title": "Response Health Check Health Get", "type": "object" } } }, "description": "Successful Response" } }, "summary": "Health Check", "tags": [ "health" ] } }, "/health/liveness": { "get": { "description": "Liveness probe endpoint.\n\nSimple check to verify the process is alive and responding.\nUsed by Kubernetes/container orchestrators for liveness probes.\n\nReturns:\n Plain text \"I'm alive!\" message", "operationId": "health_liveness_health_liveness_get", "responses": { "200": { "content": { "application/json": { "schema": { "title": "Response Health Liveness Health Liveness Get", "type": "string" } } }, "description": "Successful Response" } }, "summary": "Health Liveness", "tags": [ "health" ] } }, "/health/readiness": { "get": { "description": "Readiness probe endpoint.\n\nChecks if the gateway is ready to serve requests by validating:\n- Database connectivity\n- Service availability\n\nUsed by Kubernetes/container orchestrators for readiness probes.\nReturns HTTP 503 if any dependency is unavailable.\n\nReturns:\n dict: Status object with health details\n\nRaises:\n HTTPException: 503 if service is not ready", "operationId": "health_readiness_health_readiness_get", "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": true, "title": "Response Health Readiness Health Readiness Get", "type": "object" } } }, "description": "Successful Response" } }, "summary": "Health Readiness", "tags": [ "health" ] } }, "/v1/aliases": { "get": { "description": "List every alias in force, from config.yml and from storage.", "operationId": "list_aliases_v1_aliases_get", "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/AliasResponse" }, "title": "Response List Aliases V1 Aliases Get", "type": "array" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Aliases", "tags": [ "aliases" ] }, "post": { "description": "Create or update a stored alias.", "operationId": "set_alias_v1_aliases_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AliasRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AliasResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Set Alias", "tags": [ "aliases" ] } }, "/v1/aliases/{name}": { "delete": { "description": "Delete a stored alias.", "operationId": "delete_alias_v1_aliases__name__delete", "parameters": [ { "in": "path", "name": "name", "required": true, "schema": { "title": "Name", "type": "string" } } ], "responses": { "204": { "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Delete Alias", "tags": [ "aliases" ] } }, "/v1/audio/speech": { "post": { "description": "OpenAI-compatible audio speech (TTS) endpoint.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "create_speech_v1_audio_speech_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AudioSpeechRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} }, "audio/L16": { "schema": { "format": "binary", "type": "string" } }, "audio/aac": { "schema": { "format": "binary", "type": "string" } }, "audio/flac": { "schema": { "format": "binary", "type": "string" } }, "audio/mpeg": { "schema": { "format": "binary", "type": "string" } }, "audio/opus": { "schema": { "format": "binary", "type": "string" } }, "audio/wav": { "schema": { "format": "binary", "type": "string" } } }, "description": "Audio bytes in the requested format" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Speech", "tags": [ "audio" ] } }, "/v1/audio/transcriptions": { "post": { "description": "OpenAI-compatible audio transcription endpoint.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "create_transcription_v1_audio_transcriptions_post", "requestBody": { "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/Body_create_transcription_v1_audio_transcriptions_post" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Transcription", "tags": [ "audio" ] } }, "/v1/batches": { "get": { "description": "List batches for a provider.\n\nNon-master keys only see batches they own (plus legacy batches without an\nownership marker); the page is filtered after the provider call, so a page\nmay contain fewer than ``limit`` items.", "operationId": "list_batches_v1_batches_get", "parameters": [ { "in": "query", "name": "provider", "required": true, "schema": { "title": "Provider", "type": "string" } }, { "in": "query", "name": "after", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "After" } }, { "in": "query", "name": "limit", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Limit" } } ], "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Batches", "tags": [ "batches" ] }, "post": { "description": "Create a batch of LLM requests for asynchronous processing.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "create_batch_v1_batches_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateBatchRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Batch", "tags": [ "batches" ] } }, "/v1/batches/{batch_id}": { "get": { "description": "Retrieve the status of a batch.", "operationId": "retrieve_batch_v1_batches__batch_id__get", "parameters": [ { "in": "path", "name": "batch_id", "required": true, "schema": { "title": "Batch Id", "type": "string" } }, { "in": "query", "name": "provider", "required": true, "schema": { "title": "Provider", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Retrieve Batch", "tags": [ "batches" ] } }, "/v1/batches/{batch_id}/cancel": { "post": { "description": "Cancel a batch.", "operationId": "cancel_batch_v1_batches__batch_id__cancel_post", "parameters": [ { "in": "path", "name": "batch_id", "required": true, "schema": { "title": "Batch Id", "type": "string" } }, { "in": "query", "name": "provider", "required": true, "schema": { "title": "Provider", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Cancel Batch", "tags": [ "batches" ] } }, "/v1/batches/{batch_id}/results": { "get": { "description": "Retrieve the results of a completed batch.", "operationId": "retrieve_batch_results_v1_batches__batch_id__results_get", "parameters": [ { "in": "path", "name": "batch_id", "required": true, "schema": { "title": "Batch Id", "type": "string" } }, { "in": "query", "name": "provider", "required": true, "schema": { "title": "Provider", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "409": { "description": "Batch is not yet complete" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" }, "502": { "description": "LLM provider error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Retrieve Batch Results", "tags": [ "batches" ] } }, "/v1/budgets": { "get": { "description": "List all budgets with pagination.", "operationId": "list_budgets_v1_budgets_get", "parameters": [ { "in": "query", "name": "skip", "required": false, "schema": { "default": 0, "minimum": 0, "title": "Skip", "type": "integer" } }, { "in": "query", "name": "limit", "required": false, "schema": { "default": 100, "maximum": 1000, "minimum": 1, "title": "Limit", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/BudgetResponse" }, "title": "Response List Budgets V1 Budgets Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Budgets", "tags": [ "budgets" ] }, "post": { "description": "Create a new budget.", "operationId": "create_budget_v1_budgets_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateBudgetRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BudgetResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Budget", "tags": [ "budgets" ] } }, "/v1/budgets/{budget_id}": { "delete": { "description": "Delete a budget.", "operationId": "delete_budget_v1_budgets__budget_id__delete", "parameters": [ { "in": "path", "name": "budget_id", "required": true, "schema": { "title": "Budget Id", "type": "string" } } ], "responses": { "204": { "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Delete Budget", "tags": [ "budgets" ] }, "get": { "description": "Get details of a specific budget.", "operationId": "get_budget_v1_budgets__budget_id__get", "parameters": [ { "in": "path", "name": "budget_id", "required": true, "schema": { "title": "Budget Id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BudgetResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get Budget", "tags": [ "budgets" ] }, "patch": { "description": "Update a budget.", "operationId": "update_budget_v1_budgets__budget_id__patch", "parameters": [ { "in": "path", "name": "budget_id", "required": true, "schema": { "title": "Budget Id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateBudgetRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BudgetResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Update Budget", "tags": [ "budgets" ] } }, "/v1/budgets/{budget_id}/reset-logs": { "get": { "description": "List per-user reset events for a budget, newest first.", "operationId": "list_budget_reset_logs_v1_budgets__budget_id__reset_logs_get", "parameters": [ { "in": "path", "name": "budget_id", "required": true, "schema": { "title": "Budget Id", "type": "string" } }, { "in": "query", "name": "skip", "required": false, "schema": { "default": 0, "minimum": 0, "title": "Skip", "type": "integer" } }, { "in": "query", "name": "limit", "required": false, "schema": { "default": 100, "maximum": 1000, "minimum": 1, "title": "Limit", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/BudgetResetLogResponse" }, "title": "Response List Budget Reset Logs V1 Budgets Budget Id Reset Logs Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Budget Reset Logs", "tags": [ "budgets" ] } }, "/v1/chat/completions": { "post": { "description": "OpenAI-compatible chat completions endpoint.\n\nSupports both streaming and non-streaming responses.\nHandles reasoning content from otari providers.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "chat_completions_v1_chat_completions_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChatCompletionRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Chat Completions", "tags": [ "chat" ] } }, "/v1/embeddings": { "post": { "description": "OpenAI-compatible embeddings endpoint.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "create_embedding_v1_embeddings_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EmbeddingRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Embedding", "tags": [ "embeddings" ] } }, "/v1/files": { "get": { "description": "List the authenticated user's uploaded files.", "operationId": "list_files_v1_files_get", "parameters": [ { "in": "query", "name": "user", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } }, { "in": "query", "name": "purpose", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Purpose" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": true, "title": "Response List Files V1 Files Get", "type": "object" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Files", "tags": [ "files" ] }, "post": { "description": "OpenAI-compatible file upload endpoint.", "operationId": "create_file_v1_files_post", "requestBody": { "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/Body_create_file_v1_files_post" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": true, "title": "Response Create File V1 Files Post", "type": "object" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create File", "tags": [ "files" ] } }, "/v1/files/{file_id}": { "delete": { "description": "Soft-delete a file's metadata and remove its bytes from the backend.", "operationId": "delete_file_v1_files__file_id__delete", "parameters": [ { "in": "path", "name": "file_id", "required": true, "schema": { "title": "File Id", "type": "string" } }, { "in": "query", "name": "user", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": true, "title": "Response Delete File V1 Files File Id Delete", "type": "object" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Delete File", "tags": [ "files" ] }, "get": { "description": "Retrieve metadata for a single file.", "operationId": "get_file_v1_files__file_id__get", "parameters": [ { "in": "path", "name": "file_id", "required": true, "schema": { "title": "File Id", "type": "string" } }, { "in": "query", "name": "user", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": true, "title": "Response Get File V1 Files File Id Get", "type": "object" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get File", "tags": [ "files" ] } }, "/v1/files/{file_id}/content": { "get": { "description": "Download the raw bytes of a file.", "operationId": "get_file_content_v1_files__file_id__content_get", "parameters": [ { "in": "path", "name": "file_id", "required": true, "schema": { "title": "File Id", "type": "string" } }, { "in": "query", "name": "user", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "User" } } ], "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get File Content", "tags": [ "files" ] } }, "/v1/images/generations": { "post": { "description": "OpenAI-compatible image generation endpoint.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "create_image_v1_images_generations_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImageGenerationRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Image", "tags": [ "images" ] } }, "/v1/keys": { "get": { "description": "List all API keys.\n\nRequires master key authentication.", "operationId": "list_keys_v1_keys_get", "parameters": [ { "in": "query", "name": "skip", "required": false, "schema": { "default": 0, "minimum": 0, "title": "Skip", "type": "integer" } }, { "in": "query", "name": "limit", "required": false, "schema": { "default": 100, "maximum": 1000, "minimum": 1, "title": "Limit", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/KeyInfo" }, "title": "Response List Keys V1 Keys Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Keys", "tags": [ "keys" ] }, "post": { "description": "Create a new API key.\n\nRequires master key authentication.\n\nIf user_id is provided, the key will be associated with that user (creates user if it doesn't exist).\nIf user_id is not provided, the key is associated with the shared \"default\" user, which is created\non first use. Keys without an explicit owner therefore share one identity, and so share budget,\nusage, and files.", "operationId": "create_key_v1_keys_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateKeyRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateKeyResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Key", "tags": [ "keys" ] } }, "/v1/keys/{key_id}": { "delete": { "description": "Delete (revoke) an API key.\n\nRequires master key authentication.", "operationId": "delete_key_v1_keys__key_id__delete", "parameters": [ { "in": "path", "name": "key_id", "required": true, "schema": { "title": "Key Id", "type": "string" } } ], "responses": { "204": { "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Delete Key", "tags": [ "keys" ] }, "get": { "description": "Get details of a specific API key.\n\nRequires master key authentication.", "operationId": "get_key_v1_keys__key_id__get", "parameters": [ { "in": "path", "name": "key_id", "required": true, "schema": { "title": "Key Id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyInfo" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get Key", "tags": [ "keys" ] }, "patch": { "description": "Update an API key.\n\nRequires master key authentication.", "operationId": "update_key_v1_keys__key_id__patch", "parameters": [ { "in": "path", "name": "key_id", "required": true, "schema": { "title": "Key Id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateKeyRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyInfo" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Update Key", "tags": [ "keys" ] } }, "/v1/keys/{key_id}/rotate": { "post": { "description": "Rotate an API key's secret in place.\n\nRequires master key authentication.\n\nGenerates a new secret for the same key row (id, user, name, expiry, and\nmetadata are preserved) and returns the new raw key once, using the same\nresponse shape as key creation. The previous secret stops authenticating\nimmediately; there is no grace window.", "operationId": "rotate_key_v1_keys__key_id__rotate_post", "parameters": [ { "in": "path", "name": "key_id", "required": true, "schema": { "title": "Key Id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateKeyResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Rotate Key", "tags": [ "keys" ] } }, "/v1/messages": { "post": { "description": "Anthropic Messages API-compatible endpoint.\n\nSupports MCP tool-use loops, sandboxed code execution, and SearXNG\nweb_search in both standalone mode and hybrid mode. Hybrid-mode requests\nresolve credentials via the platform service and get multi-attempt\nfallback across the resolved route, tool-loop requests included (fallback\napplies up to the pre-lock-in point, same as chat).", "operationId": "create_message_v1_messages_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessagesRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Message", "tags": [ "messages" ] } }, "/v1/messages/count_tokens": { "post": { "description": "Anthropic ``/v1/messages/count_tokens``-compatible endpoint.\n\nReturns ``{\"input_tokens\": N}`` without contacting an upstream provider:\ncounting is local, so there is no budget reservation, pricing, or usage\nlogging. Authentication mirrors :func:`create_message` \u2014 hybrid mode\nresolves the caller's token against the platform, standalone mode validates\nthe API key \u2014 so the endpoint is not an open token-counting oracle.", "operationId": "count_message_tokens_v1_messages_count_tokens_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CountTokensRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CountTokensResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Count Message Tokens", "tags": [ "messages" ] } }, "/v1/models": { "get": { "description": "List all available models.\n\nReturns models auto-discovered from configured providers, enriched with\npricing data from the model_pricing table when available. Models that only\nexist in the pricing table are also included for backward compatibility.", "operationId": "list_models_v1_models_get", "parameters": [ { "description": "Filter models by provider name", "in": "query", "name": "provider", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter models by provider name", "title": "Provider" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ModelListResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Models", "tags": [ "models" ] } }, "/v1/models/discoverable": { "get": { "description": "List every model the configured provider credentials can reach.\n\nOperator-facing counterpart to GET /v1/models, which serves a curated catalog\nto API callers. This reports each provider separately and keeps its error, so\na provider with a bad key is distinguishable from one with no models. It is\nmaster-key gated because a provider error message describes the gateway's own\nconfiguration.", "operationId": "list_discoverable_models_v1_models_discoverable_get", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DiscoverableModelsResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Discoverable Models", "tags": [ "models" ] } }, "/v1/models/metadata": { "get": { "description": "Per-model metadata for the dashboard's detail view, from models.dev.\n\nCovers every model models.dev lists under a configured provider, keyed by the\n``instance:model`` selector the dashboard uses. ``available`` is false when\nenrichment is disabled (``models_dev_metadata``) or models.dev could not be\nreached; the response is then empty and the UI falls back to bundled data.\nMaster-key gated: it describes the gateway's configured providers.", "operationId": "list_model_metadata_v1_models_metadata_get", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ModelMetadataResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Model Metadata", "tags": [ "models" ] } }, "/v1/models/{model_id}": { "get": { "description": "Get details for a specific model.", "operationId": "get_model_v1_models__model_id__get", "parameters": [ { "in": "path", "name": "model_id", "required": true, "schema": { "title": "Model Id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ModelObject" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get Model", "tags": [ "models" ] } }, "/v1/moderations": { "post": { "description": "OpenAI-compatible moderations endpoint.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "create_moderation_v1_moderations_post", "parameters": [ { "in": "query", "name": "include_raw", "required": false, "schema": { "default": false, "title": "Include Raw", "type": "boolean" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ModerationRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ModerationResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Moderation", "tags": [ "moderations" ] } }, "/v1/pricing": { "get": { "description": "List all model pricing.", "operationId": "list_pricing_v1_pricing_get", "parameters": [ { "in": "query", "name": "skip", "required": false, "schema": { "default": 0, "minimum": 0, "title": "Skip", "type": "integer" } }, { "in": "query", "name": "limit", "required": false, "schema": { "default": 100, "maximum": 1000, "minimum": 1, "title": "Limit", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/PricingResponse" }, "title": "Response List Pricing V1 Pricing Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Pricing", "tags": [ "pricing" ] }, "post": { "description": "Set or update pricing for a model.\n\nRejects an alias: pricing, budgets, and usage all key on the resolved\ntarget, so a row stored under an alias name would never be read.", "operationId": "set_pricing_v1_pricing_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetPricingRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PricingResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Set Pricing", "tags": [ "pricing" ] } }, "/v1/pricing/refresh": { "post": { "description": "Fetch the latest defaults and hold them for operator review.", "operationId": "preview_pricing_refresh_v1_pricing_refresh_post", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PricingRefreshPreviewResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Preview Pricing Refresh", "tags": [ "pricing" ] } }, "/v1/pricing/refresh/confirm": { "post": { "description": "Activate the latest reviewed default-price snapshot.", "operationId": "confirm_pricing_refresh_v1_pricing_refresh_confirm_post", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PricingRefreshConfirmationResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Confirm Pricing Refresh", "tags": [ "pricing" ] } }, "/v1/pricing/refresh/reject": { "post": { "description": "Discard a reviewed default-price snapshot without applying it.", "operationId": "reject_pricing_refresh_v1_pricing_refresh_reject_post", "responses": { "204": { "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Reject Pricing Refresh", "tags": [ "pricing" ] } }, "/v1/pricing/{model_key}": { "delete": { "description": "Delete pricing entries for a model.", "operationId": "delete_pricing_v1_pricing__model_key__delete", "parameters": [ { "in": "path", "name": "model_key", "required": true, "schema": { "title": "Model Key", "type": "string" } }, { "description": "ISO datetime identifying a specific pricing row to delete", "in": "query", "name": "effective_at", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "ISO datetime identifying a specific pricing row to delete", "title": "Effective At" } } ], "responses": { "204": { "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Delete Pricing", "tags": [ "pricing" ] }, "get": { "description": "Get pricing for a specific model as of a timestamp.", "operationId": "get_pricing_v1_pricing__model_key__get", "parameters": [ { "in": "path", "name": "model_key", "required": true, "schema": { "title": "Model Key", "type": "string" } }, { "description": "ISO datetime for effective lookup", "in": "query", "name": "as_of", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "ISO datetime for effective lookup", "title": "as_of" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PricingResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get Pricing", "tags": [ "pricing" ] } }, "/v1/pricing/{model_key}/history": { "get": { "description": "Return the full pricing history for a model.", "operationId": "get_pricing_history_v1_pricing__model_key__history_get", "parameters": [ { "in": "path", "name": "model_key", "required": true, "schema": { "title": "Model Key", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/PricingResponse" }, "title": "Response Get Pricing History V1 Pricing Model Key History Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get Pricing History", "tags": [ "pricing" ] } }, "/v1/provider-credentials": { "get": { "description": "List runtime-stored providers. Keys are never returned, only ``last4``.", "operationId": "list_stored_providers_v1_provider_credentials_get", "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/StoredProviderResponse" }, "title": "Response List Stored Providers V1 Provider Credentials Get", "type": "array" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Stored Providers", "tags": [ "providers" ] }, "post": { "description": "Add a provider at runtime. Storing a key requires OTARI_SECRET_KEY.", "operationId": "create_stored_provider_v1_provider_credentials_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateStoredProviderRequest" } } }, "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StoredProviderResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Stored Provider", "tags": [ "providers" ] } }, "/v1/provider-credentials/reencrypt": { "post": { "description": "Re-encrypt stored provider keys with the primary OTARI_SECRET_KEY.\n\nOperators rotate ``OTARI_SECRET_KEY`` by setting it to ``new,old`` first,\nrestarting, running this endpoint, then removing the old key and restarting\nagain. Rows that cannot be decrypted are left untouched and must be recovered\nby replacing the affected provider keys.", "operationId": "reencrypt_stored_provider_keys_v1_provider_credentials_reencrypt_post", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReencryptProviderCredentialsResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Reencrypt Stored Provider Keys", "tags": [ "providers" ] } }, "/v1/provider-credentials/test": { "post": { "description": "Test provider credentials without storing them (for the add/edit form).\n\nResolves the implementation from ``provider_type`` (honoring the\n``*-compatible`` aliases) or the ``instance`` name, then lists the provider's\nmodels with the supplied credentials. Nothing is persisted and the key is\nnever echoed.", "operationId": "test_provider_connection_v1_provider_credentials_test_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestProviderRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestProviderResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Test Provider Connection", "tags": [ "providers" ] } }, "/v1/provider-credentials/{instance}": { "delete": { "description": "Delete a stored provider. A config.yml provider cannot be deleted here.", "operationId": "delete_stored_provider_v1_provider_credentials__instance__delete", "parameters": [ { "in": "path", "name": "instance", "required": true, "schema": { "title": "Instance", "type": "string" } } ], "responses": { "204": { "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Delete Stored Provider", "tags": [ "providers" ] }, "patch": { "description": "Update a stored provider. Omitted fields are left as-is; an explicit ``null`` clears them.\n\n``api_key`` follows the same rule: omit it to keep the stored key, send a new\none to rotate, or send ``null`` to clear it. The row is locked ``FOR UPDATE``\nso the ``expected_updated_at`` check and the write it guards are atomic.", "operationId": "update_stored_provider_v1_provider_credentials__instance__patch", "parameters": [ { "in": "path", "name": "instance", "required": true, "schema": { "title": "Instance", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateStoredProviderRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StoredProviderResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Update Stored Provider", "tags": [ "providers" ] } }, "/v1/provider-credentials/{instance}/test": { "post": { "description": "Verify a stored provider's key by listing its models, without exposing the key.", "operationId": "test_stored_provider_v1_provider_credentials__instance__test_post", "parameters": [ { "in": "path", "name": "instance", "required": true, "schema": { "title": "Instance", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestProviderResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Test Stored Provider", "tags": [ "providers" ] } }, "/v1/providers": { "get": { "description": "List static metadata for every configured provider.\n\nOperator-facing: reports each provider's capabilities, documentation and\npricing links, and display name from the bundled any-llm and genai-prices\ndatasets. No provider is contacted, so this is cheap and always available.\nMaster-key gated because it describes the gateway's own configuration.", "operationId": "list_providers_v1_providers_get", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProvidersResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Providers", "tags": [ "providers" ] } }, "/v1/providers/catalog": { "get": { "description": "List every known provider for the add-provider picker.\n\nNetwork-free and config-independent: the full any-llm provider set with each\none's display name, credential env var, default endpoint, and whether it\nneeds a key. Master-key gated because it is operator-facing dashboard data.", "operationId": "provider_catalog_v1_providers_catalog_get", "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/KnownProviderSchema" }, "title": "Response Provider Catalog V1 Providers Catalog Get", "type": "array" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Provider Catalog", "tags": [ "providers" ] } }, "/v1/providers/health": { "get": { "description": "Report every configured provider's reachability, with a last-checked time.\n\nReuses the per-provider model-discovery test path, so a provider is healthy\nwhen its credentials can list models. Results are served from the discovery\ncache (cheap enough to poll), so ``checked_at`` reflects when each provider\nwas actually dialed. Pass ``refresh=true`` to force a live re-dial of every\nprovider. Master-key gated because it describes the gateway's own providers.", "operationId": "provider_health_v1_providers_health_get", "parameters": [ { "in": "query", "name": "refresh", "required": false, "schema": { "default": false, "title": "Refresh", "type": "boolean" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProviderHealthResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Provider Health", "tags": [ "providers" ] } }, "/v1/rerank": { "post": { "description": "Rerank documents by relevance to a query.\n\nAuthentication modes:\n- Master key + user field: Use specified user (must exist)\n- API key + user field: Use specified user (must exist)\n- API key without user field: Use the shared \"default\" user", "operationId": "create_rerank_v1_rerank_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RerankRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Rerank", "tags": [ "rerank" ] } }, "/v1/responses": { "post": { "description": "OpenAI-compatible Responses endpoint.\n\nSupports MCP tool-use loops, sandboxed code execution, and SearXNG\nweb_search in both standalone mode and hybrid mode. Hybrid-mode requests\nresolve credentials via the platform service and get multi-attempt\nfallback across the resolved route, tool-loop requests included (fallback\napplies up to the pre-lock-in point, same as chat).", "operationId": "create_response_v1_responses_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResponsesRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create Response", "tags": [ "responses" ] } }, "/v1/settings": { "get": { "description": "Return non-secret runtime settings for the admin dashboard.", "operationId": "get_settings_v1_settings_get", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GatewaySettings" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get Settings", "tags": [ "settings" ] }, "patch": { "description": "Persist and apply runtime setting changes.\n\nEach provided field is stored as an override (winning over config/env) and\napplied to the running gateway immediately. Master-key gated: these change\nhow the gateway meters and lists models.", "operationId": "update_settings_v1_settings_patch", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSettingsRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GatewaySettings" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Update Settings", "tags": [ "settings" ] } }, "/v1/settings/master-key/rotate": { "post": { "description": "Regenerate the database-backed master key and invalidate the old one.\n\nOnly the first-run generated master key can be rotated here. When a master\nkey is supplied through config or ``OTARI_MASTER_KEY``, the dashboard cannot\ninvalidate it; the operator must change that value and restart instead.", "operationId": "rotate_master_key_v1_settings_master_key_rotate_post", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RotateMasterKeyResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Rotate Master Key", "tags": [ "settings" ] } }, "/v1/tool-settings": { "get": { "description": "Return the effective tool/guardrail settings for the dashboard.", "operationId": "get_tool_settings_v1_tool_settings_get", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolSettingsResponse" } } }, "description": "Successful Response" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get Tool Settings", "tags": [ "tool-settings" ] }, "patch": { "description": "Persist and apply tool/guardrail setting changes.\n\nUses ``model_fields_set`` so an explicit ``null`` clears a field while an\nomitted field is left unchanged. Master-key gated and standalone-only.", "operationId": "update_tool_settings_v1_tool_settings_patch", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateToolSettingsRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolSettingsResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Update Tool Settings", "tags": [ "tool-settings" ] } }, "/v1/tool-settings/{service}/test": { "post": { "description": "Structurally validate a URL and probe it for reachability.\n\nTests the URL in the request body (typically unsaved), so an operator can\nverify before saving. The probe is a plain HTTP GET with a short timeout: any\nHTTP response means the host is reachable; a connection/timeout/DNS error means\nit is not. The operator is trusted (master key), so no SSRF deny-list applies;\nonly the structural check (http/https + host) runs first.", "operationId": "test_service_v1_tool_settings__service__test_post", "parameters": [ { "in": "path", "name": "service", "required": true, "schema": { "title": "Service", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestServiceRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestServiceResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Test Service", "tags": [ "tool-settings" ] } }, "/v1/usage": { "get": { "description": "List usage logs ordered by timestamp (most recent first).\n\nSupports optional filters for time range, user, status, model, and endpoint.\nPaginated via skip/limit. The return shape is a bare JSON array; external\nbilling/analytics consumers depend on this, so the total row count for a\npaginated UI is served separately by ``GET /v1/usage/count`` rather than\nwrapped in an envelope here. Timestamps accept either ISO 8601 strings or\nUnix epoch seconds (numeric).", "operationId": "list_usage_v1_usage_get", "parameters": [ { "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "start_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "title": "Start Date" } }, { "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "end_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "title": "End Date" } }, { "description": "Filter to a single user", "in": "query", "name": "user_id", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single user", "title": "User Id" } }, { "description": "Filter to a single status (e.g. 'success' or 'error')", "in": "query", "name": "status", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single status (e.g. 'success' or 'error')", "title": "Status" } }, { "description": "Filter to a single model", "in": "query", "name": "model", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single model", "title": "Model" } }, { "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "in": "query", "name": "endpoint", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "title": "Endpoint" } }, { "in": "query", "name": "skip", "required": false, "schema": { "default": 0, "minimum": 0, "title": "Skip", "type": "integer" } }, { "in": "query", "name": "limit", "required": false, "schema": { "default": 100, "maximum": 1000, "minimum": 1, "title": "Limit", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/UsageEntry" }, "title": "Response List Usage V1 Usage Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Usage", "tags": [ "usage" ] } }, "/v1/usage/count": { "get": { "description": "Total number of usage logs matching the given filters.\n\nServes the dashboard paginator's \"N of M\" total without changing the bare\narray contract of ``GET /v1/usage``. Runs only when the client asks (a\nseparate request), so the ``COUNT(*)`` is not paid on every page load.", "operationId": "count_usage_v1_usage_count_get", "parameters": [ { "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "start_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "title": "Start Date" } }, { "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "end_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "title": "End Date" } }, { "description": "Filter to a single user", "in": "query", "name": "user_id", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single user", "title": "User Id" } }, { "description": "Filter to a single status (e.g. 'success' or 'error')", "in": "query", "name": "status", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single status (e.g. 'success' or 'error')", "title": "Status" } }, { "description": "Filter to a single model", "in": "query", "name": "model", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single model", "title": "Model" } }, { "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "in": "query", "name": "endpoint", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "title": "Endpoint" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageCount" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Count Usage", "tags": [ "usage" ] } }, "/v1/usage/summary": { "get": { "description": "Aggregate spend, tokens, and request volume for the dashboard Usage page.\n\nRange-bounded (default last 30 days, hard-capped): unlike the raw ``/v1/usage``\nlist, every aggregate is scoped to a bounded window so it stays served by the\ntimestamp index. Returns grand totals, breakdowns by model / user / API key\n(top rows plus a reconciling ``other`` fold), and a UTC-bucketed time series.", "operationId": "usage_summary_v1_usage_summary_get", "parameters": [ { "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "start_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "title": "Start Date" } }, { "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "end_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "title": "End Date" } }, { "description": "Filter to a single user", "in": "query", "name": "user_id", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single user", "title": "User Id" } }, { "description": "Filter to a single status (e.g. 'success' or 'error')", "in": "query", "name": "status", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single status (e.g. 'success' or 'error')", "title": "Status" } }, { "description": "Filter to a single model", "in": "query", "name": "model", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single model", "title": "Model" } }, { "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "in": "query", "name": "endpoint", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "title": "Endpoint" } }, { "description": "Time-series granularity: 'hour' or 'day'", "in": "query", "name": "bucket", "required": false, "schema": { "default": "day", "description": "Time-series granularity: 'hour' or 'day'", "enum": [ "hour", "day" ], "title": "Bucket", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageSummary" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Usage Summary", "tags": [ "usage" ] } }, "/v1/usage/summary.csv": { "get": { "description": "Download the per-model / per-user / per-key breakdown as CSV.\n\nA dedicated route rather than a ``format=csv`` flag on ``/summary`` so that\nendpoint keeps a single JSON response model and a clean OpenAPI schema. The\nexport is **uncapped** (no top-N fold): finance wants every row. Kept separate\nfrom the bare-array ``/v1/usage`` contract, which is untouched.", "operationId": "usage_summary_csv_v1_usage_summary_csv_get", "parameters": [ { "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "start_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)", "title": "Start Date" } }, { "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "in": "query", "name": "end_date", "required": false, "schema": { "anyOf": [ { "format": "date-time", "type": "string" }, { "type": "null" } ], "description": "Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)", "title": "End Date" } }, { "description": "Filter to a single user", "in": "query", "name": "user_id", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single user", "title": "User Id" } }, { "description": "Filter to a single status (e.g. 'success' or 'error')", "in": "query", "name": "status", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single status (e.g. 'success' or 'error')", "title": "Status" } }, { "description": "Filter to a single model", "in": "query", "name": "model", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single model", "title": "Model" } }, { "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "in": "query", "name": "endpoint", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single endpoint (e.g. '/v1/chat/completions')", "title": "Endpoint" } } ], "responses": { "200": { "content": { "application/json": { "schema": {} } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Usage Summary Csv", "tags": [ "usage" ] } }, "/v1/users": { "get": { "description": "List all users with pagination.", "operationId": "list_users_v1_users_get", "parameters": [ { "in": "query", "name": "skip", "required": false, "schema": { "default": 0, "minimum": 0, "title": "Skip", "type": "integer" } }, { "in": "query", "name": "limit", "required": false, "schema": { "default": 100, "maximum": 1000, "minimum": 1, "title": "Limit", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/UserResponse" }, "title": "Response List Users V1 Users Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "List Users", "tags": [ "users" ] }, "post": { "description": "Create a new user.", "operationId": "create_user_v1_users_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateUserRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Create User", "tags": [ "users" ] } }, "/v1/users/{user_id}": { "delete": { "description": "Delete a user.", "operationId": "delete_user_v1_users__user_id__delete", "parameters": [ { "in": "path", "name": "user_id", "required": true, "schema": { "title": "User Id", "type": "string" } } ], "responses": { "204": { "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Delete User", "tags": [ "users" ] }, "get": { "description": "Get details of a specific user.", "operationId": "get_user_v1_users__user_id__get", "parameters": [ { "in": "path", "name": "user_id", "required": true, "schema": { "title": "User Id", "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get User", "tags": [ "users" ] }, "patch": { "description": "Update a user.", "operationId": "update_user_v1_users__user_id__patch", "parameters": [ { "in": "path", "name": "user_id", "required": true, "schema": { "title": "User Id", "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateUserRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserResponse" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Update User", "tags": [ "users" ] } }, "/v1/users/{user_id}/usage": { "get": { "description": "Get usage history for a specific user.", "operationId": "get_user_usage_v1_users__user_id__usage_get", "parameters": [ { "in": "path", "name": "user_id", "required": true, "schema": { "title": "User Id", "type": "string" } }, { "in": "query", "name": "skip", "required": false, "schema": { "default": 0, "minimum": 0, "title": "Skip", "type": "integer" } }, { "in": "query", "name": "limit", "required": false, "schema": { "default": 100, "maximum": 1000, "minimum": 1, "title": "Limit", "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/UsageLogResponse" }, "title": "Response Get User Usage V1 Users User Id Usage Get", "type": "array" } } }, "description": "Successful Response" }, "422": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } }, "description": "Validation Error" } }, "security": [ { "ApiKeyAuth": [] }, { "XApiKeyAuth": [] } ], "summary": "Get User Usage", "tags": [ "users" ] } } } }