Models
The gateway is model-first: every model is identified by its canonical
catalog slug author/model, where the author is who made the model
(anthropic/claude-sonnet-4-6, alibaba/qwen3.7-max, deepseek/deepseek-v4-pro,
xai/grok-4) — regardless of where inference runs. The inference provider is an
operational detail the gateway resolves for you; it is never something you need
to know to call a model.
The slug carries no snapshot date. A model’s pinned snapshot lives in the
catalog’s provider_model field, not in the slug — the slug stays stable as the
operator advances snapshots (e.g. bytedance/seed-2-0-pro always points at the
current 2.0 Pro snapshot). The author is the model’s creator; the provider that
serves it is a routing detail that can differ from the author and that the
gateway resolves internally — you never need to know it to call a model.
The model catalog
Section titled “The model catalog”GET https://api.sociaro.com/v1/models # OpenAI-compatible listGET https://api.sociaro.com/gw/models # gateway form, with metadataBoth endpoints serve the same global catalog and accept any valid key.
GET /v1/models is the OpenAI shape
({"object":"list","data":[{"id":"alibaba/qwen3.7-max","object":"model","created":...,"owned_by":"alibaba"}]}),
so official SDKs pointed at the gateway can list models natively.
GET /gw/models adds the metadata: kind
(llm | image | video | embedding | 3d | rerank | audio),
context_length for LLMs, and a per-model allowed flag — whether your
organization’s ceiling would permit calling the model (computed server-side;
see the API reference). The kind determines which door serves the model and
how it is priced — see billing modes
below.
What’s in the catalog
Section titled “What’s in the catalog”The catalog spans many authors, each model identified by its author/model
slug. The table below lists flagship examples per category — it is not
exhaustive (the live catalog holds ~92 models and grows). For the full,
authoritative list, call GET /v1/models (or GET /gw/models for metadata);
do not hardcode this table.
Category (kind) | Door | Flagship slugs (examples) |
|---|---|---|
| Chat (LLM) | /v1/chat/completions, /v1/messages | alibaba/qwen3.7-max, bytedance/seed-2-0-pro, deepseek/deepseek-v4-pro, zai/glm-5.1, xai/grok-4, openai/gpt-oss-120b |
| Vision (LLM) | /v1/chat/completions, /v1/messages | alibaba/qwen3.7-max-vision, alibaba/qwen3-vl-235b-a22b-instruct, alibaba/qwen-vl-ocr |
| Omni (LLM, multimodal in/out) | /v1/chat/completions | alibaba/qwen3.5-omni-plus, alibaba/qwen3.5-omni-flash |
| Image | /v1/images/generations | bytedance/seedream-5-0, alibaba/qwen-image-2.0-pro, alibaba/z-image-turbo, alibaba/wan2.7-image |
| Video | /v1/videos | alibaba/wan2.7-t2v, alibaba/wan2.6-i2v, bytedance/seedance-1-5-pro, bytedance/dreamina-seedance-2-0 |
| Embedding | /v1/embeddings | alibaba/text-embedding-v4 |
| Rerank | /v1/reranks | alibaba/qwen3-rerank |
| Audio (TTS) | /v1/audio/speech | alibaba/qwen3-tts-flash |
Vision and omni models are addressed through the same LLM doors as chat — the
distinction is in what content the model accepts (images, audio) and returns,
not in a separate endpoint. Image and video generation use the media doors,
covered below and in media doors. The embedding, rerank and
audio (TTS) doors — including their request/response shapes, the per-door kind
rule, and which provider backs each — are documented in
embeddings, reranks & speech. Embedding and
Rerank are live (alibaba/text-embedding-v4, -v3, alibaba/qwen3-rerank);
Audio is not in the live catalog yet — no audio model is enabled, so both
TTS (/v1/audio/speech, 404) and ASR (through the chat door) are not yet
callable (see that page’s Availability note).
Variant families. Many authors ship a model as a family of distinct slugs —
by size and reasoning mode (alibaba/qwen3-vl-8b-instruct,
alibaba/qwen3-vl-235b-a22b-thinking) or by speed tier
(alibaba/qwen-mt-flash / -lite / -plus,
alibaba/qwen3-coder-flash / -next / -plus). Each variant is its own
catalog slug you call directly; the gateway does not infer a variant for you.
Slugs never carry a date — the dated upstream snapshot (e.g.
qwen3.7-max-2026-06-08) is the provider’s internal id, stored behind the slug,
not something you call. Enumerate the live set with GET /v1/models rather than
guessing a slug from a family name.
Recent additions to the catalog span authors such as Alibaba (alibaba/qwen3.7-max,
alibaba/qwen3-vl-*, alibaba/qwen3.5-omni-*, alibaba/wan2.7-*), ByteDance
(bytedance/seed-2-0-pro, bytedance/seedream-5-0, bytedance/seedance-1-5-pro),
DeepSeek (deepseek/deepseek-v4-pro), OpenAI (openai/gpt-oss-120b), Zhipu AI
(zai/glm-5.1), xAI (xai/grok-4, xai/grok-code-fast-1) and Google
(google/nano-banana-2).
Again: the provider that serves a model is a routing detail the gateway resolves
internally. You address a model by its author/model slug at the doors
regardless of which provider serves it; the native prefixes (below) are only for
byte-exact pass-through to a genuine vendor’s own API.
Billing modes: how models are priced
Section titled “Billing modes: how models are priced”Every model bills in exactly one mode, fixed by its kind and the provider’s
upstream pricing. You never configure the mode — the gateway computes the cost
server-side and records the authoritative per-request figure in
GET /gw/usage (cost_usd). The modes below
cover every model kind; the live catalog today holds llm, image,
video, embedding and rerank models, so only the audio / 3d rows
describe how those kinds bill once their models are enabled (neither is in the
catalog yet).
| Mode | Applies to (kind) | How cost is computed |
|---|---|---|
| Per-token | llm (chat, vision, omni) | prompt_tokens × input rate + completion_tokens × output rate, plus cache rates. |
| Per-token (input-only) | embedding, rerank | prompt_tokens × input rate. Output tokens are not billed. |
| Tiered per-token | some llm | Per-token, but the input/output rate steps up above a model-specific prompt-length break (128K or 256K). See the note above. |
| Cached input/output | llm | When the provider reports cache hits, cache_write_input_tokens bill at a cache_write rate and cache_read_input_tokens at a (cheaper) cache_read rate. These rates are not tiered. |
| Omni audio-modal premium | omni llm | Audio input/output tokens of omni models bill at a separate, higher rate than text tokens (see below). |
| Per-image | image | Number of images generated × per-image rate. The synchronous /v1/images/generations door meters the returned image count; async image jobs (POST /v1/images) finalize the count at terminal state — see async jobs. |
| Per-second (video) | video | Generated duration in seconds × per-second rate × a resolution multiplier (e.g. Alibaba Wan/HappyHorse). ByteDance Seedance video instead bills per-token × multipliers. |
| Per-second (audio / ASR) | audio (transcription) | Audio duration in seconds × per-second rate. ASR runs through /v1/chat/completions (e.g. alibaba/qwen3-asr-flash) or native async; the duration comes from the provider’s usage. |
| Per-character (TTS) | audio (speech) | input character count ÷ 10 000 × a per-10k-character rate. Counted from the request’s input string, because the TTS response is binary audio with no token usage. |
| Flat | some audio (voice enrollment/design) | A fixed price per request, independent of size. |
A few cross-cutting rules apply on top of the mode:
Omni audio tokens bill at a premium. Multimodal (omni) chat models
(alibaba/qwen3.5-omni-plus, alibaba/qwen3.5-omni-flash,
alibaba/qwen3-omni-flash) return separate audio_tokens counts inside
usage.prompt_tokens_details / completion_tokens_details. When present, those
audio tokens bill at the model’s dedicated audio rate (higher than its text
rate), and only the remaining non-audio tokens bill at the text rate. If a
response carries no audio tokens, everything bills at the text rate — there is no
omni surcharge on a text-only turn.
Async final cost can override the tariff math. For async media jobs
(video; async image jobs via POST /v1/images; native-prefix async ASR
audio jobs; 3d once its models are enabled), the gateway charges a
provisional cost at create time (from your request’s parameters) and
replaces it with the final cost when the job finishes. The final cost follows
a precedence chain:
a provider-reported explicit USD cost wins; otherwise provider-reported credits
are converted to USD; otherwise the per-token or per-unit (per-second /
per-image / per-megapixel) tariff math is used. The branch that produced the
figure is recorded as finalize_source. See async jobs.
Variant tariffs depend on a create-time parameter. A few media models scale
their per-second / per-token / per-image rate by a parameter you pass at create
time that is absent from the terminal response — for example
bytedance/seedance-1-5-pro’s generate_audio: false halves its per-token rate
(multiplier 0.5). The base
rate is always the worst case; the multiplier only ever discounts a
cheaper variant. If you omit the parameter or send an unrecognized value, you
pay the full base rate. Variant multipliers apply to both the provisional and the
final cost; they do not apply to an explicit provider-reported cost or credit
total.
The price table is global and the same for every key; your invoice is the sum of
the per-request cost_usd rows in GET /gw/usage over the period. (Resellers:
sub-account markup is applied on top of cost_usd at read time — see
markup_pct.)
Server-side route fallback
Section titled “Server-side route fallback”A catalog slug is normally served by one primary provider, but the operator can attach fallback routes to the same slug so the gateway can serve it from a second provider when the primary is unreachable. This is the gateway’s own cross-provider failover — distinct from the SDK’s client-side fallback chains, which advance across different slugs you list. Server-side route fallback advances across providers for the same slug, transparently, and the route taken is never exposed in the response.
How it works when the operator has enabled it:
- Routes are ranked. The primary route is rank 0; operator-configured fallbacks are rank 1, 2, … The gateway tries them in order, up to a configured hop limit (default: primary + 1 fallback).
- Only provider failures fail over. A route is retried on connect, timeout,
or TLS errors and on upstream
502/503/504/529(overloaded), on an upstream401(a broken provider credential — if every route fails this way you receive a generic502, never the provider’s raw401), and on upstream429only if the operator opted in. Gateway-emitted terminal responses —400,401,402(budget), plain429rate limits, and a successful2xx— are never retried: a2xxis always returned as-is, and a terminal error stops the chain. - Unhealthy routes are skipped for a short while. A route that fails several times in a row enters a brief cooldown (circuit breaker) and is skipped during it, so requests go straight to the healthy alternative instead of paying the failed attempt first. If every route is cooling down, the gateway still tries the primary rather than failing outright. This is fully transparent — responses and billing are unaffected.
- Residency is honored during fallback. For an
eu_onlyclient, a fallback route whose provider sits in a non-EU region is skipped (the same way an entitlement-denied route is skipped), so failover never silently leaves your residency policy. - Billing follows the actual route. You are billed for the provider that
actually served the request; a route that failed with a
5xxrecords acost_usd = 0usage row (nothing is charged for the failed attempt). - The route is opaque. The response is byte-identical regardless of which
provider served it;
provider/modelin yourGET /gw/usagerow reflect the route that actually ran.
Route fallback is off by default and operator-configured per deployment — there is nothing for you to set in a request. If no fallback routes are configured for a slug (or fallback is disabled), the slug is served only by its primary provider, exactly as before.
The order in which routes are tried can also be tuned per client by the operator (for example, to prefer a lower-cost provider first). Like everything else about routing, this is configured on the operator side and is fully opaque to you: it changes only which provider is attempted first internally — the response stays byte-identical and no route detail is ever exposed. There is nothing to set, and no way to observe it, from the client.
Calling models: the doors
Section titled “Calling models: the doors”The doors are the way to call a model. They speak the official API
shapes, so official SDKs work against the gateway via base_url:
POST https://api.sociaro.com/v1/chat/completions # OpenAI formatPOST https://api.sociaro.com/v1/messages # Anthropic formatPOST https://api.sociaro.com/v1/images/generations # OpenAI Images formatPOST https://api.sociaro.com/v1/videos # OpenAI Videos formatGET https://api.sociaro.com/v1/videos/{id} # poll a video jobPOST https://api.sociaro.com/v1/embeddings # OpenAI Embeddings formatPOST https://api.sociaro.com/v1/reranks # rerank (query + documents)POST https://api.sociaro.com/v1/audio/speech # OpenAI TTS format (binary audio)Availability. The chat, image, video, embeddings and reranks doors are backed by the live catalog today. The
audio/speech(TTS) door is implemented but currently has no models in the catalog — it returns404until an audio model is enabled. Always checkGET /v1/modelsfor what is callable; see embeddings, reranks & audio for the contract.
Point an official SDK at the gateway and address models by their catalog slug:
from openai import OpenAIclient = OpenAI(base_url="https://api.sociaro.com/v1", api_key="gw_live_...")client.chat.completions.create(model="alibaba/qwen3.7-max", messages=[...])import anthropicclient = anthropic.Anthropic(base_url="https://api.sociaro.com", api_key="gw_live_...")client.messages.create(model="anthropic/claude-sonnet-4-6", max_tokens=1024, messages=[...])from openai import OpenAIclient = OpenAI(base_url="https://api.sociaro.com/v1", api_key="gw_live_...")client.embeddings.create(model="alibaba/text-embedding-v4", input="hello world")The gateway resolves the slug, rewrites only the model field to the
provider-native id, and routes to wherever inference runs — the rest of your
request and the entire response (including SSE streams, passed through
unbuffered) are untouched. There is no format translation: an
Anthropic-format-only model sent to /v1/chat/completions gets a 400
pointing you to /v1/messages (or the sociaro SDK, which handles both
formats and fallback chains). The doors accept catalog slugs only — a bare
model name (gpt-4o) is a 400, a slug not in the catalog a 404.
Parameters: send whatever the model accepts. Because only model is
rewritten, every other request field passes through unchanged — standard
chat parameters (temperature, max_tokens, top_p, stop, tools,
tool_choice, response_format, stream, seed, logit_bias, …) and any
provider-specific extension. The gateway does not validate, add, or strip them;
the provider is the source of truth for which parameters a given model
supports. So the parameter reference for any model is its provider’s own API
docs (OpenAI, Anthropic, DashScope, …) — call it through the matching door and
your existing request bodies work as-is.
Image and video generation in OpenAI’s API shapes — including the one deliberate exception to “no format translation” (the video door translates bodies to the providers’ native create/poll forms) — is covered in media doors.
Multimodal inputs (vision, audio)
Section titled “Multimodal inputs (vision, audio)”Because the chat/messages doors rewrite only the top-level model field and
forward the rest of the body byte-for-byte, any input shape the model accepts
works unchanged — you do not need a special endpoint for vision or audio. Send
the provider’s native content blocks against a slug whose model supports them
(GET /v1/models lists the catalog; vision/omni examples below are Alibaba Qwen
slugs).
Vision (image input), OpenAI shape — /v1/chat/completions:
from openai import OpenAIclient = OpenAI(base_url="https://api.sociaro.com/v1", api_key="gw_live_...")client.chat.completions.create( model="alibaba/qwen3-vl-8b-instruct", # a vision-capable slug messages=[{"role": "user", "content": [ {"type": "text", "text": "What is in this image?"}, {"type": "image_url", "image_url": {"url": "https://example.com/cat.png"}}, ]}],)Vision, Anthropic shape — /v1/messages: use Anthropic’s content blocks
({"type": "image", "source": {"type": "url", "url": …}} or a base64 source)
against an Anthropic vision slug. Same rule — the door forwards the blocks as-is.
Audio input (omni): models of the Qwen-omni family accept OpenAI
input_audio content parts; pass them through the same chat door:
client.chat.completions.create( model="alibaba/qwen3-omni-flash", # an omni (audio-in) slug messages=[{"role": "user", "content": [ {"type": "text", "text": "Transcribe and summarize this clip."}, {"type": "input_audio", "input_audio": {"data": "<base64-audio>", "format": "wav"}}, ]}],)The gateway neither validates nor reshapes these content blocks — if the model doesn’t support a modality, the provider returns the error. Speech synthesis (TTS) and speech-to-text are separate doors/flows — see embeddings, reranks & audio.
Gateway-added response headers
Section titled “Gateway-added response headers”| Header | Meaning |
|---|---|
X-Gateway-Request-Id | Unique ID (ULID) for every request. Include it when contacting support — it links directly to logs and usage records. |
X-AI-Generated: true | On successful (2xx) responses of LLM providers where the operator enabled the EU AI Act Art. 50 disclosure helper — see eu-compliance. |
Errors the gateway returns itself
Section titled “Errors the gateway returns itself”Before forwarding, the gateway enforces auth, entitlements, rate limits and
budgets — see the error contract for the full table
(401, 403, 429, 402, 502/504).
Attribution
Section titled “Attribution”Tag any request with metadata for cost allocation; tags become dimensions in
GET /gw/stats:
- Canonical headers (configured per deployment):
X-Project,X-Department,X-Persona, … - Arbitrary tags: any
X-Attr-<name>header, e.g.X-Attr-Team: growth,X-Attr-Feature: chat— stored under the lowercased<name>.
curl https://api.sociaro.com/v1/chat/completions \ -H "Authorization: Bearer gw_live_..." \ -H "X-Project: alpha" \ -H "X-Attr-Feature: onboarding" \ -d '{"model": "alibaba/qwen3.7-max", ...}'Then:
curl "https://api.sociaro.com/gw/stats?group_by=feature&since=7d" \ -H "Authorization: Bearer gw_live_..."Long-running media jobs
Section titled “Long-running media jobs”Video generation — and some image models — run an asynchronous create→poll
lifecycle with its own billing semantics, whether you go through the
media doors or the native prefixes below — see
async jobs. (The POST /v1/images/generations door stays
synchronous — one request, one response; 3d is not in the live catalog yet.)
Advanced: native vendor prefixes
Section titled “Advanced: native vendor prefixes”Besides the doors, a vendor’s native API is exposed under a path prefix, with full byte-transparency:
<METHOD> https://api.sociaro.com/<vendor>/<vendor-native-path>The first path segment selects the vendor’s API; everything after it is the vendor’s own API path, forwarded verbatim. Use this when you need a vendor endpoint the doors don’t cover, or byte-exact pass-through of a vendor-specific API.
| Vendor | Prefix | Auth header | Upstream API |
|---|---|---|---|
| OpenAI | /openai | Authorization: Bearer | api.openai.com |
| Anthropic | /anthropic | x-api-key | api.anthropic.com |
| Alibaba (DashScope) | /alibaba | Authorization: Bearer | DashScope |
(The exact set of native prefixes for your organization may differ — GET /gw/me
shows what your key is entitled to.)
On native paths you address models by their vendor-native id
(gpt-4o, claude-sonnet-4-6, qwen3.7-max-2026-06-08), not the catalog
slug — this is the snapshot the catalog stores in provider_model for the
slug. The same model, called both ways:
# Via the door — catalog slug, provider resolved for you:curl https://api.sociaro.com/v1/chat/completions \ -H "Authorization: Bearer gw_live_..." \ -d '{"model": "alibaba/qwen3.7-max", "messages": [...]}'
# Via the native prefix — vendor API chosen explicitly, vendor-native id, body verbatim:curl https://api.sociaro.com/alibaba/compatible-mode/v1/chat/completions \ -H "Authorization: Bearer gw_live_..." \ -d '{"model": "qwen3.7-max-2026-06-08", "messages": [...]}'One deliberate escape hatch lives here: POST /openai/v1/images/edits — the
doors do not accept multipart uploads (media doors), so image
editing goes through the native prefix. Basic image-to-video is supported by
the /v1/videos door via input_reference for i2v-capable slugs (e.g.
alibaba/wan2.6-i2v, alibaba/wan2.7-i2v) — see
media doors. What the door does
not reach are the image-conditioned Wan 2.2 models
(alibaba/wan2.2-kf2v-flash, alibaba/wan2.2-animate-move,
alibaba/wan2.2-animate-mix) and first+last-frame / multi-reference inputs;
those are served only over the native prefix
(/alibaba/api/v1/services/aigc/image2video/video-synthesis). Their cost is metered exactly like
any other per-second video job; the gateway’s billing does not depend on whether
a job is created through a media door or a native prefix.
Transparency guarantees
Section titled “Transparency guarantees”- Request and response bodies are never modified — what the provider sends is what you receive, byte-for-byte.
- SSE streaming is passed through unbuffered; time-to-first-token is the provider’s own.
- Provider errors (4xx/5xx) are forwarded as-is — your provider-specific error handling keeps working.
- The only header the gateway touches is the provider auth header (replaced
with the real credential).
traceparentand all other headers pass through.
Entitlements on native paths
Section titled “Entitlements on native paths”Model entitlements apply to native
traffic exactly as to door traffic — including vendor-axis rules: the
gateway reverse-resolves the (provider, native model) pair to its catalog
slug, so a vendor rule follows the model whichever way you call it. A model
the catalog does not know cannot be matched by vendor rules — only
provider-axis rules can grant it.