{"openapi":"3.1.0","info":{"title":"OpenScale API","version":"1.0","description":"OpenScale serves open models in the API formats your tools already speak: OpenAI Chat\nCompletions, OpenAI Responses and Anthropic Messages. Point an OpenAI SDK at `https://api.openscale.so/v1`\n(or an Anthropic SDK at `https://api.openscale.so/anthropic`), send your OpenScale key, and your existing code\nruns unchanged.\n\n```python\nfrom openai import OpenAI\n\nclient = OpenAI(base_url=\"https://api.openscale.so/v1\", api_key=\"sk-openscale-...\")\nresp = client.chat.completions.create(\n    model=\"deepseek/deepseek-v4.1-flash\",\n    messages=[{\"role\": \"user\", \"content\": \"Hello from OpenScale\"}],\n)\nprint(resp.choices[0].message.content)\n```\n\nUsing a coding agent? The [agent setup guide](https://openscale.so/setup?utm_source=api_reference&utm_medium=docs) has a tested, copy-paste setup for\nClaude Code, Codex, OpenCode and the other popular agents.\n\n## API formats\n\n| Format | Path on `api.openscale.so` | Used by |\n| --- | --- | --- |\n| OpenAI Chat Completions | `/v1/chat/completions` | OpenAI SDKs, most agents and apps |\n| OpenAI Responses | `/v1/responses` | Codex and Responses SDKs |\n| Anthropic Messages | `/anthropic/v1/messages` | Claude Code and Anthropic SDKs |\n\nAll three share one key, one balance and the same rate limits, prices and cache discounts.\nOn the Anthropic endpoint, send the key as `x-api-key` or a Bearer token. Any `claude-*`\nmodel name runs DeepSeek V4.1 Flash, so tools that only offer Claude models work as they are;\nextended thinking maps to reasoning, and Anthropic server tools (web search, code execution)\nare not available. `POST https://api.openscale.so/anthropic/v1/messages/count_tokens` returns the exact count the request is\nbilled for (images, and models whose tokenizer we do not carry, are estimated).\n\n## Responses API compatibility\n\n`POST /v1/responses` follows the OpenAI Responses API: the same request fields, output items,\nstreaming events, error shapes and stored state, so OpenAI SDKs (`responses.create`,\n`responses.stream`, `responses.parse`, `responses.retrieve`, `conversations`) and the Agents\nSDKs work by changing the base URL. As on OpenAI, responses are stored by default, so you can\ncontinue a conversation with `previous_response_id` or a `conversation`, run a response in the\n`background` and retrieve it later. Send `store: false` to store nothing and send the whole\nconversation as `input` each turn instead. What is stored, for how long, and how to turn storage\noff for your account: see Data retention below.\n\n**Tool rules are guaranteed.** When a request sets `strict: true` on a function tool, uses\n`tool_choice` (`required`, a named tool or `allowed_tools`) or sets\n`parallel_tool_calls: false`, OpenScale checks every tool call before you see it: arguments\nmatch the JSON schema (types, `required`, `additionalProperties: false`, `enum`, `format`,\n`pattern`), only allowed tools are called, and at most one call comes back when parallel calls\nare off. A reply that breaks a rule is stopped and retried, and never returned; if no valid\nreply arrives within three attempts the request fails with `500` and\n`code: tool_call_validation_failed` (in a stream: an `error` event, then\n`response.failed`). Failed attempts are not billed. Streams with tool rules send reasoning as\nit is generated, and text and tool calls once they have been checked. A\n`strict: true` schema must follow the Structured Outputs rules (every object sets\n`additionalProperties: false` and lists all properties in `required`; no `allOf`, `not` or\n`if`), or the request is refused with `400` naming the parameter. Function tools without\n`strict` are not checked and read back as `strict: false`.\n\n| Field or tool | Status |\n| --- | --- |\n| `input` (messages, function, custom, shell, local shell, apply patch and tool search items, reasoning items), `instructions`, `stream`, `temperature`, `top_p`, `max_output_tokens` (16 to the model limit), `text.format`, `reasoning` | Supported |\n| `tools`: `function` (with `strict`), `custom`, `namespace`, `shell`, `local_shell`, `apply_patch`, `tool_search` with `execution: \"client\"`, `defer_loading` | Supported (all run by your client) |\n| `tool_choice`: `auto`, `none`, `required`, a named tool, `allowed_tools`; `parallel_tool_calls` | Supported and enforced |\n| `top_logprobs`, `include: [\"message.output_text.logprobs\"]` | Supported |\n| `phase` on assistant messages | Supported: every assistant `message` in the output has `phase`: `commentary` for text the model wrote before a tool call in the same response (always, when `tool_choice` forces a call), `final_answer` otherwise. In a stream it is on `response.output_item.done` (and already on `response.output_item.added` when `tool_choice` forces a call). Assistant messages you send back in `input` may keep it |\n| `include: [\"reasoning.encrypted_content\"]` | Supported (reasoning always comes back with `encrypted_content`, readable `reasoning_text` content, and a summary when `reasoning.summary` is set) |\n| Images (`input_image` with a URL or data URL, `detail`), including images returned in `function_call_output` | Supported |\n| `POST /v1/responses/input_tokens` | Supported (exact counts for text and tools; images and models whose tokenizer we do not carry are estimated) |\n| `prompt_cache_options.prewarm` | Supported (fills the prompt cache and returns a completed response with no output) |\n| `metadata`, `user`, `safety_identifier`, `prompt_cache_key`, `max_tool_calls` | Accepted and echoed in the response |\n| `service_tier` | `priority` runs the request in fast mode when it is available (see Fast mode); any other value runs at the standard tier. The response reports the tier that served it |\n| `store` | Supported. Defaults to `true`: the response is stored for 30 days. `false` stores nothing |\n| `previous_response_id` | Supported: the earlier responses' input and output items come before your input (their `instructions` do not carry over). An id that is unknown, deleted, past its 30 days or another account's is a `400` with `code: previous_response_not_found` |\n| `conversation` and the Conversations API (`/v1/conversations` and its items) | Supported: the conversation's items come before your input, and the input and output are added to it when the response finishes. Cannot be combined with `previous_response_id` |\n| `background: true` | Supported: answered at once with a `queued` response that runs to the end whether or not you stay connected (up to 29 minutes). Poll `GET /v1/responses/{id}`, resume its stream with `?stream=true&starting_after=`, or cancel it with `POST /v1/responses/{id}/cancel` |\n| `item_reference` items | Supported for items of your stored responses and conversations |\n| `GET` and `DELETE /v1/responses/{id}`, `GET /v1/responses/{id}/input_items` | Supported |\n| `web_search`, `web_search_preview`, a hosted `tool_search` | Left out of the request and named in the `x-openscale-ignored-tools` response header (deferred tools are then loaded directly) |\n| `file_search`, `code_interpreter`, `image_generation`, `computer`, `computer_use_preview`, `mcp`, `programmatic_tool_calling` | Refused with `400` (`param: tools[i].type`); define the capability as a function tool instead |\n| `input_file` with `file_data` (a base64 data URL) or `file_url` (public `https` URLs) | Supported for PDFs (their text, page by page), images (read as `input_image`) and text files (txt, md, csv, json, html, xml, yaml, code). Up to 20 MB and 500 pages a file, 20 files and 50 MB a request. Other types (Word, Excel, audio) are a `400` naming the parameter. Stored responses keep the text read from a file, not the file |\n| `prompt` (`id`, `version`, `variables`) | Supported with prompts you save through `/v1/prompts` (see Prompts below). Variables fill `{{name}}` placeholders with text, or with an `input_image` or `input_file` in user messages. An unknown prompt or version, a missing variable or one the prompt does not use is a `400` |\n| `POST /v1/responses/compact`, `compaction` items | Supported: returns `response.compaction` with your user messages and a `compaction` item that stands for the rest; send that output as the next input. A compaction item that OpenScale did not create, or that was changed, is a `400` |\n| `context_management: [{\"type\": \"compaction\", \"compact_threshold\": n}]`, `compaction_trigger` items | Supported: past `n` input tokens the conversation is summarized first; the response starts with a `compaction` item (streamed with `response.compaction.compacting`) that replaces everything before it in later turns, and its usage includes the summary. A final `compaction_trigger` item returns just the compaction |\n| `truncation: \"auto\"` | Supported: when the input does not fit the context window, the oldest items are dropped (a tool call is always dropped with its output, reasoning with its turn); your instructions and newest item are kept. `disabled` (the default) answers `400` with `code: context_length_exceeded` |\n| WebSocket mode (`response.create` over `wss://`) | Not available yet; use HTTP streaming (`stream: true`) |\n| Images and files by `file_id` | Refused with `400` naming the parameter; send them by URL or as data |\n\nEvery refusal uses the OpenAI error shape `{\"error\": {\"message\", \"type\", \"param\", \"code\"}}`\nwith `param` set to the field at fault.\n\n## Prompts\n\nSave reusable prompts and use them by id in `POST /v1/responses` with\n`prompt: {\"id\": \"pmpt_...\", \"version\": \"2\", \"variables\": {...}}` (leave out `version` for the\nlatest). A prompt holds `instructions`, `input` messages and default settings (`model`,\n`tools`, `tool_choice`, `text`, `reasoning`, `temperature`, `top_p`,\n`max_output_tokens`, `parallel_tool_calls`, `truncation`); fields you send with the request\nwin. Its instructions come first, its messages before your `input`.\n\n| Endpoint | Does |\n| --- | --- |\n| `POST /v1/prompts` | Create a prompt (version `1`) |\n| `POST /v1/prompts/{id}` | Save a new version (versions never change) |\n| `GET /v1/prompts/{id}` | The latest version, or `?version=` |\n| `GET /v1/prompts`, `GET /v1/prompts/{id}/versions` | List prompts, or a prompt's versions |\n| `DELETE /v1/prompts/{id}` | Delete a prompt and all its versions |\n\nPrompts belong to your account: every key on it can use them.\n\n## Authentication\n\nCreate a key in the dashboard ([sign up](https://app.openscale.so/signup?utm_source=api_reference&utm_medium=docs) if you have no account yet) and send it\non every request:\n\n```\nAuthorization: Bearer sk-openscale-...\n```\n\nKeys are shown once when created. A missing or revoked key returns `401`.\n\nAn OpenScale Unlimited plan comes with its own keys. Every key has one type, set when you create it:\n\n- **Plan keys** (`sk-openscale-plan-...`) are covered by your plan on its included models while\n  the plan is active, and never bill your balance. Any other model, fast mode included, returns\n  `400` (`model_not_in_plan`).\n- **Pay-as-you-go keys** (`sk-openscale-...`) bill your balance on every model, including the\n  plan's models.\n\nSubscribing never changes an existing key. Create keys of either type under API keys in the dashboard.\n\n## Command line\n\nThe OpenScale CLI does everything from a terminal: sign in, keys, models, chat, agent setup,\nbalance, usage and limits. Install it with npm (Node 18 or newer, on macOS, Linux or Windows):\n\n```bash\nnpm i -g openscale-cli\n```\n\nTo try it without installing: `npx openscale-cli --help`. No Node? On macOS or Linux:\n\n```bash\ncurl -fsSL https://openscale.so/install | sh\n```\n\nWith Homebrew: `brew install afgventura/tap/openscale`.\n\nIt installs `openscale` and its short alias `osc`. Then sign in once; the browser opens to\napprove this device, and the CLI keeps a key of its own for model calls:\n\n```bash\nopenscale login\nopenscale chat \"Hello from OpenScale\"\nopenscale setup claude-code\nopenscale balance\n```\n\n`openscale --help` lists every command, and every command takes `--json` for scripts. In CI,\nset `OPENSCALE_API_KEY` instead of signing in: models, chat, batch, balance, usage and limits\nwork with a key alone. Signed-in devices are listed, and can be signed out, in the dashboard's\nSettings, Devices. Exit codes: `0` ok, `1` error, `2` usage, `3` sign-in needed, `4` out of\ncredit, `5` limit reached.\n\n## Models and pricing\n\nPrices are USD per 1M tokens. A struck figure is a list price we sell under. Cached input tokens\nare prompt tokens billed at the cached rate, reported in\n`usage.prompt_tokens_details.cached_tokens`.\n\n| Model id | Name | Input | Cached input | Output |\n| --- | --- | --- | --- | --- |\n| `deepseek/deepseek-v4.1-flash` | DeepSeek V4.1 Flash | ~~$0.12~~ $0.06 | ~~$0.006~~ $0.003 | ~~$0.48~~ $0.24 |\n| `z-ai/glm-5.3-flash` | GLM 5.3 Flash | ~~$0.15~~ $0.12 | ~~$0.03~~ $0.024 | ~~$0.50~~ $0.40 |\n| `deepseek/deepseek-v4.1-flash-1017` | DeepSeek V4.1 Flash 1017 | ~~$0.12~~ $0.06 | ~~$0.006~~ $0.003 | ~~$0.48~~ $0.24 |\n| `deepseek/deepseek-v4.1-flash-0910` | DeepSeek V4.1 Flash 0910 | ~~$0.12~~ $0.06 | ~~$0.006~~ $0.003 | ~~$0.48~~ $0.24 |\n| `z-ai/glm-5.3-flash-0828` | GLM 5.3 Flash 0828 | ~~$0.15~~ $0.12 | ~~$0.03~~ $0.024 | ~~$0.50~~ $0.40 |\n| `deepseek/deepseek-v4.1-flash:fast` | DeepSeek V4.1 Flash (fast) | ~~$0.56~~ $0.28 | ~~$0.056~~ $0.028 | ~~$2.20~~ $1.10 |\n| `deepseek/deepseek-v4.1-flash-1017:fast` | DeepSeek V4.1 Flash 1017 (fast) | ~~$0.56~~ $0.28 | ~~$0.056~~ $0.028 | ~~$2.20~~ $1.10 |\n| `deepseek/deepseek-v4.1-flash-0910:fast` | DeepSeek V4.1 Flash 0910 (fast) | ~~$0.56~~ $0.28 | ~~$0.056~~ $0.028 | ~~$2.20~~ $1.10 |\n\n## Model limits and capabilities\n\nThe context length covers the prompt plus `max_tokens`. A `max_tokens` (or\n`max_completion_tokens`) above the output limit is refused with `400` before any work is done.\nImages are sent as `image_url` content parts and billed as prompt tokens. Speed is output tokens\nper second after the first token, a floor under the measured median.\n\n| Model id | Context (tokens) | Max output (tokens) | Speed | Input | Capabilities |\n| --- | --- | --- | --- | --- | --- |\n| `deepseek/deepseek-v4.1-flash` | 1,048,568 | 384,000 | 200+ tok/s | Text, Images | tools, structured outputs, reasoning |\n| `z-ai/glm-5.3-flash` | 1,048,576 | 131,072 | 100+ tok/s | Text, Images | tools, structured outputs, reasoning |\n| `deepseek/deepseek-v4.1-flash-1017` | 1,048,568 | 384,000 | 200+ tok/s | Text, Images | tools, structured outputs, reasoning |\n| `deepseek/deepseek-v4.1-flash-0910` | 1,048,568 | 384,000 | 200+ tok/s | Text, Images | tools, structured outputs, reasoning |\n| `z-ai/glm-5.3-flash-0828` | 1,048,576 | 131,072 | 100+ tok/s | Text, Images | tools, structured outputs, reasoning |\n| `deepseek/deepseek-v4.1-flash:fast` | 1,048,568 | 384,000 | ~2x standard | Text, Images | tools, structured outputs, reasoning |\n| `deepseek/deepseek-v4.1-flash-1017:fast` | 1,048,568 | 384,000 | ~2x standard | Text, Images | tools, structured outputs, reasoning |\n| `deepseek/deepseek-v4.1-flash-0910:fast` | 1,048,568 | 384,000 | ~2x standard | Text, Images | tools, structured outputs, reasoning |\n\n`GET /models` returns the same catalog as data: prices, limits, supported parameters, capacity\nand serving location. Use the returned id unchanged in the `model` field. Every model is\nserved from Singapore.\n\n## Model versions\n\nEach plain model id always runs the latest version of its model. When a lab releases an update,\nwe test it, move the plain id to it and announce the change. Responses name the version that\nserved them in `model` (today `deepseek/deepseek-v4.1-flash-1017` for `deepseek/deepseek-v4.1-flash`, `z-ai/glm-5.3-flash-0828` for `z-ai/glm-5.3-flash`).\n\nTo stay on one version, use its pinned id. A pinned id never changes:\n\n| Model id | Version | Released |\n| --- | --- | --- |\n| `deepseek/deepseek-v4.1-flash-1017` | 1017 (latest) | 17 Oct 2026 |\n| `deepseek/deepseek-v4.1-flash-0910` | 0910 | 10 Sep 2026 |\n| `z-ai/glm-5.3-flash-0828` | 0828 (latest) | 28 Aug 2026 |\n\nEvery version of a model has the same price, limits and features, and they share one rate limit\nbudget. A pinned version stays available as long as we can serve it, and we announce a\nretirement before it happens. Fast mode works the same way: `deepseek/deepseek-v4.1-flash:fast` runs the latest version on fast serving, and `deepseek/deepseek-v4.1-flash-1017:fast`, `deepseek/deepseek-v4.1-flash-0910:fast` never changes; `\"service_tier\": \"priority\"` on a pinned id selects its pinned fast serving where there is one.\n\n**20 Oct 2026:** `deepseek/deepseek-v4.1-flash` moved to version 1017, which DeepSeek reports is better at\ncoding and agent tasks and finishes them with shorter outputs. Version 0910 stays available as\n`deepseek/deepseek-v4.1-flash-0910`. GLM 5.3 Flash joined the catalog as `z-ai/glm-5.3-flash`\n(version 0828).\n\n## Fast mode\n\nFast mode is the same model on faster serving, at a higher price: about twice the output speed\nand a shorter wait for the first token. Select it with the `:fast` model id, or send\n`\"service_tier\": \"priority\"` with the standard id on Chat Completions or Responses. Every\nresponse reports the tier that served it in `service_tier`: `priority` for fast mode,\n`default` otherwise.\n\n| Fast model id | Same model as | Input | Cached input | Output |\n| --- | --- | --- | --- | --- |\n| `deepseek/deepseek-v4.1-flash:fast` | `deepseek/deepseek-v4.1-flash` | ~~$0.56~~ $0.28 | ~~$0.056~~ $0.028 | ~~$2.2~~ $1.1 |\n| `deepseek/deepseek-v4.1-flash-1017:fast` | `deepseek/deepseek-v4.1-flash-1017` | ~~$0.56~~ $0.28 | ~~$0.056~~ $0.028 | ~~$2.2~~ $1.1 |\n| `deepseek/deepseek-v4.1-flash-0910:fast` | `deepseek/deepseek-v4.1-flash-0910` | ~~$0.56~~ $0.28 | ~~$0.056~~ $0.028 | ~~$2.2~~ $1.1 |\n\nFast mode has the same context window, output limit, image input, tools, structured outputs and\nreasoning controls as the standard model, and works on all three API formats (on the Anthropic\nendpoint, use the `:fast` id). It has its own rate limit budget, at the same limits.\n\n## Reasoning\n\nReasoning models think before they answer. The reasoning arrives in `reasoning_content` next\nto `content` and its tokens are billed as output, reported in\n`usage.completion_tokens_details.reasoning_tokens`. Reasoning is on by default. Control it with\nthe `reasoning` object or OpenAI's `reasoning_effort`:\n\n| Request field | Effect |\n| --- | --- |\n| `\"reasoning\": { \"enabled\": false }` or `\"reasoning_effort\": \"none\"` | No reasoning: faster and cheaper answers. |\n| `\"reasoning\": { \"effort\": \"low\" }` (or `medium`, `high`) | Reasoning on, at that effort. |\n| `\"reasoning\": { \"exclude\": true }` | The model still reasons, but `reasoning_content` is left out of the reply. |\n\nGLM 5.3 Flash always reasons: with reasoning turned off it still thinks briefly, the reasoning is\nleft out of the reply, and those tokens are billed as output. It has two effort levels, low and\nhigh; `medium` runs as high.\n\n## Streaming\n\nWith `stream: true` the reply arrives as Server-Sent Events, and the final chunk before\n`data: [DONE]` always carries `usage`, whether or not you set `stream_options`. While a long\nprompt is being read, the stream sends `: ping` comment lines to keep the connection open;\nSSE clients ignore them. If the request fails after the stream has started, it ends with one\n`data: {\"error\": {...}}` event in the error shape below.\n\n## Batch\n\nThe Batch API runs many chat completions without keeping a connection open, the same way\nOpenAI's Batch API does: upload a JSONL file, create a batch from it, and download the results\nwhen it finishes, within 24h.\n\nEach line of the file is one request:\n\n```json\n{\"custom_id\": \"req-1\", \"method\": \"POST\", \"url\": \"/v1/chat/completions\", \"body\": {\"model\": \"deepseek/deepseek-v4.1-flash\", \"messages\": [{\"role\": \"user\", \"content\": \"Hello from OpenScale\"}]}}\n```\n\nThe `body` is a normal chat completion request without `stream`, and every line uses the same\nmodel. Every line is checked when the batch is created, with the same checks as\n`POST /v1/chat/completions`: a file with any invalid line gives a `failed` batch whose `errors`\nlist the lines, and nothing runs.\n\n```bash\ncurl https://api.openscale.so/v1/files -H \"Authorization: Bearer $OPENSCALE_API_KEY\"   -F purpose=batch -F file=@requests.jsonl\ncurl https://api.openscale.so/v1/batches -H \"Authorization: Bearer $OPENSCALE_API_KEY\"   -H \"Content-Type: application/json\"   -d '{\"input_file_id\": \"file-...\", \"endpoint\": \"/v1/chat/completions\", \"completion_window\": \"24h\"}'\n```\n\nWhen the batch is `completed`, `output_file_id` holds the successful responses and\n`error_file_id` the failed, expired and cancelled requests, one JSON line each with its\n`custom_id`. Download them with `GET /files/{file_id}/content`.\n\n| Limit | Value |\n| --- | --- |\n| File size | 20 MB |\n| Requests per file | 10,000 |\n| Requests waiting across an account's batches | 50,000 |\n| `custom_id` length | 512 characters |\n| Completion window | 24h |\n| Files, batches and results kept | 30 days |\n\nBatches bill your balance, so they need a pay-as-you-go key: a plan key\ngets `400` with `code: batch_not_in_plan`. Files and batches belong to your account, so every\nkey on it can read them. With zero data retention on, new files and batches answer `400` with\n`code: zero_data_retention`.\n\n## Data retention\n\nChat Completions and Anthropic Messages requests are never stored: their request and response\nbodies pass through to the model and are gone once the reply is sent. The Responses API stores\nresponses the way OpenAI does, so that its stateful features work:\n\n- **What is stored:** for each response created with `store: true` (the default), its input items,\n  its output items, the settings the response echoes (such as `instructions`, `tools` and\n  `metadata`) and its token usage. A background response also keeps its stream events, so its\n  stream can be resumed. A conversation keeps the items you add to it and the input and output\n  of the responses created in it.\n- **How long:** a stored response is deleted 30 days after it was created. A conversation is kept\n  until you delete it.\n- **Deleting:** `DELETE /v1/responses/{id}`, `DELETE /v1/conversations/{id}` and\n  `DELETE /v1/conversations/{id}/items/{item_id}` delete at once. A request with `store: false`\n  stores nothing.\n- **Zero data retention:** turn it on in the dashboard under Settings (account owners and admins).\n  From then on nothing is stored for the account, and everything already stored is deleted.\n  `store` reads back as `false`, and `previous_response_id`, `conversation`, `background`,\n  `item_reference`, the Conversations API and the Batch API (which keeps its files for 30 days)\n  answer `400` with `code: zero_data_retention`.\n\nStored data is never used for training and never sold. Every model is served with no retention\nof request or response content where it runs. We also keep 30 days of request metadata (model,\ntoken counts, latency, status) for billing and support.\n\n## Rate limits\n\nLimits apply per account (shared by all its API keys) and per model (a model's pinned versions share its budget; fast mode counts as its own model). A request that would cross a budget is refused with\n`429` and a `Retry-After` header; retry after that many seconds.\n\n| Budget | Per minute |\n| --- | --- |\n| Requests | 100 |\n| Tokens (prompt, cached prompt and completion combined) | 10,000,000 |\n\nNeed more? Email [hello@openscale.so](mailto:hello@openscale.so) with your account email and\nexpected volume, and we will raise your limits.\n\n## Errors\n\nErrors use the OpenAI shape: `{ \"error\": { \"message\", \"type\", \"code\" } }`.\n\n| Status | Meaning |\n| --- | --- |\n| 400 | Invalid JSON or parameters. Codes: `invalid_messages`, `max_tokens_exceeded`, `invalid_reasoning_effort`, `context_length_exceeded` (the prompt plus `max_tokens` does not fit the context), `request_rejected` (any other parameter the model refused). |\n| 400 | A plan key called a model its plan does not include (`model_not_in_plan`). Use a pay-as-you-go key for that model. |\n| 401 | Missing or invalid API key. |\n| 402 | Your balance is empty (`insufficient_credits`), this API key reached the spend limit set on it in the dashboard (`key_spend_limit_reached`), or a plan key's renewal payment failed (`plan_payment_failed`: update your card). |\n| 403 | A plan key whose plan has ended (`plan_ended`): resubscribe, or use a pay-as-you-go key. |\n| 404 | Unknown model id. List valid ids with `GET /models`. |\n| 429 | A rate limit was crossed or the model is temporarily at capacity. Wait for `Retry-After`, then retry with backoff. |\n| 502, 503, 504 | The model is temporarily unavailable or did not respond in time. Retry with backoff and quote the `x-request-id` header when contacting support. |","contact":{"name":"OpenScale","email":"hello@openscale.so","url":"https://openscale.so"}},"servers":[{"url":"https://api.openscale.so/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Chat","description":"OpenAI-compatible chat completions, streamed or not."},{"name":"Responses","description":"The OpenAI Responses API, streamed or not: tools, reasoning and structured outputs."},{"name":"Conversations","description":"Stored conversations for the Responses API: create them, add and remove items, and use them with `conversation`."},{"name":"Prompts","description":"Reusable prompts for the Responses API: save versioned instructions, messages and settings, and use them with `prompt`."},{"name":"Anthropic Messages","description":"The Anthropic Messages API, for Claude Code and Anthropic SDKs. Base URL `https://api.openscale.so/anthropic`."},{"name":"Batch","description":"Run many chat completions from one JSONL file and collect the results within 24h."},{"name":"Models","description":"The public model catalog."}],"paths":{"/responses/input_tokens":{"post":{"tags":["Responses"],"summary":"Count input tokens","operationId":"countResponseInputTokens","description":"Count the input tokens a Responses request would use, without running the model. Takes the same body as Create a response and counts it with the model tokenizer: exact for text and tools, estimated for images and for models whose tokenizer we do not carry. Free.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["input"]},"example":{"model":"deepseek/deepseek-v4.1-flash","input":"Hello from OpenScale"}}}},"responses":{"200":{"description":"The input token count.","content":{"application/json":{"schema":{"type":"object","required":["object","input_tokens"],"properties":{"object":{"type":"string","enum":["response.input_tokens"]},"input_tokens":{"type":"integer"}}}}}},"400":{"description":"The request cannot be served; `param` names the field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/responses":{"post":{"tags":["Responses"],"summary":"Create a response","operationId":"createResponse","description":"Create a response from a string or an array of input items (messages, tool call and tool output items, and `reasoning` items from an earlier turn). Function, custom, namespace, shell, local shell, apply patch and client tool search tools are supported, and `strict`, `tool_choice` (including `allowed_tools`) and `parallel_tool_calls: false` are enforced. Reasoning comes back as a `reasoning` item with `encrypted_content` you can send back unchanged, readable `reasoning_text` content, and a summary when `reasoning.summary` is set. Responses are stored for 30 days by default (`store`), so a later request can continue from one with `previous_response_id`, or keep its turns in a `conversation`; with `background: true` the response runs on its own and is retrieved later. See the Responses API compatibility table and Data retention in the introduction.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["model","input"],"properties":{"model":{"type":"string","enum":["deepseek/deepseek-v4.1-flash","z-ai/glm-5.3-flash","deepseek/deepseek-v4.1-flash-1017","deepseek/deepseek-v4.1-flash-0910","z-ai/glm-5.3-flash-0828","deepseek/deepseek-v4.1-flash:fast","deepseek/deepseek-v4.1-flash-1017:fast","deepseek/deepseek-v4.1-flash-0910:fast"]},"input":{"oneOf":[{"type":"string"},{"type":"array","description":"Messages plus `function_call`, `function_call_output`, `custom_tool_call`, `custom_tool_call_output` and `reasoning` items.","items":{"type":"object","properties":{"role":{"type":"string"},"content":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["input_text","input_image"]},"text":{"type":"string"},"image_url":{"type":"string"}}}}]}}}}]},"instructions":{"type":"string"},"tools":{"type":"array","description":"`function` (with `strict`), `custom`, `namespace`, `shell`, `local_shell`, `apply_patch` and client `tool_search` tools. Web search is left out (see `x-openscale-ignored-tools`); other hosted tools are refused.","items":{"type":"object"}},"tool_choice":{"description":"`auto`, `none`, `required`, a named tool, or `allowed_tools`. Enforced: a reply that breaks it is retried and never returned."},"parallel_tool_calls":{"type":"boolean"},"text":{"type":"object","description":"Structured outputs: `{ \"format\": { \"type\": \"json_schema\", ... } }` or `json_object`. `json_object` works whether or not your prompt mentions JSON."},"max_output_tokens":{"type":"integer"},"temperature":{"type":"number","minimum":0,"maximum":2},"top_p":{"type":"number","minimum":0,"maximum":1},"stream":{"type":"boolean","default":false},"metadata":{"type":"object"},"store":{"type":"boolean","default":true,"description":"Store the response for 30 days, for `previous_response_id`, retrieval and `input_items`. `false` stores nothing. Always `false` when the account has zero data retention on."},"previous_response_id":{"type":"string","description":"Continue from a stored response: its input and output (and those of the responses before it) come before `input`. Its `instructions` do not carry over."},"conversation":{"description":"A conversation id (or `{ \"id\": ... }`): its items come before `input`, and the input and output are added to it when the response finishes.","oneOf":[{"type":"string"},{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}]},"background":{"type":"boolean","default":false,"description":"Run the response on its own: answered at once with a `queued` response; retrieve it, stream it, or cancel it by id."},"user":{"type":"string"},"reasoning":{"type":"object","description":"Reasoning control: `effort` (`none` to `xhigh`) and `summary` (`auto`, `concise` or `detailed` returns a readable summary)."}}},"example":{"model":"deepseek/deepseek-v4.1-flash","input":"Hello from OpenScale","store":false}}}},"responses":{"200":{"description":"The response, or a typed SSE stream when `stream` is true.","headers":{"x-request-id":{"description":"Gateway request id. Quote it when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Response"},"example":{"id":"resp_example","object":"response","created_at":1790078324,"status":"completed","model":"deepseek/deepseek-v4.1-flash","output":[{"type":"message","id":"msg_example","role":"assistant","status":"completed","content":[{"type":"output_text","text":"Hello!","annotations":[]}],"phase":"final_answer"}],"usage":{"input_tokens":5,"input_tokens_details":{"cached_tokens":0},"output_tokens":2,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":7}}},"text/event-stream":{"description":"Typed events: response.created, response.in_progress, response.output_item.added and .done, response.content_part.added and .done, response.output_text.delta and .done, response.reasoning_summary_part and response.reasoning_summary_text events, response.function_call_arguments.delta and .done, response.custom_tool_call_input.done, and response.completed, response.incomplete or response.failed.","schema":{"type":"string"}}}},"400":{"description":"Invalid request; `param` names the field. `previous_response_not_found` when the previous response is unknown, deleted or past its 30 days.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Empty balance, or the key reached its spend limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown model id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit crossed or model at capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The model is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"504":{"description":"The model did not respond in time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/responses/{response_id}":{"parameters":[{"name":"response_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Responses"],"summary":"Retrieve a response","operationId":"getResponse","description":"A stored response, as it was returned (status `queued` or `in_progress` while a background response runs). With `stream=true` (background responses only), its stream events from the start, or after `starting_after`, then each new one as it happens.","parameters":[{"name":"stream","in":"query","schema":{"type":"boolean"},"description":"Stream a background response as SSE events."},{"name":"starting_after","in":"query","schema":{"type":"integer"},"description":"With `stream`: the sequence number to resume after."}],"responses":{"200":{"description":"The response, or its events when `stream` is true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Response"}},"text/event-stream":{"schema":{"type":"string"}}}},"404":{"description":"No stored response with this id in your account (never stored, deleted or past its 30 days).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Responses"],"summary":"Delete a response","operationId":"deleteResponse","description":"Delete a stored response, its input and its output at once. A running background response is cancelled.","responses":{"200":{"description":"Deleted.","content":{"application/json":{"example":{"id":"resp_example","object":"response.deleted","deleted":true}}}},"404":{"description":"No stored response with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/responses/{response_id}/cancel":{"parameters":[{"name":"response_id","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["Responses"],"summary":"Cancel a background response","operationId":"cancelResponse","description":"Stop a queued or running background response; it ends with status `cancelled` and is not billed for unfinished work. Cancelling again, or cancelling a finished response, returns it unchanged.","responses":{"200":{"description":"The response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Response"}}}},"400":{"description":"The response was not created in the background.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No stored response with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/responses/{response_id}/input_items":{"parameters":[{"name":"response_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Responses"],"summary":"List input items","operationId":"listInputItems","description":"The input items of a stored response, each with its id. Paged with `limit` (1 to 100, default 20), `order` (`desc` by default) and `after` (an item id).","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"after","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A list of items.","content":{"application/json":{"schema":{"type":"object","required":["object","data","first_id","last_id","has_more"],"properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object"}},"first_id":{"type":["string","null"]},"last_id":{"type":["string","null"]},"has_more":{"type":"boolean"}}}}}},"404":{"description":"No stored response (or `after` item) with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/responses/compact":{"post":{"tags":["Responses"],"summary":"Compact a conversation","operationId":"compactConversation","description":"Summarize a conversation so it can continue in fewer tokens. Takes `model` and the conversation as `input` (and/or `previous_response_id`, plus `instructions`). The output keeps your user messages and ends with a `compaction` item that stands for everything else; send the output, followed by new items, as the next input. Nothing is stored. Billed like a response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["model"],"properties":{"model":{"type":"string"},"input":{},"previous_response_id":{"type":"string"},"instructions":{"type":"string"}}},"example":{"model":"deepseek/deepseek-v4.1-flash","input":[{"role":"user","content":"My locker number is 7731."},{"type":"message","role":"assistant","content":[{"type":"output_text","text":"Noted."}]}]}}}},"responses":{"200":{"description":"The compacted conversation.","content":{"application/json":{"schema":{"type":"object","required":["id","object","created_at","output","usage"],"properties":{"id":{"type":"string"},"object":{"type":"string","enum":["response.compaction"]},"created_at":{"type":"integer"},"output":{"type":"array","items":{"type":"object"}},"usage":{"type":"object"}}}}}},"400":{"description":"The request cannot be served; `param` names the field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/prompts":{"post":{"tags":["Prompts"],"summary":"Create a prompt","operationId":"createPrompt","description":"Save a reusable prompt as version `1`. It needs `instructions` or `input` messages; `{{name}}` placeholders in them become the prompt's `variables`. Settings (`model`, `tools`, `tool_choice`, `text`, `reasoning`, `temperature`, `top_p`, `max_output_tokens`, `parallel_tool_calls`, `truncation`) apply when a request leaves them out.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":256},"instructions":{"type":"string"},"input":{"description":"A string (one user message) or a list of messages."},"model":{"type":"string"},"tools":{"type":"array","items":{"type":"object"}},"tool_choice":{},"text":{"type":"object"},"reasoning":{"type":"object"},"temperature":{"type":"number"},"top_p":{"type":"number"},"max_output_tokens":{"type":"integer"},"parallel_tool_calls":{"type":"boolean"},"truncation":{"type":"string","enum":["auto","disabled"]}}},"example":{"name":"Support","instructions":"You are a support agent for {{company}}. Answer in one paragraph.","model":"deepseek/deepseek-v4.1-flash"}}}},"responses":{"200":{"description":"The prompt.","content":{"application/json":{"schema":{"type":"object","required":["id","object","version","latest_version","variables"],"properties":{"id":{"type":"string","examples":["pmpt_9f2c..."]},"object":{"type":"string","enum":["prompt"]},"name":{"type":["string","null"]},"version":{"type":"string","examples":["2"]},"latest_version":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"created_at":{"type":"integer"},"version_created_at":{"type":"integer"}}}}}},"400":{"description":"Invalid prompt; `param` names the field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Prompts"],"summary":"List prompts","operationId":"listPrompts","description":"Your account's prompts at their latest versions, newest first. Paged with `limit`, `order` and `after` (a prompt id).","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"after","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A list of prompts.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","required":["id","object","version","latest_version","variables"],"properties":{"id":{"type":"string","examples":["pmpt_9f2c..."]},"object":{"type":"string","enum":["prompt"]},"name":{"type":["string","null"]},"version":{"type":"string","examples":["2"]},"latest_version":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"created_at":{"type":"integer"},"version_created_at":{"type":"integer"}}}},"first_id":{"type":["string","null"]},"last_id":{"type":["string","null"]},"has_more":{"type":"boolean"}}}}}}}}},"/prompts/{prompt_id}":{"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Prompts"],"summary":"Retrieve a prompt","operationId":"getPrompt","description":"The latest version of a prompt, or the one in `?version=`.","parameters":[{"name":"version","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"The prompt.","content":{"application/json":{"schema":{"type":"object","required":["id","object","version","latest_version","variables"],"properties":{"id":{"type":"string","examples":["pmpt_9f2c..."]},"object":{"type":"string","enum":["prompt"]},"name":{"type":["string","null"]},"version":{"type":"string","examples":["2"]},"latest_version":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"created_at":{"type":"integer"},"version_created_at":{"type":"integer"}}}}}},"404":{"description":"No prompt (or version) with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Prompts"],"summary":"Save a new version","operationId":"updatePrompt","description":"Save the body (as in Create a prompt) as the next version; earlier versions stay as they were. `name` renames the prompt.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":256},"instructions":{"type":"string"},"input":{"description":"A string (one user message) or a list of messages."},"model":{"type":"string"},"tools":{"type":"array","items":{"type":"object"}},"tool_choice":{},"text":{"type":"object"},"reasoning":{"type":"object"},"temperature":{"type":"number"},"top_p":{"type":"number"},"max_output_tokens":{"type":"integer"},"parallel_tool_calls":{"type":"boolean"},"truncation":{"type":"string","enum":["auto","disabled"]}}}}}},"responses":{"200":{"description":"The new version.","content":{"application/json":{"schema":{"type":"object","required":["id","object","version","latest_version","variables"],"properties":{"id":{"type":"string","examples":["pmpt_9f2c..."]},"object":{"type":"string","enum":["prompt"]},"name":{"type":["string","null"]},"version":{"type":"string","examples":["2"]},"latest_version":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"created_at":{"type":"integer"},"version_created_at":{"type":"integer"}}}}}},"404":{"description":"No prompt with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Prompts"],"summary":"Delete a prompt","operationId":"deletePrompt","description":"Delete a prompt and all its versions.","responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["prompt.deleted"]},"deleted":{"type":"boolean"}}}}}},"404":{"description":"No prompt with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/prompts/{prompt_id}/versions":{"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Prompts"],"summary":"List prompt versions","operationId":"listPromptVersions","description":"Every version of a prompt, newest first. Paged with `limit`, `order` and `after` (a version number).","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"after","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A list of versions.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","required":["id","object","version","latest_version","variables"],"properties":{"id":{"type":"string","examples":["pmpt_9f2c..."]},"object":{"type":"string","enum":["prompt"]},"name":{"type":["string","null"]},"version":{"type":"string","examples":["2"]},"latest_version":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"created_at":{"type":"integer"},"version_created_at":{"type":"integer"}}}},"first_id":{"type":["string","null"]},"last_id":{"type":["string","null"]},"has_more":{"type":"boolean"}}}}}},"404":{"description":"No prompt with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/conversations":{"post":{"tags":["Conversations"],"summary":"Create a conversation","operationId":"createConversation","description":"A stored conversation, with up to 20 initial `items` and `metadata` (up to 16 string pairs). Use its id as `conversation` in Create a response. Conversations are kept until you delete them.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","maxItems":20,"items":{"type":"object"}},"metadata":{"type":"object"}}},"example":{"metadata":{"topic":"support"},"items":[{"type":"message","role":"user","content":"Hello!"}]}}}},"responses":{"200":{"description":"The conversation.","content":{"application/json":{"schema":{"type":"object","required":["id","object","created_at","metadata"],"properties":{"id":{"type":"string","examples":["conv_example"]},"object":{"type":"string","enum":["conversation"]},"created_at":{"type":"integer"},"metadata":{"type":"object"}}}}}},"400":{"description":"Invalid items or metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/conversations/{conversation_id}":{"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Conversations"],"summary":"Retrieve a conversation","operationId":"getConversation","responses":{"200":{"description":"The conversation.","content":{"application/json":{"schema":{"type":"object","required":["id","object","created_at","metadata"],"properties":{"id":{"type":"string","examples":["conv_example"]},"object":{"type":"string","enum":["conversation"]},"created_at":{"type":"integer"},"metadata":{"type":"object"}}}}}},"404":{"description":"No conversation with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Conversations"],"summary":"Update a conversation","operationId":"updateConversation","description":"Replace the conversation metadata.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["metadata"],"properties":{"metadata":{"type":"object"}}}}}},"responses":{"200":{"description":"The conversation.","content":{"application/json":{"schema":{"type":"object","required":["id","object","created_at","metadata"],"properties":{"id":{"type":"string","examples":["conv_example"]},"object":{"type":"string","enum":["conversation"]},"created_at":{"type":"integer"},"metadata":{"type":"object"}}}}}},"404":{"description":"No conversation with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Conversations"],"summary":"Delete a conversation","operationId":"deleteConversation","description":"Delete the conversation and all of its items at once.","responses":{"200":{"description":"Deleted.","content":{"application/json":{"example":{"id":"conv_example","object":"conversation.deleted","deleted":true}}}},"404":{"description":"No conversation with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/conversations/{conversation_id}/items":{"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Conversations"],"summary":"List items","operationId":"listConversationItems","description":"Paged with `limit` (1 to 100, default 20), `order` (`desc` by default) and `after` (an item id).","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"after","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A list of items.","content":{"application/json":{"schema":{"type":"object","required":["object","data","first_id","last_id","has_more"],"properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object"}},"first_id":{"type":["string","null"]},"last_id":{"type":["string","null"]},"has_more":{"type":"boolean"}}}}}},"404":{"description":"No conversation (or `after` item) with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Conversations"],"summary":"Add items","operationId":"createConversationItems","description":"Add up to 20 items to the end of the conversation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","maxItems":20,"items":{"type":"object"}}}}}}},"responses":{"200":{"description":"The added items.","content":{"application/json":{"schema":{"type":"object","required":["object","data","first_id","last_id","has_more"],"properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object"}},"first_id":{"type":["string","null"]},"last_id":{"type":["string","null"]},"has_more":{"type":"boolean"}}}}}},"400":{"description":"Invalid items, or an item already in the conversation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No conversation with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/conversations/{conversation_id}/items/{item_id}":{"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"item_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Conversations"],"summary":"Retrieve an item","operationId":"getConversationItem","responses":{"200":{"description":"The item.","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No such conversation or item.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Conversations"],"summary":"Delete an item","operationId":"deleteConversationItem","description":"Delete one item; answers with the conversation.","responses":{"200":{"description":"The conversation.","content":{"application/json":{"schema":{"type":"object","required":["id","object","created_at","metadata"],"properties":{"id":{"type":"string","examples":["conv_example"]},"object":{"type":"string","enum":["conversation"]},"created_at":{"type":"integer"},"metadata":{"type":"object"}}}}}},"404":{"description":"No such conversation or item.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/messages":{"servers":[{"url":"https://api.openscale.so/anthropic/v1","description":"Production"}],"post":{"tags":["Anthropic Messages"],"summary":"Create a message","operationId":"createMessage","security":[{"apiKeyHeader":[]},{"bearerAuth":[]}],"description":"The Anthropic Messages API: system prompts, multi-turn messages with text, image, `tool_use` and `tool_result` blocks, client tools and `tool_choice`, extended thinking, `stop_sequences` and streaming with the standard event sequence. Any `claude-*` model name runs DeepSeek V4.1 Flash, and the reply echoes the name you sent. Thinking (`thinking.type` `enabled` or `adaptive`, or `output_config.effort`) turns reasoning on; it comes back as `thinking` blocks. Anthropic server tools are ignored. Usage reports `cache_read_input_tokens` for prompt tokens billed at the cached rate. Errors use the Anthropic shape.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["model","max_tokens","messages"],"properties":{"model":{"type":"string","description":"A model id from `GET /v1/models`, or any `claude-*` name."},"max_tokens":{"type":"integer"},"system":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"object"}}]},"messages":{"type":"array","items":{"type":"object"}},"tools":{"type":"array","items":{"type":"object"}},"tool_choice":{"type":"object"},"thinking":{"type":"object"},"temperature":{"type":"number"},"stop_sequences":{"type":"array","items":{"type":"string"}},"stream":{"type":"boolean","default":false}}},"example":{"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"Hello from OpenScale"}]}}}},"responses":{"200":{"description":"The message, or an SSE stream when `stream` is true: message_start, content_block_start, content_block_delta, content_block_stop, message_delta and message_stop.","headers":{"x-request-id":{"description":"Gateway request id. Quote it when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"id":"msg_example","type":"message","role":"assistant","model":"claude-sonnet-4-5","content":[{"type":"text","text":"Hello!"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":9,"cache_read_input_tokens":0,"output_tokens":3}}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Invalid request. A prompt that does not fit says `prompt is too long`."},"401":{"description":"Missing or invalid API key."},"402":{"description":"Empty balance, or the key reached its spend limit."},"429":{"description":"Rate limit crossed or model at capacity."},"529":{"description":"The model is temporarily overloaded."}}}},"/chat/completions":{"post":{"tags":["Chat"],"summary":"Create a chat completion","operationId":"createChatCompletion","description":"Send a conversation and receive the next assistant message. Set `stream: true` for Server-Sent Events. Models that reason return their reasoning in `reasoning_content` alongside `content`; when replaying a tool-calling conversation, send `reasoning_content` back on the assistant messages.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"},"examples":{"basic":{"summary":"Simple request","value":{"model":"deepseek/deepseek-v4.1-flash","messages":[{"role":"user","content":"Hello from OpenScale"}]}},"noReasoning":{"summary":"Streamed, reasoning off","value":{"model":"deepseek/deepseek-v4.1-flash","stream":true,"reasoning":{"enabled":false},"messages":[{"role":"user","content":"Hello from OpenScale"}]}}}}}},"responses":{"200":{"description":"The completion, or an SSE stream when `stream` is true.","headers":{"x-request-id":{"description":"Gateway request id. Quote it when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletion"},"example":{"id":"chatcmpl-ucOlCLBJhTr5ahpQzgJaeiK8","object":"chat.completion","created":1790078324,"model":"deepseek/deepseek-v4.1-flash","choices":[{"index":0,"message":{"role":"assistant","content":"Hello! How can I help you today?","reasoning_content":"The user is greeting me."},"finish_reason":"stop"}],"usage":{"prompt_tokens":17,"completion_tokens":42,"total_tokens":59,"prompt_tokens_details":{"cached_tokens":0},"completion_tokens_details":{"reasoning_tokens":31}}}},"text/event-stream":{"schema":{"$ref":"#/components/schemas/ChatCompletionChunk"},"example":"data: {\"id\":\"chatcmpl-y3nR30I9R87biSC5oz4gHeF5\",\"object\":\"chat.completion.chunk\",\"model\":\"deepseek/deepseek-v4.1-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"Hel\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"chatcmpl-y3nR30I9R87biSC5oz4gHeF5\",\"object\":\"chat.completion.chunk\",\"model\":\"deepseek/deepseek-v4.1-flash\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"lo\"},\"finish_reason\":\"stop\"}]}\n\ndata: {\"id\":\"chatcmpl-y3nR30I9R87biSC5oz4gHeF5\",\"object\":\"chat.completion.chunk\",\"model\":\"deepseek/deepseek-v4.1-flash\",\"choices\":[],\"usage\":{\"prompt_tokens\":17,\"completion_tokens\":2,\"total_tokens\":19}}\n\ndata: [DONE]"}}},"400":{"description":"Invalid request: `invalid_messages`, `max_tokens_exceeded`, `invalid_reasoning_effort`, `context_length_exceeded` or `request_rejected`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Empty balance, or the key reached its spend limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown model id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit crossed or model at capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}},"502":{"description":"The model is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"504":{"description":"The model did not respond in time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/files":{"post":{"tags":["Batch"],"summary":"Upload a file","operationId":"uploadFile","description":"Upload a JSONL batch input file as `multipart/form-data` with the fields `file` and `purpose` (`batch`). Up to 20 MB and 10,000 requests.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","purpose"],"properties":{"file":{"type":"string","format":"binary","description":"The JSONL file, one request per line."},"purpose":{"type":"string","enum":["batch"]}}}}}},"responses":{"200":{"description":"The file.","content":{"application/json":{"schema":{"type":"object","required":["id","object","bytes","created_at","filename","purpose"],"properties":{"id":{"type":"string","examples":["file-example"]},"object":{"type":"string","enum":["file"]},"bytes":{"type":"integer"},"created_at":{"type":"integer"},"expires_at":{"type":"integer","description":"Unix seconds when the file is deleted, 30 days after upload."},"filename":{"type":"string"},"purpose":{"type":"string","enum":["batch","batch_output"],"description":"`batch` for uploads, `batch_output` for results."},"status":{"type":"string","enum":["processed"]}}},"example":{"id":"file-example","object":"file","bytes":1204,"created_at":1790078324,"expires_at":1792670324,"filename":"requests.jsonl","purpose":"batch","status":"processed"}}}},"400":{"description":"Invalid upload; `param` names the field. `zero_data_retention` when the account has zero data retention on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The file is larger than the limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Batch"],"summary":"List files","operationId":"listFiles","description":"Your account's files, newest first. Filter with `purpose` (`batch` or `batch_output`).","parameters":[{"name":"purpose","in":"query","schema":{"type":"string","enum":["batch","batch_output"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"after","in":"query","description":"The id of the last object on the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"A list of files.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","required":["id","object","bytes","created_at","filename","purpose"],"properties":{"id":{"type":"string","examples":["file-example"]},"object":{"type":"string","enum":["file"]},"bytes":{"type":"integer"},"created_at":{"type":"integer"},"expires_at":{"type":"integer","description":"Unix seconds when the file is deleted, 30 days after upload."},"filename":{"type":"string"},"purpose":{"type":"string","enum":["batch","batch_output"],"description":"`batch` for uploads, `batch_output` for results."},"status":{"type":"string","enum":["processed"]}}}},"first_id":{"type":["string","null"]},"last_id":{"type":["string","null"]},"has_more":{"type":"boolean"}}}}}}}}},"/files/{file_id}":{"parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Batch"],"summary":"Retrieve a file","operationId":"getFile","description":"A file's metadata.","responses":{"200":{"description":"The file.","content":{"application/json":{"schema":{"type":"object","required":["id","object","bytes","created_at","filename","purpose"],"properties":{"id":{"type":"string","examples":["file-example"]},"object":{"type":"string","enum":["file"]},"bytes":{"type":"integer"},"created_at":{"type":"integer"},"expires_at":{"type":"integer","description":"Unix seconds when the file is deleted, 30 days after upload."},"filename":{"type":"string"},"purpose":{"type":"string","enum":["batch","batch_output"],"description":"`batch` for uploads, `batch_output` for results."},"status":{"type":"string","enum":["processed"]}}}}}},"404":{"description":"No file with this id in your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Batch"],"summary":"Delete a file","operationId":"deleteFile","description":"Delete a file at once.","responses":{"200":{"description":"Deleted.","content":{"application/json":{"example":{"id":"file-example","object":"file","deleted":true}}}},"404":{"description":"No file with this id in your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/files/{file_id}/content":{"parameters":[{"name":"file_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Batch"],"summary":"Download file content","operationId":"getFileContent","description":"The file as uploaded, or a batch's results: one JSON line per request with its `custom_id` and either a `response` (`status_code` and `body`) or an `error`.","responses":{"200":{"description":"The file content.","content":{"application/octet-stream":{"schema":{"type":"string"}}}},"404":{"description":"No file with this id in your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batches":{"post":{"tags":["Batch"],"summary":"Create a batch","operationId":"createBatch","description":"Start a batch from an uploaded file. Every line is checked first: a file with an invalid line gives a `failed` batch that lists the errors, and nothing runs. Needs a pay-as-you-go key.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["input_file_id","endpoint","completion_window"],"properties":{"input_file_id":{"type":"string","description":"A file uploaded with `purpose: batch`."},"endpoint":{"type":"string","enum":["/v1/chat/completions"]},"completion_window":{"type":"string","enum":["24h"]},"metadata":{"type":"object","description":"Up to 16 string pairs (keys up to 64 characters, values up to 512)."}}},"example":{"input_file_id":"file-example","endpoint":"/v1/chat/completions","completion_window":"24h"}}}},"responses":{"200":{"description":"The batch.","content":{"application/json":{"schema":{"type":"object","required":["id","object","endpoint","input_file_id","status"],"properties":{"id":{"type":"string","examples":["batch_example"]},"object":{"type":"string","enum":["batch"]},"endpoint":{"type":"string","enum":["/v1/chat/completions"]},"model":{"type":["string","null"]},"errors":{"description":"For a `failed` batch: the invalid lines of the input file, each with its line number, code and message.","type":["object","null"]},"input_file_id":{"type":"string"},"completion_window":{"type":"string","enum":["24h"]},"status":{"type":"string","enum":["failed","in_progress","completed","expired","cancelling","cancelled"]},"output_file_id":{"type":["string","null"],"description":"Results of the requests that succeeded."},"error_file_id":{"type":["string","null"],"description":"Failed, expired and cancelled requests."},"created_at":{"type":"integer"},"expires_at":{"type":["integer","null"]},"completed_at":{"type":["integer","null"]},"request_counts":{"type":"object","properties":{"total":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"}}},"metadata":{"type":["object","null"]}}},"example":{"id":"batch_example","object":"batch","endpoint":"/v1/chat/completions","model":"deepseek/deepseek-v4.1-flash","errors":null,"input_file_id":"file-example","completion_window":"24h","status":"in_progress","output_file_id":null,"error_file_id":null,"created_at":1790078324,"expires_at":1790164724,"completed_at":null,"request_counts":{"total":2,"completed":0,"failed":0},"metadata":null}}}},"400":{"description":"Invalid request; `param` names the field. `batch_not_in_plan` for a plan key, `zero_data_retention` when the account has zero data retention on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Batch"],"summary":"List batches","operationId":"listBatches","description":"Your account's batches, newest first.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"after","in":"query","description":"The id of the last object on the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"A list of batches.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","required":["id","object","endpoint","input_file_id","status"],"properties":{"id":{"type":"string","examples":["batch_example"]},"object":{"type":"string","enum":["batch"]},"endpoint":{"type":"string","enum":["/v1/chat/completions"]},"model":{"type":["string","null"]},"errors":{"description":"For a `failed` batch: the invalid lines of the input file, each with its line number, code and message.","type":["object","null"]},"input_file_id":{"type":"string"},"completion_window":{"type":"string","enum":["24h"]},"status":{"type":"string","enum":["failed","in_progress","completed","expired","cancelling","cancelled"]},"output_file_id":{"type":["string","null"],"description":"Results of the requests that succeeded."},"error_file_id":{"type":["string","null"],"description":"Failed, expired and cancelled requests."},"created_at":{"type":"integer"},"expires_at":{"type":["integer","null"]},"completed_at":{"type":["integer","null"]},"request_counts":{"type":"object","properties":{"total":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"}}},"metadata":{"type":["object","null"]}}}},"first_id":{"type":["string","null"]},"last_id":{"type":["string","null"]},"has_more":{"type":"boolean"}}}}}}}}},"/batches/{batch_id}":{"parameters":[{"name":"batch_id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Batch"],"summary":"Retrieve a batch","operationId":"getBatch","description":"A batch, with live request counts while it runs.","responses":{"200":{"description":"The batch.","content":{"application/json":{"schema":{"type":"object","required":["id","object","endpoint","input_file_id","status"],"properties":{"id":{"type":"string","examples":["batch_example"]},"object":{"type":"string","enum":["batch"]},"endpoint":{"type":"string","enum":["/v1/chat/completions"]},"model":{"type":["string","null"]},"errors":{"description":"For a `failed` batch: the invalid lines of the input file, each with its line number, code and message.","type":["object","null"]},"input_file_id":{"type":"string"},"completion_window":{"type":"string","enum":["24h"]},"status":{"type":"string","enum":["failed","in_progress","completed","expired","cancelling","cancelled"]},"output_file_id":{"type":["string","null"],"description":"Results of the requests that succeeded."},"error_file_id":{"type":["string","null"],"description":"Failed, expired and cancelled requests."},"created_at":{"type":"integer"},"expires_at":{"type":["integer","null"]},"completed_at":{"type":["integer","null"]},"request_counts":{"type":"object","properties":{"total":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"}}},"metadata":{"type":["object","null"]}}}}}},"404":{"description":"No batch with this id in your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batches/{batch_id}/cancel":{"parameters":[{"name":"batch_id","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["Batch"],"summary":"Cancel a batch","operationId":"cancelBatch","description":"Cancel the requests that have not started. The batch moves to `cancelling`, then `cancelled`; finished requests keep their results.","responses":{"200":{"description":"The batch.","content":{"application/json":{"schema":{"type":"object","required":["id","object","endpoint","input_file_id","status"],"properties":{"id":{"type":"string","examples":["batch_example"]},"object":{"type":"string","enum":["batch"]},"endpoint":{"type":"string","enum":["/v1/chat/completions"]},"model":{"type":["string","null"]},"errors":{"description":"For a `failed` batch: the invalid lines of the input file, each with its line number, code and message.","type":["object","null"]},"input_file_id":{"type":"string"},"completion_window":{"type":"string","enum":["24h"]},"status":{"type":"string","enum":["failed","in_progress","completed","expired","cancelling","cancelled"]},"output_file_id":{"type":["string","null"],"description":"Results of the requests that succeeded."},"error_file_id":{"type":["string","null"],"description":"Failed, expired and cancelled requests."},"created_at":{"type":"integer"},"expires_at":{"type":["integer","null"]},"completed_at":{"type":["integer","null"]},"request_counts":{"type":"object","properties":{"total":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"}}},"metadata":{"type":["object","null"]}}}}}},"404":{"description":"No batch with this id in your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The batch has already finished (`batch_not_cancellable`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/models":{"get":{"tags":["Models"],"summary":"List models","operationId":"listModels","security":[],"description":"The live catalog. Public, no key required. Each entry carries pricing, context and output limits, supported parameters, per-account capacity and serving location.","responses":{"200":{"description":"The catalog.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Model"}}}}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your OpenScale API key: `sk-openscale-...` (pay as you go) or `sk-openscale-plan-...` (plan key)."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"Your OpenScale API key, as Anthropic SDKs send it. A Bearer token works too."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message","type"],"properties":{"message":{"type":"string"},"type":{"type":"string","examples":["invalid_request_error","rate_limit_error","api_error"]},"code":{"type":["string","null"],"examples":["model_not_found","context_length_exceeded","max_tokens_exceeded","rate_limit_exceeded","insufficient_credits","key_spend_limit_reached","model_not_in_plan","plan_payment_failed","plan_ended"]}}}}},"Message":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["system","user","assistant","tool"]},"content":{"description":"Text, or an array of content parts for multimodal input.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text","image_url"]},"text":{"type":"string"},"image_url":{"type":"object","properties":{"url":{"type":"string"}}}}}}]},"name":{"type":"string"},"tool_call_id":{"type":"string"},"tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolCall"}},"reasoning_content":{"type":"string","description":"The model's reasoning from a previous turn. Send it back on assistant messages when replaying a tool-calling conversation."}}},"ToolCall":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["function"]},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string","description":"JSON-encoded arguments."}}}}},"Usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"total_tokens":{"type":"integer"},"prompt_tokens_details":{"type":"object","properties":{"cached_tokens":{"type":"integer","description":"Prompt tokens billed at the cached rate."}}},"completion_tokens_details":{"type":"object","properties":{"reasoning_tokens":{"type":"integer","description":"Reasoning tokens, billed as completion tokens."}}}}},"ChatCompletionRequest":{"type":"object","required":["model","messages"],"properties":{"model":{"type":"string","enum":["deepseek/deepseek-v4.1-flash","z-ai/glm-5.3-flash","deepseek/deepseek-v4.1-flash-1017","deepseek/deepseek-v4.1-flash-0910","z-ai/glm-5.3-flash-0828","deepseek/deepseek-v4.1-flash:fast","deepseek/deepseek-v4.1-flash-1017:fast","deepseek/deepseek-v4.1-flash-0910:fast"],"description":"A chat model id from `GET /models`."},"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"stream":{"type":"boolean","default":false,"description":"Stream the completion as Server-Sent Events. The final chunk before `[DONE]` carries `usage`."},"stream_options":{"type":"object","properties":{"include_usage":{"type":"boolean"}}},"max_tokens":{"type":"integer","minimum":1,"description":"Maximum completion tokens, including reasoning tokens. Reasoning models spend part of this budget thinking, so allow room for it. Above the model's output limit the request is refused with `max_tokens_exceeded`."},"max_completion_tokens":{"type":"integer","minimum":1,"description":"Same as `max_tokens` (the newer OpenAI name)."},"temperature":{"type":"number","minimum":0,"maximum":2},"top_p":{"type":"number","minimum":0,"maximum":1},"stop":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"tools":{"type":"array","description":"OpenAI-style function tools.","items":{"type":"object","properties":{"type":{"type":"string","enum":["function"]},"function":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":{"type":"object"}}}}}},"tool_choice":{"oneOf":[{"type":"string","enum":["none","auto","required"]},{"type":"object"}]},"response_format":{"type":"object","description":"Structured outputs: `json_object` or `json_schema`. `json_object` works whether or not your prompt mentions JSON.","properties":{"type":{"type":"string","enum":["text","json_object","json_schema"]},"json_schema":{"type":"object"}}},"reasoning":{"type":"object","description":"Reasoning control. `enabled: false` turns reasoning off; `effort` sets how much the model thinks; `exclude: true` keeps reasoning out of the reply.","properties":{"enabled":{"type":"boolean"},"effort":{"type":"string","enum":["none","minimal","low","medium","high","xhigh"]},"exclude":{"type":"boolean"}}},"reasoning_effort":{"type":"string","enum":["none","minimal","low","medium","high","xhigh"],"description":"How much the model reasons before answering (OpenAI style); `none` turns reasoning off."},"logprobs":{"type":"boolean"},"top_logprobs":{"type":"integer","minimum":0,"maximum":20},"frequency_penalty":{"type":"number","minimum":-2,"maximum":2},"presence_penalty":{"type":"number","minimum":-2,"maximum":2},"user":{"type":"string"},"service_tier":{"type":"string","examples":["priority"],"description":"`priority` runs the request in fast mode (same model, faster serving, higher price) when it is available; any other value runs at the standard tier. The response reports the tier that served it."}}},"ChatCompletion":{"type":"object","properties":{"id":{"type":"string","examples":["chatcmpl-ucOlCLBJhTr5ahpQzgJaeiK8"]},"object":{"type":"string","enum":["chat.completion"]},"created":{"type":"integer"},"model":{"type":"string","enum":["deepseek/deepseek-v4.1-flash","z-ai/glm-5.3-flash","deepseek/deepseek-v4.1-flash-1017","deepseek/deepseek-v4.1-flash-0910","z-ai/glm-5.3-flash-0828","deepseek/deepseek-v4.1-flash:fast","deepseek/deepseek-v4.1-flash-1017:fast","deepseek/deepseek-v4.1-flash-0910:fast"]},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"message":{"type":"object","properties":{"role":{"type":"string","enum":["assistant"]},"content":{"type":["string","null"]},"reasoning_content":{"type":"string","description":"The model's reasoning, when it reasons before answering."},"tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolCall"}}}},"finish_reason":{"type":["string","null"],"enum":["stop","length","tool_calls",null]}}}},"usage":{"$ref":"#/components/schemas/Usage"},"service_tier":{"type":"string","enum":["default","priority"],"description":"The tier that served the request: `priority` in fast mode."}}},"ChatCompletionChunk":{"type":"object","description":"One Server-Sent Event `data:` payload. The stream ends with `data: [DONE]`.","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["chat.completion.chunk"]},"created":{"type":"integer"},"model":{"type":"string","enum":["deepseek/deepseek-v4.1-flash","z-ai/glm-5.3-flash","deepseek/deepseek-v4.1-flash-1017","deepseek/deepseek-v4.1-flash-0910","z-ai/glm-5.3-flash-0828","deepseek/deepseek-v4.1-flash:fast","deepseek/deepseek-v4.1-flash-1017:fast","deepseek/deepseek-v4.1-flash-0910:fast"]},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"delta":{"type":"object","properties":{"role":{"type":"string"},"content":{"type":["string","null"]},"reasoning_content":{"type":["string","null"]},"tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolCall"}}}},"finish_reason":{"type":["string","null"]}}}},"usage":{"description":"Present on the final chunk only.","oneOf":[{"$ref":"#/components/schemas/Usage"},{"type":"null"}]},"service_tier":{"type":"string","enum":["default","priority"],"description":"The tier that served the request: `priority` in fast mode."}}},"Response":{"type":"object","required":["id","object","created_at","status","model","output","usage"],"properties":{"id":{"type":"string","examples":["resp_example"]},"object":{"type":"string","enum":["response"]},"created_at":{"type":"integer"},"status":{"type":"string","enum":["completed","incomplete","failed","in_progress","queued","cancelled"]},"model":{"type":"string","enum":["deepseek/deepseek-v4.1-flash","z-ai/glm-5.3-flash","deepseek/deepseek-v4.1-flash-1017","deepseek/deepseek-v4.1-flash-0910","z-ai/glm-5.3-flash-0828","deepseek/deepseek-v4.1-flash:fast","deepseek/deepseek-v4.1-flash-1017:fast","deepseek/deepseek-v4.1-flash-0910:fast"]},"output":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["message"]},"id":{"type":"string","examples":["msg_example"]},"role":{"type":"string","enum":["assistant"]},"status":{"type":"string","enum":["completed"]},"content":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["output_text"]},"text":{"type":"string"},"annotations":{"type":"array","items":{}}}}},"phase":{"type":"string","enum":["commentary","final_answer"],"description":"`commentary`: text written before a tool call in the same response. `final_answer`: the reply. Assistant messages sent back in `input` may keep it."}}}},"usage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"input_tokens_details":{"type":"object","properties":{"cached_tokens":{"type":"integer","description":"Input tokens billed at the cached rate."}}},"output_tokens":{"type":"integer"},"output_tokens_details":{"type":"object","properties":{"reasoning_tokens":{"type":"integer","description":"Reasoning tokens, billed as output tokens."}}},"total_tokens":{"type":"integer"}}},"service_tier":{"type":"string","enum":["default","priority"],"description":"The tier that served the response: `priority` in fast mode."}}},"Model":{"type":"object","description":"One catalog entry: prices per token as decimal strings, limits, supported parameters, per-account capacity and serving location.","properties":{"schema_version":{"type":"string","examples":["2.4"]},"id":{"type":"string","examples":["deepseek/deepseek-v4.1-flash"]},"name":{"type":"string","examples":["DeepSeek: DeepSeek V4.1 Flash"]},"description":{"type":"string"},"hugging_face_id":{"type":"string","examples":["deepseek-ai/DeepSeek-V4.1-Flash-1017"]},"created":{"type":"integer","description":"Model release date, unix seconds."},"quantization":{"type":["string","null"],"examples":[null]},"tokenizer":{"type":"string","examples":["DeepSeek"]},"input_modalities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","examples":["text"]},"supported_inputs":{"type":"object"},"pricing":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","examples":["prompt","cached_prompt"]},"unit":{"type":"string","examples":["token"]},"cost_usd":{"type":"string","description":"USD per unit."}}}},"capacity":{"type":"array","items":{"type":"object"}}}}},"output_modalities":{"type":"array","items":{"type":"object"}},"capacity":{"type":"array","description":"Per-key limits: requests per minute.","items":{"type":"object"}},"datacenters":{"type":"array","items":{"type":"object","properties":{"country_code":{"type":"string","examples":["US"]}}}}}}}}}