AI Gateway Endpoints
Every route is served from https://ai.varity.app. The full machine-readable
schema is public, needs no key, and is the source for anything this page leaves
out:
curl https://ai.varity.app/v1/openapi.jsonReplace <… model id> in the examples with an id from
GET /v1/models whose capabilities fit the route. For
example, output_modalities containing embedding for embeddings, image for
images, capabilities.speech for speech, and capabilities.transcription for
transcription.
https://ai.varity.app is the canonical AI Gateway host. https://varity.app/v1
is a compatibility alias that the edge routes to the same service, so existing
clients keep working; use https://ai.varity.app/v1 in new code.
Discovery
Section titled “Discovery”GET /v1/models
Section titled “GET /v1/models”The live catalog. Public, no key.
curl https://ai.varity.app/v1/modelsGET /v1/openapi.json
Section titled “GET /v1/openapi.json”The contract for this surface, including its commercial and data-handling terms. Public, no key.
Inference
Section titled “Inference”All inference routes take an inference key as Authorization: Bearer … and a
JSON body. Varity has no total response-time limit: without an
X-Varity-Deadline-Ms header a request runs until the model finishes or the
client disconnects. A provider that sends nothing for 300 seconds fails the
request 504 upstream_timeout (every chat request except a web_search one,
whose answer the provider returns only whole).
POST /v1/chat/completions
Section titled “POST /v1/chat/completions”curl https://ai.varity.app/v1/chat/completions \ -H "Authorization: Bearer $VARITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "glm-5-2", "messages": [{ "role": "user", "content": "Say hello in one sentence." }] }'Required: model, messages. Optional fields include stream,
max_completion_tokens, temperature, top_p, stop, seed,
response_format, reasoning_effort, tools, tool_choice, and
parallel_tool_calls. Each works only on models whose capabilities advertise
it.
A message’s content can be an array of parts: text, image_url (an https URL
or a base64 data: URL), and document ({ "url": …, "filename": … }), on
models whose capabilities.input_modalities include image or document.
Varity-specific options go in varity_extensions:
| Field | Effect |
|---|---|
web_search | Ground the answer in a live web search, on models with capabilities.web_search. |
web_scraping | Read up to 5 pages linked from the latest user message. |
privacy_floor | Tighten, never loosen, the account privacy floor for this request. |
Two optional headers:
| Header | Effect |
|---|---|
Idempotency-Key | Send the same key when retrying. Reuse returns 409 duplicate_request instead of charging twice. |
X-Varity-Deadline-Ms | Optional absolute Unix-epoch deadline in milliseconds, chosen by the caller. With it, a request still running at that instant ends 504 deadline_exceeded. A malformed or already-past value is refused 400 invalid_request before any provider effect or charge. |
Streaming is covered on the overview.
POST /v1/embeddings
Section titled “POST /v1/embeddings”curl https://ai.varity.app/v1/embeddings \ -H "Authorization: Bearer $VARITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "<embedding model id>", "input": "The quick brown fox." }'input is a string or an array of up to 2,048 strings. Optional:
encoding_format (float or base64) and dimensions.
POST /v1/images/generations
Section titled “POST /v1/images/generations”curl https://ai.varity.app/v1/images/generations \ -H "Authorization: Bearer $VARITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "<image model id>", "prompt": "A red cube on a table" }'Optional: size and n. Images come back inline as base64 in
data[].b64_json with a mime_type, and Varity never stores them.
POST /v1/images/edits
Section titled “POST /v1/images/edits”The OpenAI SDK’s images.edit upload (multipart/form-data, file fields
image or image[] and optional mask) works unchanged. A JSON body with the
image as base64 is also accepted:
curl https://ai.varity.app/v1/images/edits \ -H "Authorization: Bearer $VARITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "<image model id>", "prompt": "Make the sky orange.", "image": { "data": "<base64 bytes>", "mime_type": "image/png" } }'image.mime_type is one of image/png, image/jpeg, or image/webp. An
optional mask takes the same { data, mime_type } shape, and size is
optional.
POST /v1/audio/speech
Section titled “POST /v1/audio/speech”curl https://ai.varity.app/v1/audio/speech \ -H "Authorization: Bearer $VARITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "<speech model id>", "input": "Hello from Varity.", "response_format": "mp3" }' \ --output hello.mp3response_format must be one of the model’s capabilities.speech_formats.
Optional: voice, speed, language, prompt, and stream. The response is
audio bytes, not JSON.
POST /v1/audio/transcriptions
Section titled “POST /v1/audio/transcriptions”The OpenAI SDK’s audio.transcriptions upload (multipart/form-data, file field
file) works unchanged. A JSON body with the audio as base64 is also accepted:
curl https://ai.varity.app/v1/audio/transcriptions \ -H "Authorization: Bearer $VARITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "<transcription model id>", "audio": { "data": "<base64 bytes>", "media_type": "audio/mpeg" } }'audio.media_type is one of audio/wav, audio/wave, audio/x-wav,
audio/flac, audio/x-flac, audio/mp4, audio/m4a, audio/x-m4a,
audio/aac, audio/mpeg, audio/ogg, audio/oga, or audio/webm, and the
decoded audio must be under 25 MB. Optional: audio.filename,
response_format (json or text), language, and timestamps.
Your Account, With An Inference Key
Section titled “Your Account, With An Inference Key”curl https://ai.varity.app/v1/inference/policy \ -H "Authorization: Bearer $VARITY_API_KEY"These routes take an inference key, so your own code can read its policy and what it has spent:
| Route | Returns |
|---|---|
GET /v1/inference/policy | Your privacy floor and rate limits. |
GET /v1/inference/usage | Requests, tokens, and spend_usd from inference key requests for the current period, with breakdowns. Chat and Build requests are not included. |
GET /v1/inference/requests | Per-request metadata. Rows for Chat and Build requests carry customer_charge and usage as null. Filters: limit (1 to 100), cursor, model, state, created_after, created_before. The two timestamps are RFC 3339; send them with fractional seconds, for example 2026-09-16T00:00:00.000Z. |
GET /v1/inference/performance | Latency percentiles. window is 1h, 24h, 7d, or 30d. |
Your Account, With A Portal Session
Section titled “Your Account, With A Portal Session”Keys, billing, and the privacy setting are managed from the Developer Portal.
The /v1/keys*, /v1/billing/*, and PUT /v1/inference/policy routes refuse an
inference key. They are Developer Portal session operations and are not in
GET /v1/openapi.json. Each is described on
Billing and Keys.
Health
Section titled “Health”curl https://ai.varity.app/healthzcurl https://ai.varity.app/readyzPublic, no key, outside /v1.
{ "status": "ok", "service": "varity-ai-gateway", "version": "<deployed build>", "source_commit": "<commit>" }/readyz returns the same fields with status: "ready", plus model counts
(servable, servable_by_vertical, published, minimum_servable) and a
components object. version reports the deployed gateway build; re-probe
for the current one rather than pinning it in your own config.
Next Steps
Section titled “Next Steps”- Compatibility: what the OpenAI surface includes and excludes, and every error code
- Rate Limits: request budgets and body-size ceilings