{"openapi":"3.1.0","info":{"title":"Aiduct API","version":"1.0.0","description":"Unified API for chat, image, video, and audio models. Chat speaks OpenAI Chat Completions and Responses, Anthropic Messages and Google Gemini, so the OpenAI, Anthropic and Gemini SDKs and the Codex, Claude Code, Gemini CLI and pi agents work by changing only the base URL and the API key.","contact":{"name":"Aiduct","url":"https://aiduct.ai","email":"hello@aiduct.ai"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://api.aiduct.ai","description":"Production"}],"tags":[{"name":"Chat","description":"OpenAI ChatCompletion protocol — streaming + non-streaming"},{"name":"Messages","description":"Anthropic Messages protocol — Claude Code and the Anthropic SDKs"},{"name":"Responses","description":"OpenAI Responses protocol — Codex CLI and `responses.create`"},{"name":"Gemini","description":"Google Gemini protocol — Gemini CLI, `@google/genai` and pi"},{"name":"Images","description":"OpenAI Images protocol — text-to-image generation"},{"name":"Embeddings","description":"Vector embeddings for retrieval, clustering, classification"},{"name":"Audio","description":"Text-to-speech (TTS) and speech-to-text via the OpenAI audio protocols"},{"name":"Models","description":"Available model catalog + pricing"}],"security":[{"bearerAuth":[]},{"apiKeyAuth":[]},{"googApiKeyAuth":[]}],"paths":{"/v1/chat/completions":{"post":{"operationId":"createChatCompletion","tags":["Chat"],"summary":"Create a chat completion","description":"OpenAI ChatCompletion-compatible endpoint. Set `stream: true` to receive a Server-Sent Events stream where each `data:` line is a `chat.completion.chunk` payload terminated by `data: [DONE]`. Model id is the API-platform id from `GET /v1/models`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"},"examples":{"simple":{"summary":"Single-turn chat","value":{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"Hello!"}]}},"streaming":{"summary":"Streaming chat","value":{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Write a haiku about APIs"}],"stream":true}}}}}},"responses":{"200":{"description":"Chat completion (non-stream) or SSE event stream when `stream: true`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionResponse"}},"text/event-stream":{"schema":{"type":"string","description":"SSE: each event is `data: <ChatCompletionChunk JSON>` and the stream terminates with `data: [DONE]`."}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/messages":{"post":{"operationId":"createAnthropicMessage","tags":["Messages"],"summary":"Anthropic Messages (Claude Code protocol)","description":"Anthropic's Messages protocol, for Claude Code (`ANTHROPIC_BASE_URL=https://api.aiduct.ai`, no `/v1`) and the Anthropic SDKs. Every catalog chat model answers here: Claude models natively, others translated, with tool use, thinking and images kept. Authenticate with `x-api-key` or `Authorization: Bearer`; `anthropic-version` and `anthropic-beta` reach a natively served model. Set `stream: true` for Anthropic's `event: <type>` SSE stream. Errors use Anthropic's envelope. `usage` counts `input_tokens` without the cache, beside `cache_read_input_tokens` and `cache_creation_input_tokens`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagesRequest"},"examples":{"simple":{"summary":"Single user turn","value":{"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"Hi"}]}}}}}},"responses":{"200":{"description":"Anthropic Messages response (non-stream) or `event: <type>` SSE stream when `stream: true`","content":{"application/json":{"schema":{"type":"object"}},"text/event-stream":{"schema":{"type":"string","description":"SSE: each event is `event: <message_start|content_block_delta|message_stop|...>` followed by `data: <json>`."}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}}}}},"/v1/messages/count_tokens":{"post":{"operationId":"countAnthropicMessageTokens","tags":["Messages"],"summary":"Count the input tokens of a Messages request","description":"Anthropic's token-counting endpoint. A model served natively on this protocol is counted by its upstream; any other count is an estimate, marked by `x-aiduct-token-count: estimated`. Not billed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCountRequest"}}}},"responses":{"200":{"description":"`{ input_tokens }`","content":{"application/json":{"schema":{"type":"object","required":["input_tokens"],"properties":{"input_tokens":{"type":"integer"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}}}}},"/v1/responses":{"post":{"operationId":"createOpenAIResponse","tags":["Responses"],"summary":"OpenAI Responses API (Codex CLI protocol)","description":"OpenAI's Responses protocol, for the Codex CLI (a model provider with `base_url = \"https://api.aiduct.ai/v1\"` and `wire_api = \"responses\"`) and `responses.create` in the OpenAI SDKs. Every catalog chat model answers here: OpenAI models natively where the route allows it, others translated, including Codex's function, custom (`apply_patch`) and local shell tools and encrypted reasoning round trips. Stateless: send the whole conversation each turn. Set `stream: true` for the Responses SSE event stream.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsesRequest"},"examples":{"simple":{"summary":"Single-input response","value":{"model":"gpt-4o","input":"Write a haiku about API gateways."}}}}}},"responses":{"200":{"description":"Responses payload (non-stream) or SSE event stream","content":{"application/json":{"schema":{"type":"object"}},"text/event-stream":{"schema":{"type":"string","description":"OpenAI Responses SSE event stream"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/responses/input_tokens":{"post":{"operationId":"countOpenAIResponseInputTokens","tags":["Responses"],"summary":"Count the input tokens of a Responses request","description":"OpenAI's input-token counting endpoint. A model served natively on this protocol is counted by its upstream; any other count is an estimate, marked by `x-aiduct-token-count: estimated`. Not billed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCountRequest"}}}},"responses":{"200":{"description":"`{ object: \"response.input_tokens\", input_tokens }`","content":{"application/json":{"schema":{"type":"object","required":["object","input_tokens"],"properties":{"object":{"type":"string","enum":["response.input_tokens"]},"input_tokens":{"type":"integer"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1beta/models/{model}:generateContent":{"post":{"operationId":"geminiGenerateContent","tags":["Gemini"],"summary":"Gemini generateContent","description":"Google's Gemini protocol, for the Gemini CLI (`GOOGLE_GEMINI_BASE_URL=https://api.aiduct.ai`), `@google/genai` (`httpOptions.baseUrl`) and pi. Every catalog chat model answers here: Gemini models natively, others translated, with function calling and thinking kept. Authenticate with `x-goog-api-key`. Errors use Google's envelope.","parameters":[{"name":"model","in":"path","required":true,"schema":{"type":"string"},"description":"Catalog model id, e.g. `gemini-2.5-flash`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateContentRequest"}}}},"responses":{"200":{"description":"`GenerateContentResponse`","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeminiError"}}}}}}},"/v1beta/models/{model}:streamGenerateContent":{"post":{"operationId":"geminiStreamGenerateContent","tags":["Gemini"],"summary":"Gemini streamGenerateContent","description":"The streamed form of `generateContent`. Send `?alt=sse` for a server-sent event per `GenerateContentResponse` chunk, as the Gemini SDKs do.","parameters":[{"name":"model","in":"path","required":true,"schema":{"type":"string"}},{"name":"alt","in":"query","schema":{"type":"string","enum":["sse"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateContentRequest"}}}},"responses":{"200":{"description":"SSE stream of `GenerateContentResponse` chunks","content":{"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeminiError"}}}}}}},"/v1beta/models/{model}:countTokens":{"post":{"operationId":"geminiCountTokens","tags":["Gemini"],"summary":"Gemini countTokens","description":"Gemini's token-counting endpoint. A model served natively on this protocol is counted by its upstream; any other count is an estimate, marked by `x-aiduct-token-count: estimated`. Not billed.","parameters":[{"name":"model","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateContentRequest"}}}},"responses":{"200":{"description":"`{ totalTokens }`","content":{"application/json":{"schema":{"type":"object","required":["totalTokens"],"properties":{"totalTokens":{"type":"integer"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeminiError"}}}}}}},"/v1/images/generations":{"post":{"operationId":"createImageGeneration","tags":["Images"],"summary":"Generate or edit an image from a prompt","description":"OpenAI Images-compatible endpoint. Some models, such as `gpt-image-2`, also accept `input_media` reference images. No streaming.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationRequest"},"examples":{"fluxSchnell":{"summary":"Cheap and fast","value":{"model":"flux-schnell","prompt":"a red panda eating bamboo, studio photo","size":"1024x1024"}}}}}},"responses":{"200":{"description":"Generated images (URL or base64 per `response_format`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/videos/generations":{"post":{"operationId":"createVideoGeneration","tags":["Videos"],"summary":"Submit an async video-generation job","description":"Always async. Returns a queue ticket; poll the `status_url` until the job completes, then read the final result from `response_url`. Use `cancel_url` to abort. Optional `webhook_url` lets us POST `response.completed` to a customer endpoint (validated against SSRF: must be https in production, must resolve to a public IP).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoGenerationRequest"},"examples":{"textToVideo":{"summary":"Text to video","value":{"model":"kling-v2.1","prompt":"a red panda eating bamboo, cinematic","duration":5,"aspect_ratio":"16:9"}},"imageToVideo":{"summary":"Image to video","value":{"model":"kling-v2.1","prompt":"gentle camera push-in, cinematic lighting","input_media":[{"type":"image","role":"first_frame","url":"https://example.com/frame.png"}],"duration":5}}}}}},"responses":{"202":{"description":"Job accepted; poll the returned URLs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueTicket"}}}},"400":{"description":"Invalid request (bad model, unreachable webhook_url, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/queue/requests/{id}":{"get":{"operationId":"getQueueRequestResult","tags":["Queue"],"summary":"Fetch the queued job's result (or terminal-state payload)","description":"200 with the final result when status is `completed`. 200 with `{status:'failed'|'cancelled', error, ...}` when terminal but unsuccessful (no body retry, just inspect). 202 with the polling payload when still in progress.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Result or terminal status","content":{"application/json":{"schema":{"type":"object"}}}},"202":{"description":"Still pending/running — keep polling","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueStatus"}}}},"404":{"description":"Unknown request_id (or not owned by this API key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/queue/requests/{id}/status":{"get":{"operationId":"getQueueRequestStatus","tags":["Queue"],"summary":"Cheap poll of a job's current state","description":"Always returns 200 with the latest status. Safe to call at sub-second cadence — does not touch upstream providers.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Current job state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueStatus"}}}},"404":{"description":"Unknown request_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/queue/requests/{id}/cancel":{"post":{"operationId":"cancelQueueRequest","tags":["Queue"],"summary":"Cancel a queued job","description":"Marks the job as cancelled and best-effort asks the upstream provider to stop. Does NOT refund compute already consumed. Returns 409 if the job is already in a terminal state.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"request_id":{"type":"string"},"status":{"type":"string","example":"cancelled"}}}}}},"409":{"description":"Job already terminal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/embeddings":{"post":{"operationId":"createEmbedding","tags":["Embeddings"],"summary":"Create vector embeddings for text input","description":"OpenAI-compatible embeddings endpoint. Pass a single string or an array; receive one float (or base64) vector per input. Use `text-embedding-3-small` for cheap baselines and `text-embedding-3-large` for higher retrieval quality.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingRequest"},"examples":{"simple":{"summary":"Single string input","value":{"model":"text-embedding-3-small","input":"Aiduct is a unified AI API gateway."}},"batch":{"summary":"Batch of strings","value":{"model":"text-embedding-3-large","input":["hello","world"],"dimensions":1024}}}}}},"responses":{"200":{"description":"Embedding vectors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/audio/speech":{"post":{"operationId":"createAudioSpeech","tags":["Audio"],"summary":"Generate speech or queued music from text","description":"Model-specific audio generation endpoint. Speech models return audio bytes synchronously. `minimax-music-v2` returns a 202 queue ticket and rejects speech-only fields such as `voice` and `speed`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudioSpeechRequest"},"examples":{"alloyMp3":{"summary":"Alloy voice, mp3","value":{"model":"tts-1","input":"Hello from Aiduct.","voice":"alloy"}}}}}},"responses":{"200":{"description":"Raw audio bytes; Content-Type matches `response_format`.","content":{"audio/mpeg":{"schema":{"type":"string","format":"binary","description":"mp3 audio bytes (default)."}},"audio/opus":{"schema":{"type":"string","format":"binary"}},"audio/aac":{"schema":{"type":"string","format":"binary"}},"audio/flac":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"schema":{"type":"string","format":"binary"}},"audio/pcm":{"schema":{"type":"string","format":"binary"}}}},"202":{"description":"Queued music job accepted; poll the returned URLs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueTicket"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/audio/transcriptions":{"post":{"operationId":"createAudioTranscription","tags":["Audio"],"summary":"Transcribe audio into text","description":"OpenAI-compatible multipart speech-to-text endpoint. The gateway returns JSON transcription responses.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["model","file"],"properties":{"model":{"type":"string","example":"whisper-1"},"file":{"type":"string","format":"binary"},"language":{"type":"string","description":"Optional ISO-639-1 input language hint."},"prompt":{"type":"string","description":"Optional transcription style or context hint."},"response_format":{"type":"string","enum":["json"],"default":"json"},"temperature":{"type":"number","minimum":0,"maximum":1}}}}}},"responses":{"200":{"description":"Transcription text","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudioTranscriptionResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/models":{"get":{"operationId":"listModels","tags":["Models"],"summary":"OpenAI-compatible model list","description":"Returns every model the gateway can route to in OpenAI's `{object:'list', data:[…]}` shape, augmented with `available`, `display_name`, `description`, and `pricing`. A request carrying `anthropic-version`, as the Anthropic SDKs send, gets the chat models in Anthropic's `{data, has_more, first_id, last_id}` shape instead.","responses":{"200":{"description":"Model list","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"type":"object"}}}}}}}}}},"/v1/models/{model}":{"get":{"operationId":"retrieveModel","tags":["Models"],"summary":"Retrieve one model","description":"One model by its catalog id or a declared alias, in OpenAI's shape, or Anthropic's when the request carries `anthropic-version`.","parameters":[{"name":"model","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Model","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown model","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1beta/models":{"get":{"operationId":"geminiListModels","tags":["Gemini"],"summary":"Gemini models.list","description":"The chat models as Gemini `Model` resources named `models/{id}`, each supporting `generateContent`, `streamGenerateContent` and `countTokens`.","responses":{"200":{"description":"`{ models: [...] }`","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1beta/models/{model}":{"get":{"operationId":"geminiGetModel","tags":["Gemini"],"summary":"Gemini models.get","description":"One chat model as a Gemini `Model` resource.","parameters":[{"name":"model","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Model","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown or non-chat model","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeminiError"}}}}}}},"/v1/models/catalog":{"get":{"operationId":"getPublicModelCatalog","tags":["Models"],"summary":"SEO-friendly merged model catalog","description":"Slug-friendly catalog used by aiduct.ai marketing pages. Includes pre-formatted price labels and a single-line price summary. Cached 60s.","responses":{"200":{"description":"Catalog","content":{"application/json":{"schema":{"type":"object","required":["models","generatedAt"],"properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/ModelCatalogEntry"}},"generatedAt":{"type":"string","format":"date-time"}}}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Aiduct API key sent as `Authorization: Bearer sk-aiduct-…`. Get one from the dashboard."},"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Aiduct API key sent as `x-api-key: sk-aiduct-…`, as the Anthropic SDKs do."},"googApiKeyAuth":{"type":"apiKey","in":"header","name":"x-goog-api-key","description":"Aiduct API key sent as `x-goog-api-key: sk-aiduct-…`, as the Gemini SDKs do."}},"schemas":{"PlatformMediaInput":{"type":"object","required":["type","url"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["image","video","audio"]},"url":{"type":"string","format":"uri","description":"Public URL or data URL for the referenced media."},"role":{"type":"string","description":"Model-specific role such as `first_frame`, `last_frame`, `reference`, `reference_image`, `reference_video`, `reference_audio`, `source`, or `mask`."},"mime_type":{"type":"string","example":"image/png"},"metadata":{"type":"object","additionalProperties":true}}},"ChatMessage":{"type":"object","required":["role"],"properties":{"role":{"type":"string","enum":["system","user","assistant","tool"]},"content":{"oneOf":[{"type":"string"},{"type":"array","items":{"oneOf":[{"type":"object","required":["type","text"],"properties":{"type":{"const":"text"},"text":{"type":"string"}}},{"type":"object","required":["type","image_url"],"properties":{"type":{"const":"image_url"},"image_url":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"detail":{"type":"string","enum":["auto","low","high"]}}}}}]}},{"type":"null"}]},"name":{"type":"string"},"tool_call_id":{"type":"string"},"reasoning_content":{"type":"string","description":"Optional assistant reasoning history accepted for thinking models. Provider adapters may omit it when an upstream does not accept reasoning in request messages."},"tool_calls":{"type":"array","items":{"type":"object","required":["id","type","function"],"properties":{"id":{"type":"string"},"type":{"const":"function"},"function":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string"},"arguments":{"type":"string"}}}}}}}},"ChatCompletionRequest":{"type":"object","required":["model","messages"],"properties":{"model":{"type":"string","description":"API-platform model id, e.g. `gpt-4o-mini` or `claude-sonnet-4-5`. See `GET /v1/models` for the live catalog."},"messages":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"},"minItems":1},"temperature":{"type":"number","minimum":0,"maximum":2},"top_p":{"type":"number","minimum":0,"maximum":1},"max_tokens":{"type":"integer","minimum":1},"stream":{"type":"boolean","default":false},"stop":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"tools":{"type":"array","items":{"type":"object","required":["type","function"],"properties":{"type":{"const":"function"},"function":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":{"type":"object"}}}}}},"tool_choice":{},"response_format":{"type":"object","properties":{"type":{"type":"string","enum":["text","json_object"]}}},"user":{"type":"string"},"thinking":{"anyOf":[{"type":"boolean"},{"type":"object","required":["effort"],"properties":{"effort":{"type":"string","enum":["none","low","high","max"]}}}],"description":"Thinking-mode control for thinking-capable models that support it (see `supported_parameters` in `GET /v1/models`). `true` selects the model's default effort, `false` turns thinking off, and `{ \"effort\": \"none\" | \"auto\" | \"low\" | \"high\" | \"max\" }` selects an effort (`none` is off, `auto` lets the model decide per request). Omitting the field keeps the model's declared default. The gateway translates this into the upstream's own thinking parameter; it is never forwarded as-is. Models that declare they cannot think while a tool call is forced run without thinking whenever `tool_choice` forces a call."}}},"ChatCompletionResponse":{"type":"object","required":["id","object","model","choices","usage"],"properties":{"id":{"type":"string"},"object":{"const":"chat.completion"},"created":{"type":"integer"},"model":{"type":"string"},"choices":{"type":"array","items":{"type":"object","required":["index","message","finish_reason"],"properties":{"index":{"type":"integer"},"message":{"$ref":"#/components/schemas/ChatMessage"},"finish_reason":{"type":"string","enum":["stop","length","tool_calls","content_filter"]}}}},"usage":{"type":"object","required":["prompt_tokens","completion_tokens","total_tokens"],"properties":{"prompt_tokens":{"type":"integer","description":"Every input token, including those read from or written to a prompt cache."},"completion_tokens":{"type":"integer","description":"Every output token, reasoning included."},"total_tokens":{"type":"integer"},"prompt_tokens_details":{"type":"object","properties":{"audio_tokens":{"type":"integer"},"cached_tokens":{"type":"integer","description":"Input read from a prompt cache; part of `prompt_tokens`."},"cache_write_tokens":{"type":"integer","description":"Input written to a prompt cache; part of `prompt_tokens`."},"cache_write_1h_tokens":{"type":"integer","description":"The part of `cache_write_tokens` written with a one-hour TTL, when the model prices it separately."},"web_search":{"type":"integer","description":"Server-side web searches billed per call."},"image":{"type":"integer"}}},"completion_tokens_details":{"type":"object","properties":{"accepted_prediction_tokens":{"type":"integer"},"audio_tokens":{"type":"integer"},"reasoning_tokens":{"type":"integer"},"rejected_prediction_tokens":{"type":"integer"}}}}}}},"ImageGenerationRequest":{"type":"object","required":["model","prompt"],"properties":{"model":{"type":"string","description":"e.g. `gpt-image-2`, `flux-schnell`, `flux-pro-v1.1`"},"prompt":{"type":"string","minLength":1},"input_media":{"type":"array","items":{"$ref":"#/components/schemas/PlatformMediaInput"},"description":"Optional reference/source images for models that support image input, such as `gpt-image-2`. Use role `reference` for the subject the output should be of; models that bind it also accept role `style` for a picture whose look should be imitated rather than kept."},"n":{"type":"integer","minimum":1,"maximum":8},"size":{"type":"string","description":"e.g. `1024x1024`"},"quality":{"type":"string","enum":["standard","hd","low","medium","high","xhigh","max","auto"],"description":"Model-specific quality. Image 2.5 accepts native levels; standard maps to medium and hd maps to high."},"background":{"type":"string","enum":["auto","opaque","transparent"],"description":"Image 2.5 background. Transparent output requires png or webp."},"output_format":{"type":"string","enum":["png","jpeg","webp"],"description":"Image 2.5 output encoding; independent of the response URL/base64 envelope."},"style":{"type":"string","enum":["vivid","natural"]},"response_format":{"type":"string","enum":["url","b64_json"]}}},"VideoGenerationRequest":{"type":"object","required":["model","prompt"],"properties":{"model":{"type":"string","example":"kling-v2.1"},"prompt":{"type":"string","minLength":1},"negative_prompt":{"type":"string"},"input_media":{"type":"array","items":{"$ref":"#/components/schemas/PlatformMediaInput"},"description":"Model-configured media inputs. Use roles such as `first_frame` for image-to-video and `reference` for reference-driven video models."},"duration":{"type":"integer","example":5},"aspect_ratio":{"type":"string","example":"16:9"},"resolution":{"type":"string","example":"1080p"},"cfg_scale":{"type":"number"},"loop":{"type":"boolean"},"seed":{"type":"integer"},"webhook_url":{"type":"string","format":"uri","description":"Optional. Receives `response.completed` POST when the job finishes."}}},"ImageGenerationResponse":{"type":"object","required":["created","data"],"properties":{"created":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"b64_json":{"type":"string","format":"byte"},"revised_prompt":{"type":"string"}}}}}},"MessagesRequest":{"type":"object","required":["model","max_tokens","messages"],"properties":{"model":{"type":"string","description":"Any chat model id from the catalog, e.g. `claude-sonnet-4-5`. Claude models are served natively; other models are translated to and from this protocol."},"max_tokens":{"type":"integer","minimum":1},"messages":{"type":"array","items":{"type":"object"}},"system":{"oneOf":[{"type":"string"},{"type":"array"}]},"temperature":{"type":"number"},"top_p":{"type":"number"},"top_k":{"type":"integer"},"stop_sequences":{"type":"array","items":{"type":"string"}},"stream":{"type":"boolean","default":false},"tools":{"type":"array","items":{"type":"object"}},"tool_choice":{},"thinking":{"type":"object","description":"`{ type: \"enabled\", budget_tokens }`, `{ type: \"adaptive\" }` or `{ type: \"disabled\" }`."},"output_config":{"type":"object","description":"`effort` (`low` … `max`) and structured `format`."},"metadata":{}}},"TokenCountRequest":{"type":"object","required":["model"],"description":"The request body you would send to create the message or response, minus generation settings.","properties":{"model":{"type":"string"}},"additionalProperties":true},"EmbeddingRequest":{"type":"object","required":["model","input"],"properties":{"model":{"type":"string","example":"text-embedding-3-small"},"input":{"oneOf":[{"type":"string","minLength":1},{"type":"array","items":{"type":"string","minLength":1}}]},"dimensions":{"type":"integer","minimum":1},"encoding_format":{"type":"string","enum":["float","base64"]},"user":{"type":"string"}}},"EmbeddingResponse":{"type":"object","required":["object","model","data","usage"],"properties":{"object":{"const":"list"},"model":{"type":"string"},"data":{"type":"array","items":{"type":"object","required":["object","index","embedding"],"properties":{"object":{"const":"embedding"},"index":{"type":"integer"},"embedding":{"oneOf":[{"type":"array","items":{"type":"number"}},{"type":"string","format":"byte"}]}}}},"usage":{"type":"object","required":["prompt_tokens","total_tokens"],"properties":{"prompt_tokens":{"type":"integer"},"total_tokens":{"type":"integer"}}}}},"AudioSpeechRequest":{"type":"object","required":["model","input"],"properties":{"model":{"type":"string","example":"tts-1"},"input":{"type":"string","minLength":1,"maxLength":4096},"voice":{"type":"string","description":"Model-specific voice id. Omit it to use that model's configured default. Music models reject this field."},"response_format":{"type":"string","enum":["mp3","opus","aac","flac","wav","pcm"],"description":"Model-specific output format. Gemini TTS supports wav only, VibeVoice returns mp3, and MiniMax Music supports mp3 or wav."},"speed":{"type":"number","description":"Model-specific speech speed. Models without an explicit speed contract, including music, Gemini TTS, and VibeVoice, reject this field."},"webhook_url":{"type":"string","format":"uri","description":"Completion webhook for queued music generation only."}}},"AudioTranscriptionResponse":{"type":"object","required":["text"],"properties":{"text":{"type":"string"}}},"ResponsesRequest":{"type":"object","required":["model","input"],"properties":{"model":{"type":"string","description":"Any chat model id from the catalog, e.g. `gpt-4o`. OpenAI models are served natively where the route allows it; other models are translated to and from this protocol."},"input":{"description":"The whole conversation. Responses are not stored: send every turn each time, as Codex does with `store: false`."},"instructions":{"type":"string"},"tools":{"type":"array","items":{"type":"object"}},"tool_choice":{},"parallel_tool_calls":{"type":"boolean"},"temperature":{"type":"number"},"top_p":{"type":"number"},"max_output_tokens":{"type":"integer","minimum":1},"store":{"type":"boolean","description":"Accepted and ignored; `previous_response_id` and `conversation` are rejected."},"include":{"type":"array","items":{"type":"string"},"description":"`reasoning.encrypted_content` returns reasoning items that can be sent back in `input`."},"stream":{"type":"boolean","default":false},"reasoning":{"type":"object","description":"`effort`: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max` or `ultra`, fitted to what the model supports."},"metadata":{},"text":{}}},"GenerateContentRequest":{"type":"object","required":["contents"],"properties":{"contents":{"type":"array","items":{"type":"object"}},"systemInstruction":{"type":"object"},"tools":{"type":"array","items":{"type":"object"}},"toolConfig":{"type":"object"},"generationConfig":{"type":"object","description":"Includes `maxOutputTokens`, `temperature`, `responseMimeType`/`responseSchema` and `thinkingConfig` (`thinkingBudget` or `thinkingLevel`)."}}},"ModelCatalogEntry":{"type":"object","required":["id","slug","providerKey","capability","displayName","available","pricing","priceSummary"],"properties":{"id":{"type":"string","example":"gpt-4o-mini"},"slug":{"type":"string","example":"openai-gpt-4o-mini"},"providerKey":{"type":"string","example":"openai"},"capability":{"type":"string","enum":["chat","image","video","audio"]},"displayName":{"type":"string"},"description":{"type":"string","nullable":true},"available":{"type":"boolean","description":"Whether this provider key is configured on the gateway"},"pricing":{"type":"array","items":{"type":"object","required":["unit","microCentsPerUnit","perUnitLabel"],"properties":{"unit":{"type":"string","enum":["tokens_in","tokens_out","image","second"]},"microCentsPerUnit":{"type":"integer"},"perUnitLabel":{"type":"string","example":"$0.15 / 1M input tokens"}}}},"priceSummary":{"type":"string"}}},"AnthropicError":{"type":"object","required":["type","error"],"properties":{"type":{"type":"string","enum":["error"]},"error":{"type":"object","required":["type","message"],"properties":{"type":{"type":"string","example":"invalid_request_error"},"message":{"type":"string"}}},"request_id":{"type":"string"}}},"GeminiError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","status"],"properties":{"code":{"type":"integer","example":400},"message":{"type":"string"},"status":{"type":"string","example":"INVALID_ARGUMENT"}}}}},"ApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message","type"],"properties":{"message":{"type":"string"},"type":{"type":"string","example":"invalid_request_error"},"code":{"type":"string"},"param":{"type":"string"}}}}},"QueueTicket":{"type":"object","required":["request_id","status_url","response_url","cancel_url"],"properties":{"request_id":{"type":"string","example":"req_01J4..."},"status_url":{"type":"string","format":"uri","example":"https://api.aiduct.ai/v1/queue/requests/req_01J4.../status"},"response_url":{"type":"string","format":"uri","example":"https://api.aiduct.ai/v1/queue/requests/req_01J4..."},"cancel_url":{"type":"string","format":"uri","example":"https://api.aiduct.ai/v1/queue/requests/req_01J4.../cancel"}}},"QueueStatus":{"type":"object","required":["request_id","status"],"properties":{"request_id":{"type":"string"},"status":{"type":"string","enum":["pending","submitting","running","finalizing","completed","failed","cancelled"]},"stage":{"type":"string"},"progress":{"type":"number"},"created_at":{"type":"string","format":"date-time"},"started_at":{"type":"string","format":"date-time","nullable":true},"finished_at":{"type":"string","format":"date-time","nullable":true},"duration_ms":{"type":"integer","nullable":true},"error":{"type":"string","nullable":true},"upstream_request_id":{"type":"string","nullable":true},"next_poll_at":{"type":"string","format":"date-time","nullable":true},"webhook_status":{"type":"string","nullable":true},"billing":{"type":"object","properties":{"status":{"type":"string"},"baseChargeMicroCents":{"type":"integer"},"profitRatioBps":{"type":"integer"},"profitMicroCents":{"type":"integer"},"chargeMicroCents":{"type":"integer"}}},"response_url":{"type":"string","format":"uri"},"cancel_url":{"type":"string","format":"uri"}}}}}}