Integration guide
Chat Completions
The fields POST /v1/chat/completions accepts and how they differ across providers.
POST /v1/chat/completions accepts requests in the OpenAI Chat Completions format.
The Gateway rejects unsupported fields, and any field not listed here, with 400.
A field with an empty “Provider differences” cell behaves the same whichever of OpenAI, Anthropic, Gemini, DeepSeek, and Kimi is assigned.
The shared rules and error sources are in the Gateway overview.
Provider differences at a glance
Section titled “Provider differences at a glance”- Anthropic requires a maximum token count. When both
max_completion_tokensandmax_tokensare omitted, the Gateway sends that model’s output ceiling. Seemax_output_tokensinGET /v1/modelsfor each model’s value, and set the field yourself when you need a long response. - Anthropic adds
additionalProperties: falseto every object in ajson_schema. A property the schema does not declare will not appear in the response. - Anthropic has no schema-free JSON mode. The Gateway adds a tool of its own named
json_output, has the model call it, and returns the result as acontentstring.json_objectcannot be combined withtools, and the tool namejson_outputcannot be used. - Kimi fixes its generation parameters to the values its model defines. Another value is rejected by Kimi, and you receive that response as it came.
- DeepSeek and Kimi accept the OpenAI format as it is, so the request shape stays the same. The values they do not accept are listed per field in the tables below.
Request fields
Section titled “Request fields”Model and messages
Section titled “Model and messages”| Field | Support | Provider differences |
|---|---|---|
model | Supported | |
messages[].role: system, developer | Supported (text only) | Anthropic, Gemini: concatenated into one message at the front DeepSeek, Kimi: developer is sent as system, and its position is kept |
messages[].role: user | Supported (string or part array) | |
messages[].role: assistant | Supported (text only) | |
messages[].content[].image_url.url | Supported (base64 data URL or http(s) URL) | Gemini: a URL’s type comes from the extension at the end of the address, so an address without one is rejected Kimi: http(s) URLs are not accepted DeepSeek: some of its models read images and some do not |
messages[].content[].file.file_data | Supported (base64 PDF data URL only) | DeepSeek, Kimi: PDFs are not accepted |
messages[].content[].file.filename | Supported | Gemini: not sent |
- Content shape: The content of a
usermessage is a string or an array oftext,image_url, andfileparts. Anassistantmessage needscontentunless it carriestool_callsorreasoning_details. - Media parts: Images and PDFs are accepted only in
usermessages, and images may be png, jpeg, webp, or gif. - Image URLs: An image may be sent as an http(s) URL instead of a base64 data URL. The Gateway passes the address through and the provider downloads it, so the address must be publicly reachable by the provider. PDFs are accepted as base64 data URLs only.
- System prompt: When the assigned option has a system prompt, it is used instead of the
systemanddevelopermessages. - Model name: Before routing is configured, requests go to OpenAI, so
modelmust be an OpenAI model name. Once routing is configured, the assigned option sets the provider and the model. The available names are in the Model list.
Output length and streaming
Section titled “Output length and streaming”| Field | Support | Provider differences |
|---|---|---|
max_completion_tokens | Supported | Anthropic: the model’s output ceiling when both are omitted |
max_tokens | Supported (legacy) | Anthropic: the model’s output ceiling when both are omitted |
n | No multiple choices (1 only) | |
stream | No streaming (false only) |
When max_tokens and max_completion_tokens are sent together, max_completion_tokens is used.
Generation parameters
Section titled “Generation parameters”| Field | Support | Provider differences |
|---|---|---|
temperature | Supported | Kimi: only the value its model defines DeepSeek: not applied while the model reasons |
top_p | Supported | Kimi: only the value its model defines |
frequency_penalty | Supported | Kimi: only the value its model defines DeepSeek: not applied |
presence_penalty | Supported | Kimi: only the value its model defines DeepSeek: not applied |
seed | Supported | Kimi: not applied |
reasoning_effort | Supported | DeepSeek, Kimi: the accepted values differ from OpenAI, so check them in the dashboard |
verbosity | Supported | DeepSeek, Kimi: not applied |
- Before routing is configured: The values you send are used as sent, and that setup is registered as an Origin option.
- After routing is configured: The assigned option’s values are used, and the values in the request are not applied. A parameter the option leaves unset is not sent to the provider, so the provider’s own default applies.
- What you can set: The dashboard shows the range each option can set for a given provider and model. Options can also carry provider-specific parameters that this table does not list.
Response format
Section titled “Response format”| Field | Support | Provider differences |
|---|---|---|
response_format: text | Supported | |
response_format: json_schema | Supported | Anthropic: adds additionalProperties: falseDeepSeek: not accepted |
response_format: json_object | Supported | Anthropic: implemented as a tool call |
- Schema:
json_schemarequiresjson_schema.schema. The inside of the schema is passed through without inspection. - What travels: A
json_schemacarries four keys —name,description,strict, andschema. Any other key is not passed on to the provider, and key names must match exactly, including case. Anthropic and Gemini rebuild it in the provider’s own format and carry onlyjson_schema.schema, soname,description, andstrictreach OpenAI only. - Value types:
nameanddescriptionare strings andstrictis a boolean. A mismatched type is rejected with a 400 that names the key. - Combination rule:
json_objectcannot be sent together withtools.
Tool calling
Section titled “Tool calling”| Field | Support | Provider differences |
|---|---|---|
tools | Supported (type: function only) | |
tools[].function.strict | Supported | Gemini: one true validates every tool |
tool_choice | Supported (none, auto, required, named function) | A named function may still be called more than once |
tool_choice: allowed_tools | Supported (mode is auto or required only) | Anthropic, DeepSeek, Kimi: tools outside the list are removed |
parallel_tool_calls | Cannot be turned off (true only) | |
functions | Supported (legacy) | |
function_call | Supported (legacy; none, auto, named function) | |
messages[].tool_calls[].id | Supported | |
messages[].tool_calls[].function.arguments | Supported (JSON object string only) | |
messages[].role: tool | Supported | |
messages[].role: function | Supported (legacy) |
- Combination rules:
tool_choicemust be sent withtools. Legacyfunctionscannot be sent withtoolsortool_choice, andfunction_callrequiresfunctions. - Tool names and schemas: The tool name
json_outputcannot be used. The inside oftools[].function.parametersis passed through without inspection. - Returning results: Send back the
tool_calls[].idandtool_call_idvalues you received in the response. Values that do not pair up are rejected by the provider. Thecontentof arole: toolmessage is a string or atextpart, and arole: functionmessage needs anamematching the precedingfunction_call. - Response shape: A request sent with
functionscomes back withmessage.function_callandfinish_reason: "function_call". When one response carries several calls, only the first one is placed inmessage.function_call; read the rest frommessage.tool_calls. Every other tool-calling response comes back withmessage.tool_callsandfinish_reason: "tool_calls". - Legacy recommendation: Legacy
functionsexpresses only one call per turn. Gemini, DeepSeek, and Kimi return several calls in one response, and answering them one at a time makes them ask for the remaining calls again, which adds turns. Usetools.
Reasoning
Section titled “Reasoning”| Field | Support | Provider differences |
|---|---|---|
messages[].reasoning_details | Supported | OpenAI: returns no reasoning, so there is nothing to send |
- What comes back: Reasoning models return their reasoning in
message.reasoning_details. Each entry is identified bytype:reasoning.textholds the text intext, andreasoning.encryptedholds a value only the provider can read indata.formatnames the provider that produced the reasoning. - Carrying it to the next turn: To continue a conversation, send the
reasoning_detailsyou received back in the assistant message without changing it. Reordering the entries or editing their contents breaks the continuation. Placing the responsemessageobject into the history as it is carries the field along. - Keep a conversation on one option: Send the same
x-abto-device-idon every request of a multi-turn conversation. That value keeps the conversation assigned to one option so the reasoning carries over. Without it each request is assigned on its own, and once the provider changes the earlier reasoning is not used and the model reasons again. - When it is left out: Gemini rejects a history whose tool-calling turn is missing its reasoning. DeepSeek rejects a history that changes the
tool_calls[].idvalues it returned and drops the reasoning as well. Anthropic and Kimi continue without it and reason again on every turn, which raises the reasoning token count. - Reasoning tokens:
usage.completion_tokens_details.reasoning_tokenscounts the tokens spent on reasoning and is separate from the reasoning contents. - Conversations without tools: Reasoning carries over independently of tool calling. Send it the same way in multi-turn conversations that use no tools and in conversations that use
functions.
Unsupported fields
Section titled “Unsupported fields”The Gateway rejects the fields below with 400. Fields that appear in no table are rejected the same way.
| Group | Fields |
|---|---|
| Token probabilities | logprobs, top_logprobs, logit_bias |
| Audio and other inputs | modalities, audio, messages[].audio, other content parts such as input_audio |
| Image and file options | messages[].content[].image_url.detail, messages[].content[].file.file_id, an http(s) URL in messages[].content[].file.file_data |
| Provider-side features | store, service_tier, moderation, web_search_options, prediction |
| Prompt caching | prompt_cache_key, prompt_cache_options, prompt_cache_retention |
| Request tags and user identity | metadata, user, safety_identifier |
| Other | stop, stream_options, messages[].name (except role: function), messages[].refusal, messages[].reasoning, messages[].reasoning_content |
Tagging requests at the provider and identifying users to the provider cannot be replaced. For your own analytics, send identifiers as x-abto-feature-id and x-abto-device-id from the Reference; those headers are recorded in ABTO and are not forwarded to the provider.
Provider API references
Section titled “Provider API references”The Gateway sends requests in the API formats below. For the values each provider accepts and the conditions it rejects, see its documentation.
- OpenAI: Chat Completions API
- Anthropic: Messages API
- Gemini: Interactions API