Gateway reference#
Look up the gateway addresses, authentication, headers, endpoint behaviour and limits. For how the gateway works and why, see Gateway concepts. For error formats, see Errors.
At a glance
- Call OpenAI-style endpoints under
https://<atlas-host>/gateway/openai/v1, and Anthropic Messages underhttps://<atlas-host>/gateway/anthropic. - Authenticate with an ATLAS API key. The key alone decides the space or project the request runs under. The gateway ignores any space or project header you send.
- Name the model as
provider-slug/model-slug, for exampleopenai/gpt-4.1. - Every request is checked against your model and budget rules before it reaches a provider.
Endpoints#
All paths are relative to https://<atlas-host>/gateway.
| Method | Path | Request | Response | Purpose |
|---|---|---|---|---|
POST |
/openai/v1/chat/completions |
JSON | JSON or SSE | Chat completions on any provider |
POST |
/openai/v1/responses |
JSON | JSON or SSE | OpenAI Responses API |
POST |
/openai/v1/embeddings |
JSON | JSON | Text embeddings |
POST |
/openai/v1/rerank |
JSON | JSON | Document reranking (Cohere v2 / Jina shape) |
POST |
/openai/v1/audio/transcriptions |
multipart/form-data |
Provider's content type | Speech to text |
POST |
/openai/v1/audio/speech |
JSON | Audio bytes | Text to speech |
GET |
/openai/v1/models |
Optional ?endpoint=chat|embeddings|rerank|transcription|speech |
{object:"list", data:[…]} |
Models your key can use. An unknown filter returns 400 |
GET |
/openai/v1/models/{model} |
{model} is provider-slug/model-slug |
Model entry | One model |
GET |
/openai/v1/models/{model}/parameters |
None | {model, supported_parameters[]} |
Parameters the gateway passes on for the model |
POST |
/anthropic/v1/messages |
JSON | JSON or Anthropic SSE | Anthropic Messages API (Claude models only) |
POST |
/anthropic/v1/messages/count_tokens |
JSON | JSON | Token count (no budget check, no cost) |
GET |
/anthropic/v1/models |
limit, before_id, after_id |
Anthropic model list | Claude models your key can use |
GET |
/anthropic/v1/models/{model} |
{model} may be %2F-encoded |
Anthropic model entry | One Claude model |
POST |
/openai/v1/completions |
None | None | Not offered. Use /openai/v1/chat/completions. |
Model entry#
Each entry in /openai/v1/models has these fields:
id,object,created,owned_byprovider_scope,provider_type,model_name,statusmax_input_tokens,max_tokens,context_lengthendpoints[],top_provider.max_completion_tokens- A
capabilitiesobject withtemperature_supported,reasoning,reasoning_options,tool_call,structured_output,context_limit,output_limit,statusandmodalities
Anthropic model entry#
Each entry has type, id, display_name and created_at. created_at is RFC 3339 in UTC and holds the date the model was added to ATLAS.
| Rule | Value |
|---|---|
limit |
1 to 1000, default 20 |
before_id and after_id together |
400 |
| Cursor your key cannot see | 400 |
| Order | Newest first, then by id |
| Hidden or unknown model | 404 with not_found_error |
Authentication#
| Rule | Behaviour |
|---|---|
| Header | Authorization: Bearer <your-atlas-key> |
| Anthropic addresses | Also accept x-api-key: <your-atlas-key>. Sending both with the same key is fine. Different keys return 401. |
| OpenAI addresses | Bearer only |
401 |
The key is missing, invalid, expired, revoked or conflicting. The answer is identical for every cause, so keys cannot be probed. Requests with an invalid key aren't recorded. |
| Key types | Personal keys (act under a space or a project) and project keys. See API keys. |
A valid key can still be refused. The error tells you why: 403 organization_suspended, project_archived or no_acting_context. See Errors.
Headers#
| Header | Direction | Notes |
|---|---|---|
Authorization |
Request | Bearer ATLAS key |
x-api-key |
Request | Anthropic addresses only |
anthropic-version |
Request | Passed on. Your value wins. |
anthropic-beta |
Request | Passed on to Claude models. Flags a provider does not support may be removed so your client keeps working. |
Accept |
Request | Ignored on streaming endpoints. The stream flag in the body decides. |
traceparent, tracestate, atlas-correlation-id |
Request | Optional. The correlation id is kept in the audit log, so you can match a request to your own logs. |
atlas-request-id |
Response | The ATLAS request id. Also present in error bodies. Quote it to your ilionx contact. |
request-id |
Response | Anthropic addresses only. Same value as atlas-request-id. |
Retry-After |
Response | On provider_rate_limited and availability errors. |
Your credentials are never forwarded to the provider.
Chat completions#
POST /openai/v1/chat/completions is OpenAI-compatible. model is a reference of the form provider-slug/model-slug. A bare model name returns 404 model_not_found.
- ATLAS understands
model,messages,temperature,max_tokensandstream. Other parameters are passed to the provider where the model supports them. See Unsupported parameters. max_completion_tokensis accepted. If you send bothmax_tokensandmax_completion_tokens,max_completion_tokenswins and only one limit reaches the provider.toolsandtool_choicework on OpenAI, Azure OpenAI, Anthropic and Ollama models. See Tool calling.- Dropped parameters are listed in a top-level
atlas_stripped_parametersarray, or on the first chunk only when streaming. The array is present only when something was dropped. - Claude thinking blocks appear as
message.reasoning_content(non-streaming) ordelta.reasoning_content(streaming). contentis always present andnullwhen the turn produced no visible text.- A streamed response never contains an empty
"content":""chunk.
Streaming#
| Rule | Value |
|---|---|
| Selector | The top-level stream flag in the body. Nested stream keys are ignored. |
| Applies to | Chat completions, Responses and Anthropic Messages |
| Format | data: {…} frames ending with data: [DONE] (OpenAI). Anthropic Messages returns Anthropic SSE. |
| Embeddings and rerank | Not streamed. stream has no effect. |
| Transcription | stream=true returns 400 |
| Speech | stream_format=sse is refused |
| Failure before the first chunk | A normal HTTP error |
| Failure after the first chunk | One final error frame in the format of the address you called, then the stream ends |
| Provider closes the connection early | provider_stream_interrupted (502) |
Tokens used before a failure or a client cancel are still counted and billed.
Trailing usage chunk#
Before [DONE], a final chunk with choices: [] carries token usage:
{
"id": "…",
"object": "chat.completion.chunk",
"model": "…",
"choices": [],
"usage": {
"prompt_tokens": 123,
"completion_tokens": 45,
"total_tokens": 168,
"prompt_tokens_details": { "cached_tokens": 80 }
}
}| Rule | Behaviour |
|---|---|
| OpenAI and Azure OpenAI models | The provider's own usage chunk passes through unchanged |
| Anthropic, Ollama and Bedrock models | The gateway creates the chunk. stream_options.include_usage set to true or false in your request wins. Otherwise the chunk is sent. |
| Never invented | Omitted when no tokens were observed, and after a failure mid-stream |
| Claude cache tokens | Cache read and cache creation tokens are included in prompt_tokens. Cache reads also show as prompt_tokens_details.cached_tokens. |
Tool calling#
| Provider | Behaviour |
|---|---|
| OpenAI, Azure OpenAI | Native and unchanged |
| Anthropic | tool_choice values "auto", "none", "required" or a named function are translated. parallel_tool_calls: false disables parallel tool use. Unrecognisable forms fail with 400 naming tool_choice. Tool results and replayed tool calls are converted both ways. finish_reason is tool_calls. |
| Ollama | tools are forwarded. tool_choice "auto" is dropped. "none" sends no tools. "required" or a named function returns 400. Responses are normalised to the OpenAI shape for streaming and non-streaming alike. |
Responses API#
POST /openai/v1/responses accepts the OpenAI Responses format for any chat model. The model decides whether ATLAS passes the request straight to the provider or translates it:
- A model that supports the Responses API natively receives the request unchanged, apart from the model name.
- A chat-only model (Anthropic, Ollama, AWS Bedrock, or any model configured for chat) is served by translating the request to chat and the answer back.
- A chat request to a model configured for Responses is translated the other way.
| Rule | Behaviour |
|---|---|
Rejected when translated to chat (400) |
previous_response_id, store: true, conversation and built-in tools |
| Fields that cannot be mapped | Dropped and reported in atlas_stripped_parameters |
atlas_stripped_parameters placement |
Top level when not streaming. On response.created when streaming. |
| Streaming terminal event | Exactly one of response.completed, response.failed, response.incomplete |
| Provider failure on a translated request | response.failed |
| Usage | input, output, cached-read and reasoning tokens |
Embeddings#
POST /openai/v1/embeddings takes {model, input: string | string[], encoding_format?, dimensions?, user?}.
| Rule | Behaviour |
|---|---|
| Eligibility | The model must offer embeddings. Otherwise 400 model_not_supported_for_endpoint and nothing is sent to the provider. |
| Batching | One request is one cost and one budget decision, however many inputs it holds |
| Cost | Input tokens only |
| Storage | Vectors are never stored |
- The gateway accepts a list of any length for every embedding model. If the model limits inputs per upstream call, the gateway splits the list into several calls and runs them in parallel. Cohere Embed models on AWS Bedrock take 96 inputs per call. Amazon Titan Text Embeddings v2 takes one input per call, so a list of 50 inputs makes 50 calls. Other models take the whole list in one call.
- The gateway merges the results in input order. It records one audit entry and one cost for the request, based on the summed input tokens of all calls.
- If any call fails, the whole request fails. Tokens from calls that completed are still billed.
input_typeapplies to Cohere Embed models on AWS Bedrock only. Values aresearch_document(default),search_query,classificationorclustering. Any other value returns400. Other models ignore it.- With
encoding_format: base64, vectors are returned as little-endian 32-bit floats.
Rerank#
POST /openai/v1/rerank needs a rerank model.
| Field | Rule |
|---|---|
query |
Required |
documents |
1 to 1000 strings. Structured documents return 400 |
top_n |
At least 1. Clamped to the number of documents sent. |
return_documents |
Optional |
Results are sorted by descending score and capped to top_n. The gateway fills in the document text from your request and always returns usage.
Transcription#
POST /openai/v1/audio/transcriptions accepts multipart/form-data and needs a transcription model.
| Field | Rule |
|---|---|
file |
Required, exactly one |
model |
Required |
language, prompt |
Optional |
response_format |
json, text, srt, verbose_json, vtt |
temperature |
0 to 2 |
timestamp_granularities[] |
Optional |
A missing file or model, a duplicate file, an invalid temperature or stream=true returns 400. The provider's answer comes back unchanged with its content type. Audio is never stored.
Speech#
POST /openai/v1/audio/speech needs a speech model.
| Field | Rule |
|---|---|
model |
Required |
input |
Up to 4096 characters |
voice |
Required by OpenAI-compatible providers |
response_format |
mp3, opus, aac, flac, wav, pcm |
speed, instructions |
Optional |
stream_format=sse |
Refused |
Audio streams back with the provider's content type. Audio is never stored.
Anthropic Messages#
Claude Code, Anthropic SDKs and opencode use the Anthropic addresses to reach Claude through ATLAS. For client setup, see Connect an OpenAI- or Anthropic-compatible client.
| Setting | Value |
|---|---|
| Base URL | https://<atlas-host>/gateway/anthropic |
| Credentials | Your ATLAS API key, sent as x-api-key or as a Bearer token |
model |
The ATLAS model reference (provider-slug/model-slug), not the provider's own id |
The request body is forwarded as you sent it. Only the model id is replaced.
| Rule | Behaviour |
|---|---|
| Rejections | Unknown model: not found. Non-Claude model: 400. Server-side tools: 400 (allowed on count_tokens). Malformed body: 400. |
count_tokens |
Same authentication and model access as Messages, but no budget check and no cost. ATLAS never estimates counts. The provider counts them. |
Model resolution#
The key decides where a model name is looked up.
| Credential | Models available |
|---|---|
| Personal key | The organisation's models first, then models provided by ilionx, minus any the space restricts |
| Key acting under a project | Only the project's own model list |
| Condition | Error |
|---|---|
Bare name, empty part, more than one /, unknown, inactive, or hidden by a space restriction |
404 model_not_found |
| The model's provider is disabled | 403 provider_disabled |
| The project has no models | 404 project_has_no_models |
| The model cannot serve the endpoint you called | 400 model_not_supported_for_endpoint |
A model that the space restricts or hides returns 404 model_not_found, the same as a model that does not exist.
Unsupported parameters#
ATLAS removes some parameters a model does not support so the request still succeeds. Removed parameters are listed in atlas_stripped_parameters in the response.
ATLAS does not silently remove parameters that change how you must read the response: n, logprobs, top_logprobs and response_format. On providers that cannot honour them, the request fails with 400 naming the field.
ATLAS adds stored model defaults for any parameter you omitted (JSON null counts as omitted). Your values always win, including none and 0. Admins can adjust parameter handling per provider. See Tune how a provider handles request parameters.
Reasoning parameters#
ATLAS understands these reasoning parameters:
reasoning_effort(OpenAI, Anthropic, AWS Bedrock)reasoning_budget_tokensandreasoning_enabled(Anthropic, AWS Bedrock)
Claude thinking blocks appear as reasoning_content. OpenAI-family models receive reasoning_effort as sent.
Provider failures#
- ATLAS retries temporary provider failures automatically before it returns an error.
- Streams that have already started are not retried.
- A provider may still bill a failed first attempt.
- When a provider keeps failing, you receive one of the errors listed in Errors.
- Your key was valid even if the error mentions the provider's credentials. The problem is on the provider side.
- Quote the
atlas-request-idto your ilionx contact.
Budgets#
ATLAS checks budgets before it sends the request. A used-up limit returns 429 budget_exceeded (OpenAI addresses) or 402 with billing_error (Anthropic addresses). For the rules, see Budgets.
Limits#
| Limit | Value |
|---|---|
| Request body | 25 MB. Larger returns 413 request_too_large. |
| Rerank documents | 1 to 1000 strings |
Speech input |
4096 characters |
Transcription temperature |
0 to 2 |
Anthropic models limit |
1 to 1000 (default 20) |
| Provider connect timeout | 10 seconds |
| Provider response timeout | 180 seconds by default. An Admin can set 1 to 600 seconds per provider. |
| Provider retries | Up to 2 retries on 429, 500, 502, 503, 504 and connection errors. Started streams are not retried. |