Integration guide
Gateway overview
How the Gateway handles requests, which endpoints it accepts, where each request parameter comes from, and how to read the error source.
The ABTO Gateway takes your AI calls and forwards each one to OpenAI, Anthropic, Gemini, DeepSeek, or Kimi according to your routing. Gemini can be called through Google AI Studio or through Google Cloud Vertex AI. This page covers the rules that apply across the Gateway: supported endpoints, where request parameters come from, and error sources. The accepted fields and the per-provider differences are in Chat Completions and Responses.
How requests are handled
Section titled “How requests are handled”- The Gateway rejects unsupported fields with
400instead of ignoring them. - Supported fields are translated into the assigned provider’s API format. The provider decides how to apply each value, and a request the provider rejects comes back with the provider’s status code and error message.
- Some fields behave differently depending on the assigned provider. Provider differences at a glance lists which fields differ and how.
Supported endpoints
Section titled “Supported endpoints”The Gateway accepts only the endpoints below.
| Endpoint | Format | Guide |
|---|---|---|
POST /v1/chat/completions | OpenAI Chat Completions | Chat Completions |
POST /v1/responses | OpenAI Responses | Responses |
GET /v1/models | OpenAI Models | Model list |
A request body larger than 20MB returns 413.
The headers every request must carry are in the Reference.
Where request parameters come from
Section titled “Where request parameters come from”Before you configure routing, every request is forwarded to OpenAI exactly as sent, so x-abto-key-openai is required.
The settings your code was already using are registered automatically as an Origin variant.
Once a feature has routing, request fields fall into three groups.
Taken from the request
Section titled “Taken from the request”| What it carries | Request fields |
|---|---|
| Conversation | user, assistant, and tool messages, input in Responses |
| Output length limit | max_completion_tokens, max_tokens, max_output_tokens |
| Response format | response_format, text.format |
| Tool calling | tools, tool_choice, functions, function_call |
| Reasoning summary | reasoning.summary |
These use the values you send, regardless of routing.
Replaced when the variant sets one
Section titled “Replaced when the variant sets one”| What it carries | Request fields |
|---|---|
| System prompt | system, developer messages, instructions in Responses |
When that node allows system prompts and the assigned variant has a system prompt, that value is used instead of the original request’s messages. Otherwise the original request’s messages are used as sent.
Replaced by the variant
Section titled “Replaced by the variant”| What it carries | Request fields |
|---|---|
| Model | model |
| Generation parameters | temperature, top_p, seed, reasoning_effort, reasoning.effort, and so on |
The assigned variant sets these values, and the values in the request are not used. The variant also sets the provider. If the variant does not change that node’s setup, the values in the request are used as sent. A parameter the variant leaves unset is not sent to the provider, so the provider’s own default applies. Variants can also carry provider-specific parameters that this table does not list. The dashboard shows what you can set for each provider and model.
Model list
Section titled “Model list”GET /v1/models returns the models ABTO supports in the OpenAI Models format. It authenticates with the same API key as Chat Completions and Responses, and the OpenAI SDK’s models.list() reads it as is.
{ "object": "list", "data": [ { "id": "gpt-5.4", "object": "model", "owned_by": "openai", "base_model": "gpt-5.4", "supported_parameters": [ { "name": "temperature", "type": "number", "range": [0, 2] }, { "name": "reasoning_effort", "type": "string", "allowed_values": ["none", "low", "medium", "high", "xhigh"], "default": "none" } ], "constraints": [ { "type": "depends_on", "param": "temperature", "ref_param": "reasoning_effort", "ref_value": "none" } ] } ]}| Field | Meaning |
|---|---|
id | Model name. Use it as is in the request’s model |
owned_by | Provider (openai, anthropic, gemini, deepseek, kimi, vertex). vertex is Gemini called through Vertex AI |
base_model | Name of the model family. Equal to id for the current name; different for a dated snapshot of that family |
supported_parameters | Generation parameters this model accepts, with their value ranges |
max_output_tokens | The model’s output token ceiling. Absent for providers that do not require one |
constraints | Relations between parameters. mutually_exclusive cannot be sent together; depends_on can be sent only while ref_param is ref_value |
- Parameter names for Responses requests: for OpenAI models,
supported_parametersandconstraintsuse the Chat Completions names. When you call Responses, sendreasoning_effortasreasoning.effortandverbosityastext.verbosity;seed,frequency_penaltyandpresence_penaltyare not accepted.reasoning.efforton the GPT-5.6 and GPT-6 families also acceptsmax. - Before routing is configured: requests go to OpenAI, so only names whose
owned_byisopenaican be sent inmodel. OpenAI fine-tuned models (names starting withft:) can also be sent as is, even though they are not in this list. - After routing is configured: only canonical models whose
base_modelequalsidcan be chosen for a variant in the dashboard. Dated snapshots do not appear in the variant editor. - Cost: ABTO first uses the price for the model name returned by the provider. If the response has no model name, it uses the assigned model. When the catalog has no price for that name, the request is recorded without a cost. A fine-tuned model is recorded at its base model’s fine-tuned inference price when the catalog has one, and without a cost otherwise.
Origin variants
Section titled “Origin variants”Before you configure routing, requests run with the provider, model, generation parameters, and system prompt your code chose. The Gateway registers that setup as the feature’s Origin variant. Nothing else to set up.
The Origin variant is your baseline for comparison. Create a new variant in the dashboard, split routing between them, and you measure the new setup against Origin, your existing code. Its setup comes from your code, so it cannot be edited in the dashboard. Only its name can change.
When your code changes the model or generation parameters, the Gateway registers the new setup as a new Origin variant.
The previous Origin variant stays so you can still read its past results, and the routing share it held moves to the new Origin variant.
Origin variants do not include a system prompt and use the original request’s system and developer messages as sent. A change to the system prompt alone does not create a new Origin variant (see the Routing screen).
Error source
Section titled “Error source”The x-abto-error-source header on an error response tells you what rejected the request.
| What rejected it | Status code | x-abto-error-source | Body |
|---|---|---|---|
| Provider | The status the provider returned | provider | The provider’s message, type, and code |
| Provider connection failure | 502, 504, 499 | transport | type is transport_error |
| ABTO Gateway | 400, 401, 413, 500 | gateway | {"error":{"message":"…"}} |
An error body the ABTO Gateway produced has no type, param, or code. A provider error keeps the provider’s values inside the OpenAI error format.
When the Gateway rejects the request body, message says why.
| Example | message |
|---|---|
| Unsupported field | unsupported field "logprobs" |
| Unsupported value | n=2 is not supported: the gateway serves a single choice |
| Fields that cannot be combined | response_format json_object cannot be combined with tools |
| JSON parse failure, type mismatch | cannot parse request body |
Every response from a supported endpoint carries x-abto-request-id.
The Requests screen records the requests that finished assignment and went into processing. Those responses also carry x-abto-attempt and x-abto-provider, so an error without these headers leaves no record on that screen.