API Reference
Version: 3.20.3 | Last Updated: 2026-09-04
Current Gemini Flash models (2026-09-03):
gemini-3.8-flashis the latest stable Flash model published by API429.gemini-3.7-flashremains supported. The release notes below describe past releases, not the access granted to an individual token.Check access with the same key and endpoint: the website's public catalog is platform-wide;
GET /v1/modelsis filtered for the token used in that request and the currently available serving routes. An older token can have an explicit model allowlist that does not automatically gain new models. Absence from the token's catalog is not, by itself, a reason to upgrade your plan. Ask support to review the token's model permissions, then refresh the catalog.If a listed model returns
not supported: retry the catalog check with the exact same token and base URL used for generation, and use the exact canonical model ID. The current error can also mean the token's allowlist excludes the model. Send support the model ID, endpoint, request time andtrace_id(or only the token's last four characters), never the full token. Do not keep retrying a fixed access restriction or assume a plan change will resolve it.What's new in 3.20.3
- Gemini 3.5 Flash serving route: on 2026-09-03 the upstream that served the
gemini-3.5-flash-low/-medium/-higheffort variants retired Gemini 3.5 Flash and began answering with a text notice instead of an error.gemini-3.5-flashis now served on Google's own transports only, and the three effort IDs remain accepted as compatibility aliases ofgemini-3.5-flashat the same price. The suffix no longer changes the reasoning budget — passthinking_level(low/medium/high) ongemini-3.5-flashinstead.gemini-3.5-flash-lowis no longer listed inGET /v1/models.- Retirement notices are errors: a provider reply whose only content is a "model is no longer available" notice is treated as a failed attempt — it is retried on the next serving route and is never billed.
What's new in 3.20.2
- Music access for customers: new active
external_customertokens receive both asyncvideoandaudioscopes by default. Existing customer and project tokens are upgraded only while they retain API429's managed policy.- Explicit restrictions stay explicit: test, internal, admin, unclassified, and manually configured policies are unchanged. Restricted model allowlists must include
lyria-3-pro-previewbefore the token can generate music.What's new in 3.20.0
- Lyria 3 Pro music generation: added
lyria-3-pro-previewthrough the durable asyncPOST /v1/music/generationsAPI.- Songs and instrumentals: prompts may request genre, mood, arrangement and structure; optionally provide lyrics or request instrumental-only output. The result is an MP3 delivered by HTTPS URL.
- Safe paid requests:
Idempotency-Keyis mandatory, jobs are never automatically replayed after an uncertain upstream outcome, and each completed song costs $0.08.What's new in 3.19.0
- Gemini 3.8 Flash GA: added the exact canonical model ID
gemini-3.8-flash, generally available since 2026-09-02. API429 exposes it through both client-token and Service Account authentication.- Context and reasoning contract: 1,048,576-token input window, 65,536-token output limit, and
low/medium/highreasoning effort withmediumas the default.- Canonical-only requests: do not append
-non-thinkingor effort suffixes to the model ID. Customtemperature,top_p,top_k, andn/ nativecandidateCountare unsupported.- Strict request validation: generation must end with a non-empty user text turn; model-prefill turns are rejected. Native
FunctionResponseparts require both a call ID and function name.- Promotional pricing: $0.75 input, $0.075 cached input, and $3.75 output (including thought tokens) per 1M tokens through 2026-12-31. The 2027 rates double to $1.50 / $0.15 / $7.50 and require a pricing update before 2027-01-01.
What's new in 3.18.0
- Gemini Omni 1.1 Flash: use the stable client model ID
gemini-omni-1.1-flash. The retiredgemini-omni-flash-previewand shortgemini-omni-flashspellings remain input-only compatibility aliases.- New Omni controls: added
360p,1080p, and4kalongside720p, first/last-frame interpolation, and source-video extension.- Resolution-aware video billing: Omni reservations and usage fallback use Google's published token rate for the requested resolution; native provider usage remains authoritative when returned.
- Safe video access default: active external-customer tokens receive only the async
videoscope by default. Text, image, and audio async scopes remain explicit admin opt-ins.- Native TTS billing parity: Gemini
generateContentspeech requests now use the same character-based balance preflight and single successful-request charge as/v1/audio/speech, including multi-speaker requests.What's new in 3.17.0
- Gemini TTS contract corrected:
gemini-3.1-flash-tts-previewis the current Gemini speech model on both API429 TTS surfaces. Cloud TTS model IDs are no longer presented as GeminigenerateContentmodels.- Round-trip-safe media: standard and URL-safe base64 inputs are accepted; gateway output is canonical padded standard base64.
- Image response contract:
response_format:"url"always returnsurl(with a data-URI fallback), Google MIME/person controls use a Vertex-backed credential, and the actual returned MIME is preserved.- Resolution billing clarified: exact Gemini Flash and Pro prices are listed for 1K, 2K, and 4K, including standard API429 discounted amounts.
What's new in 3.16.0
- Branded endpoint: the API is now published at
https://gateway.api429.com. The previous address keeps working; no migration required.What's new in 3.15.0
- nobalancerapi catalogue: a separate set of image, editing and video models enabled per account rather than served by default — Midjourney, FLUX.1, Qwen Images, Sora Images, DALL·E 3, clothing replacement, and video (Veo, Kling, Pika, face replacement, upscale). Pricing on request.
- Midjourney batches: a generation returns all 4 images of the job by default (you are billed per job, not per returned image); pass
nexplicitly to receive fewer. Request-levelsize/aspect_ratioare ignored — use--arinsideprompt.- Midjourney modifications: every generated image returns an
id; pass it assource_image_idwithmj-upscale,mj-upscale-creative,mj-outpaint-*,mj-variations-subtle,mj-variations-strongormj-remixto act on that image.What's new in 3.14.0
- Fish Audio TTS: new
fish-s2.1-proonPOST /v1/audio/speech— 80+ languages, a large public voice library, $0.015 / 1K chars official ($0.0045 after the standard 70% discount).- Output formats:
fish-s2.1-prohonoursresponse_format—mp3(default),wav,pcm,opus. Usewavwhen the consumer requires RIFF/WAVE.- Long-form narration: long input is split on sentence boundaries, synthesised in parallel and returned as one joined clip. An hour of speech takes roughly three minutes;
opuscannot be joined and returns400for long input.- Link delivery: send
"delivery": "url"on/v1/audio/speechto get a JSON descriptor with a CDN link instead of the audio bytes. Omit it and the raw-bytes response is unchanged.What's new in 3.13.0
- Grok 4.6: added the exact canonical xAI model id
grok-4.6after production probes confirmed text, vision, reasoning, function calling, structured output, Chat Completions, and Responses API.- Reasoning:
reasoning_effortacceptslow,medium,high, orxhigh; omit it for xAI'shighdefault. Reasoning cannot be disabled.- Exact usage and billing: cached input and reasoning tokens are preserved and charged once. Official Standard rates are $2 input / $0.50 cached input / $6 output per 1M below 200K input tokens, and $4 / $1 / $12 from 200K input tokens onward, before API429 discounts.
- Fail-closed tools: local function tools are supported. Separately billed xAI web, X, and code-execution tools are not exposed until per-call metering is available.
What's new in 3.12.0
- Gemini 3.7 Flash: added the stable
gemini-3.7-flashmodel, with a 1,048,576-token input window, 65,536-token output limit, multimodal input and text output. For the latest published Flash model, see the current-model note above.- Verified availability: production validation confirmed the canonical ID. API429 publishes only
gemini-3.7-flash; provider-specific effort suffixes are not part of the public API.- Current promotional pricing: $0.75 input, $0.075 cached input and $3.75 output per 1M tokens through 2026-12-31. Google has announced $1.50 / $0.15 / $7.50 starting 2027-01-01.
- Compatibility controls: OpenAI clients may send
temperature,top_p,top_kandthinking_budget; API429 removes those unsupported controls before dispatch. Usethinking_levelorreasoning_effortwithlow,medium, orhigh(default:medium).What's new in 3.11.0
- Nano Banana Pro is GA: use canonical ID
gemini-3-pro-image. The retiredgemini-3-pro-image-previewID and friendly namesnano-banana-pro/nana-bana-proremain accepted as compatibility aliases and are rewritten before the Google request.- Model catalogue re-audited: every
Available Modelstable (text, GPT, Claude, image, video, TTS) was verified against live pricing; no other IDs or prices changed.What's new in 3.10.0
- Single ElevenLabs model: the ElevenLabs family is now one canonical model,
elevenlabs-gen, listed inGET /v1/modelsat $0.100 / 1K chars official ($0.030 after the standard 70% discount). It is served by three interchangeable backends tried in order until one returns audio, and you are always billed at theelevenlabs-genrate no matter which backend served the request.- Legacy ids still accepted:
eleven_v3,eleven_multilingual_v2,eleven_flash_v2_5, andapi429-ttskeep routing for backward compatibility but are no longer advertised in the catalogue; new integrations should useelevenlabs-gen.What's new in 3.9.0
- Claude Opus 5 and Claude Fable 5:
claude-opus-5andclaude-fable-5are available for Claude chat workloads. Both are listed in the Claude pricing table below and served through the standard Claude provider chain.- ElevenLabs standby: every ElevenLabs model now has a primary backend and an automatic standby. If the primary is unavailable the request is retried transparently, and you are billed for the model you asked for either way.
- Generic ElevenLabs alias:
api429-ttsrequests ElevenLabs speech without pinning a specific model; it resolves to the current default (eleven_multilingual_v2).- Gemini TTS correction: the earlier multi-model rollout was superseded. The current Gemini TTS model on
/v1/audio/speechand the Gemini-native gateway isgemini-3.1-flash-tts-preview.- Content filter: TTS input rejected by the speech provider's content filter now returns
422naming how many fragments were blocked, instead of a generic failure.- Fixed reasoning-effort Gemini variants:
gemini-3.5-flash-lowandgemini-3.1-pro-loware documented and billed at their base model's rate.- Catalogue cleanup:
GET /v1/modelsno longer advertises IDs it cannot serve — internal route twins, a disabled provider's aliases, vendor-prefixed catalogue keys, and reasoning variants that do not resolve upstream. These IDs already returned an error when called; listing them was the bug. Request routing itself is unchanged, so nothing that worked before has stopped working. If you pinned one of the removed IDs, switch to the documented equivalent: use the clean alias (gemini-2.0-flash, not a vendor-prefixed form), the base Claude model instead of accw-twin, andgemini-3.5-flashorgemini-3.1-pro-previewinstead of a-high/-mediumvariant.What's new in 3.8.0
- ElevenLabs TTS: added
eleven_v3,eleven_multilingual_v2, andeleven_flash_v2_5on the OpenAI-compatiblePOST /v1/audio/speechendpoint.- Native voices: pass an ElevenLabs
voice_idthrough the standardvoicefield; the requested ElevenLabs model is preserved end to end.- Transparent pricing: the catalogue shows the official ElevenLabs character price and the standard API429 price after the 70% discount.
What's new in 3.7.0
- Gemini Omni Flash video: added native
gemini-omni-flash-previewgeneration through the async/v1/videos/generationsAPI. The accepted compatibility alias isgemini-omni-flash.- Multimodal video workflows: text-to-video, image-to-video, reference-to-video, source-video editing, and stateful follow-up editing with
previous_job_idare supported.- Usage and billing: completed Omni jobs expose native input/output/thought token usage when Google provides it, and billing settles the initial reservation to official Agent Platform usage.
- Model integrity: Omni requests are not silently routed to Veo or another video model. Check
GET /v1/modelsfor availability on your token.What's new in 3.6.0
- GPT-5.6 family: added
gpt-5.6(alias ofgpt-5.6-sol),gpt-5.6-sol, andgpt-5.6-terrafor Chat Completions and Responses API.- Reasoning: GPT-5.6 supports
none,low,medium,high,xhigh, andmax; the default ismedium.- Usage and billing: cache-read/cache-write usage is preserved, streaming requests are billed from the final usage event, and requests above 272K input tokens use the published long-context rates.
- Availability:
gpt-5.6-lunais not yet listed because it is not currently available through the gateway. CheckGET /v1/modelsfor the authoritative per-token catalogue.What's new in 3.5.10
- Nano Banana 2 Lite (
gemini-3.1-flash-lite-image/nano-banana-2-lite) is now available onPOST /v1/images/generations.- Pricing: Lite image generation is billed at $0.0336 per 1K output image; batch image jobs use the $0.0168 batch unit.
- Routing: the public alias resolves to the Google/Vertex native image model ID before provider selection.
What's new in 3.5.9
- Claude Sonnet 5 (
claude-sonnet-5/claude-sonnet-5.0) is now available for Claude chat workloads through the standard Claude provider chain.- Pricing and context: Sonnet 5 is listed at $2 input / $10 output per 1M tokens during the current launch pricing window and supports a 1M-token context window.
- Availability note: Sonnet 5 is available through the gateway's current Claude routes; provider-specific route details are intentionally not part of the public contract.
What's new in 3.5.8
- Anthropic-compatible Messages API: documented
POST /v1/messagesfor Claude clients that already use the official Anthropic Messages API shape. Usex-api-keyauth and the same API429 client token.- Claude usage transparency: clarified
usage.input_tokens/usage.output_tokenson native Messages responses andprompt_tokens/completion_tokenson OpenAI-compatible responses.- Claude native streaming: documented Anthropic SSE event order for
stream:trueon/v1/messages.- Claude cache and web search notes: documented the current public contract for prompt-cache usage fields and Anthropic server-tool passthrough.
What's new in 3.5.7
- Grok models: added xAI Grok text models —
x-ai/grok-4,x-ai/grok-4-reasoning,x-ai/grok-3,x-ai/grok-3-reasoning— on the standardPOST /v1/chat/completionsendpoint.- Extended text catalogue: additional vendor-prefixed chat IDs are now selectable —
openai/gpt-5,openai/gpt-5-instant,openai/gpt-5-thinking, andgoogle/gemini-3-pro,google/gemini-2.5-pro,google/gemini-2.5-flash.- New image models:
nano-banana-2(alias ofgemini-3.1-flash-image),flower-image,gpt-image-1, andgrok-image(xAI Aurora) added toPOST /v1/images/generations.- Confirm availability with
GET /v1/modelsusing the same token and base URL as generation. The response reflects model permissions and serving availability, not an automatic promise of access after a plan change.What's new in 3.5.6
- Gemini video input for chat: token-gated Gemini text routes now accept video input on
POST /v1/chat/completionsusing OpenAI-compatible message content parts.- Supported video input shapes:
input_videowith base64 data, and directvideo_urlinputs that the gateway stages temporarily before sending to Gemini.- Streaming support:
stream:trueworks for video-input chat requests and returns standard OpenAI-compatible SSE chunks.What's new in 3.5.5
- Veo 3.1 video generation: added async video generation docs for
veo-3.1-generate-001,veo-3.1-fast-generate-001, andveo-3.1-lite-generate-001.- Native migration paths: clients can use the API429/OpenAI-style
/v1/videos/generationsroute or Vertex-compatiblepredictLongRunning/fetchPredictOperationroutes by changing only the base URL and token.- Video billing: documented per-second Veo 3.1 list prices and async polling behavior.
What's new in 3.5.4
- Gemini 3.5 Flash (
gemini-3.5-flash) is now part of the public Gemini text catalogue. It supports chat, streaming, multimodal input, function/tools, structured output, search grounding, code execution and thinking. Output is text only.- Pricing:
gemini-3.5-flashis billed at the Google Standard PayGo Global text rate: $1.50 input / $9.00 output per 1M tokens. Image generation, TTS and embeddings use their own model IDs.What's new in 3.5.3
- Self-contained client docs: removed links to separate
.mdguides that are not served publicly. GPT Image 2, Claude, TTS, embeddings and multimodal examples now live in this API Reference.- Claude public contract cleanup: public docs list only canonical Claude model IDs (
claude-*). Internal routing/fallback model IDs are intentionally not documented for client integrations.- Client troubleshooting cookbook: added concrete guidance for SSE parsing, image edits/reference images, 429/503 retries, unsupported fields and endpoint/model mismatches.
What's new in 3.5.2
- Public model catalogue audit: the GPT and Gemini tables now match the current client-visible
/v1/modelscatalogue. Unsupported legacy GPT/Codex IDs and the allowlist-gated Gemini custom-tools preview are no longer advertised as public model IDs.- Canonical IDs clarified: use the exact model IDs in these tables for new integrations.
GET /v1/modelsremains the authoritative per-token allowlist.What's new in 3.5.1
- GPT Image 2 client guide: clarified how to call
gpt-image-2through API429 Images endpoints and how billing is calculated from text input, image input and image output.- GPT Image 2 pricing refresh: updated API429 billing notes to match OpenAI's current GPT-Image-2 token rates and official per-image calculator examples.
What's new in 3.5.0
- Claude catalogue refresh: all public Anthropic/Claude text models are listed with canonical model IDs, accepted aliases, context windows and API429 list prices.
- Claude integration guide cleanup: public docs now describe only the client-facing API contract (
/v1/chat/completions, streaming and jobs).What's new in 3.4.0
- GPT Image 2:
model:"gpt-image-2"on/v1/images/generationsand/v1/images/editsis documented as a dedicated GPT Image path, not a Gemini image alias.- GPT Image edits/reference images:
/v1/images/editsand Responsesimage_generationguidance now coversinput_image, masks, supported output options, concrete GPT Image 2 pricing, and client-visible retry/error behavior.What's new in 3.3.0
- Claude streaming updates for plain
stream:truechat requests. Text deltas stream through OpenAI-compatible SSE.stream:true + toolsremains synthetic SSE.What's new in 3.2.0
- Claude long-gen optional headers for batch screenwriter / multi-turn workflows:
X-Session-Keyfor conversation continuity andX-Async-Jobs-Optin: truefor durable jobs on overload. See "Optional headers" under Claude Models below.What's new in 3.1.0
- Claude Sonnet 4.5 (
claude-sonnet-4-5/claude-sonnet-4.5) — same pricing as 4.6 ($3 / $15 per 1M), 200k context, Extended Thinking enabled.- GPT-5.5 (
gpt-5.5) — frontier model from OpenAI, $5 / $30 per 1M.- Gemini 3.1 TTS preview (
gemini-3.1-flash-tts-preview) — the current Gemini speech model on API429.OpenAI-compatible gateway for chat, image, text-to-speech and embedding models across the Gemini, GPT and Claude families, plus native-compatible Gemini and Anthropic entry points for clients that already use those SDKs. Supports both Chat Completions and Responses API formats. Works with any OpenAI SDK client (Python, JS, Go, Rust, Ruby, Java, cURL).
Quick Start
Base URL: https://gateway.api429.com/v1
Auth: Authorization: Bearer YOUR_API_KEY
The previous address
https://hostkey24760.api429.comcontinues to work; existing integrations do not need to change anything. New integrations should usehttps://gateway.api429.com.
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY"
)
response = client.chat.completions.create(
model="gemini-3.1-pro",
messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
Table of Contents
- Endpoints & Auth Matrix
- Authentication
- Text Models (Chat Completions)
- Responses API
- GPT Models
- Grok & Extended Catalogue
- Claude Models
- Image Generation Models
- Embeddings
- Video Generation Models
- Text-to-Speech
- Integration Cookbook
- Files API
- Client Usage & Balance
- Error Handling
- Rate Limits
- Supported SDK Clients
Endpoints & Auth Matrix
The same base host (https://gateway.api429.com) serves four API families.
Pick the one that matches your SDK.
| API family | Paths | Auth |
|---|---|---|
| OpenAI-compatible | /v1/*, /hf/v1/*, /openai/v1/* — models, chat/completions, responses, images/generations, embeddings, audio/speech |
Authorization: Bearer <token> |
| Anthropic-compatible | POST /v1/messages — Claude Messages API request/response shape, including Anthropic-style SSE streaming |
x-api-key: <token> |
| Gemini native | /v1beta/models/{model}:generateContent, :streamGenerateContent, :countTokens, :embedContent, :batchEmbedContents (also under /gemini/v1beta/*) |
x-goog-api-key: <token> or ?key=<token> |
| Vertex Express | /vertex-express/v1beta/models/{model}:generateContent, :streamGenerateContent, GET /vertex-express/v1beta/models |
x-goog-api-key: <token> or ?key=<token> |
| Video generation | /v1/videos/generations, /v1/videos/generations/{job_id}, Vertex-compatible :predictLongRunning / :fetchPredictOperation |
Bearer token for /v1/videos/*; x-goog-api-key, ?key=, or Bearer token for Vertex-compatible routes |
| Files API | POST /upload/v1beta/files, GET/DELETE /v1beta/files[/…] (plus /gemini/ variants) |
x-goog-api-key: <token> or ?key=<token> |
| Client usage | GET /api/client/balance, GET /api/client/usage/daily, GET /api/client/usage/summary, POST /api/client/usage/daily/telegram |
Authorization: Bearer <token> |
Streaming endpoints return text/event-stream (SSE). Error payloads are normalised
as {"error": {"code": ..., "message": ...}}.
Authentication
All OpenAI-compatible and client-usage endpoints require a Bearer token:
Authorization: Bearer YOUR_API_KEY
Anthropic-compatible /v1/messages accepts the same API429 client token in
Anthropic's standard header:
x-api-key: YOUR_API_KEY
anthropic-version is accepted for SDK compatibility. The gateway does not
require clients to pin a specific version.
Gemini-native, Vertex Express, and Files API endpoints accept the Google-style header or query parameter:
x-goog-api-key: YOUR_API_KEY
GET /v1beta/models?key=YOUR_API_KEY
Tokens are issued by the admin panel. Contact your administrator for access.
Service Account (SA) authentication is also supported for Google Vertex AI SDK clients. See the dedicated Service Account Guide tab for setup instructions and examples.
Text Models (Chat Completions)
Available Models
| Model | Status | Input $/1M tokens | Output $/1M tokens | Capabilities |
|---|---|---|---|---|
gemini-3.8-flash |
Stable | $0.75 | $3.75 | chat, vision/multimodal input, thinking, JSON/schema, URL context, countTokens |
gemini-3.7-flash |
Stable | $0.75 | $3.75 | chat, multimodal input, thinking, JSON/schema, URL context |
gemini-2.5-flash-lite |
Stable | $0.10 | $0.40 | chat |
gemini-2.5-flash |
Stable | $0.30 | $2.50 | chat, search |
gemini-2.5-pro |
Stable | $1.25 | $10.00 | chat, thinking, search |
gemini-3.5-flash |
Stable | $1.50 | $9.00 | chat, multimodal input, thinking, search, tools, JSON/schema |
gemini-3-flash-preview |
Preview | $0.50 | $3.00 | chat, thinking, search |
gemini-3.1-flash-lite-preview |
Preview | $0.25 | $1.50 | chat |
gemini-3.1-pro-preview |
Preview | $2.00 | $12.00 | chat, thinking, search, vision |
Gemini 3.8 Flash is GA. The exact public ID is
gemini-3.8-flash; do not append-non-thinking,-low,-medium,-high, or another effort suffix. It has a 1,048,576-token input window and a 65,536-token output limit. Selectlow,medium, orhighwiththinking_levelorreasoning_effort; the default ismedium. API429 serves the request through a managed provider chain with Google/Vertex fallback. Provider-specific model IDs are mapped internally and are not part of the public API. In Chat/Responses, tools are not supported by API429's adapter for this model. Unsupported Responses tools (includingweb_search_preview,web_search, andfile_search) return HTTP 400; they are never silently treated as text-only requests. Use native Gemini for supported function declarations and URL context.
Gemini 3.8 pricing window. The table shows the promotion through 2026-12-31. Cached input is $0.075/1M, and the $3.75 output rate includes thought tokens. On 2027-01-01 all three rates double to $1.50 input, $0.15 cached input, and $7.50 output; pricing must be updated before then.
Gemini 3.8 request controls. Custom
temperature,top_p,top_k, andn/ nativecandidateCountare not supported. Omit them rather than relying on a provider default.frequency_penaltyandpresence_penaltyremain valid.
Gemini 3.8 tool turns. The OpenAI-compatible route rejects
tools,tool_choice, assistanttool_calls, androle:"tool"messages for this model. Use the native Gemini route when function calling is required. Native requests support client-executedfunctionDeclarationsandurlContext. Search, Maps, File Search, computer use, and code execution are not part of the current API429 contract for this model.
Gemini 3.8 turn validation.
generateContentand OpenAI-compatible chat requests must end with a user turn containing non-whitespace text; assistant or model prefill is rejected. NativeFunctionResponseobjects must include both a call identifier (call_idor RESTid) andname.countTokensaccepts chat history independently and counts the supplied system instruction and function declarations as well as message contents.
Gemini 3.7 Flash remains GA. It supports text, image, video, audio and PDF input and returns text. API429 exposes exactly the canonical
gemini-3.7-flashID; do not append an effort suffix. Older Gemini 3.0/3.1 entries in this table remain preview IDs.
Gemini 3.7 pricing window. The table shows Google's current Standard promotion through 2026-12-31. Cached input is $0.075/1M. Google has announced $1.50 input, $0.15 cached input and $7.50 output starting 2027-01-01.
Gemini 3.7 request controls. Custom
temperature,top_p,top_k,n/ nativecandidateCountandthinking_budgetare not forwarded. Choose reasoning withthinking_levelor OpenAI-stylereasoning_effort:low,medium, orhigh.minimaland disabled thinking are not supported.
Gemini 3.7 tool turns. OpenAI-compatible
tools/tool_choicerequests are rejected for this model because its tool round trip requires native function-call IDs and thought signatures. Use the native Gemini route for function calling; ordinary chat, structured output and URL context remain available through the OpenAI-compatible route.
Gemini 3.5 Flash output mode.
gemini-3.5-flashaccepts text, image, audio, video and document/PDF inputs on the text chat path, but returns text. Use image models for image output, TTS models for audio output and embedding models for vector output.
Long-context pricing.
gemini-2.5-proandgemini-3.1-pro-previewswitch to a higher billing tier when the prompt exceeds 200K tokens (roughly 2× the base rate on both input and output). Prompts below 200K are billed at the rates shown above.
Model aliases (shorthand):
gemini-3.1-pro→gemini-3.1-pro-previewgemini-3-flash→gemini-3-flash-preview
Fixed reasoning-effort variants. These IDs pin the reasoning budget at request time instead of letting the model choose. They are billed at their base model's rate — the suffix changes latency and depth, not price.
| Model | Billed as | Input $/1M | Output $/1M | Notes |
|---|---|---|---|---|
gemini-3.5-flash-low |
gemini-3.5-flash |
$1.50 | $9.00 | Compatibility alias since 2026-09-04: served as gemini-3.5-flash; use thinking_level: "low" on the canonical id for the reduced budget |
gemini-3.1-pro-low |
gemini-3.1-pro-preview |
$2.00 | $12.00 | Pro quality with a reduced reasoning budget |
Higher-effort variants (-high, -medium) are not currently offered: they do
not resolve on our upstream. Request gemini-3.5-flash or
gemini-3.1-pro-preview for full reasoning, or pass thinking_level on the
base model.
Model suffixes (append to any compatible model):
-search— Enable grounded web search (e.g.gemini-3.1-pro-search)-non-thinking— Disable reasoning/thinking mode (e.g.gemini-3.1-pro-non-thinking)-image-generation— Enable inline image output on image-capable models
gemini-3.8-flash and gemini-3.7-flash are canonical-only in API429 and
reject all of these model-ID suffixes. Use thinking_level or
reasoning_effort to select a supported thinking level on either model.
Gemini Live API (advanced)
gemini-3.1-flash-live-preview is a streaming bidirectional audio model
served over Google's Live API (bidiGenerateContent). It is not reachable
via /v1/chat/completions — clients need to use the native Gemini Live
protocol. Contact your administrator if you need Live API access.
Endpoint
POST /v1/chat/completions
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
model |
string | No | gemini-2.5-flash-lite |
Model ID from the table above |
messages |
array | Yes | — | Array of message objects |
temperature |
float | No | 0.7 |
Creativity (0.0–2.0); unsupported by Gemini 3.8/3.7 |
max_tokens |
integer | No | — | Max output tokens |
stream |
boolean | No | false |
Enable streaming |
top_p |
float | No | 0.9 |
Nucleus sampling; unsupported by Gemini 3.8/3.7 |
stop |
string/array | No | — | Stop sequences |
tools |
array | No | — | Function calling tools where the selected model supports the OpenAI-compatible tool adapter; for Gemini 3.8/3.7 use native generateContent |
tool_choice |
string | No | — | auto, none, required; unavailable for Gemini 3.8/3.7 on the OpenAI-compatible route |
response_format |
object | No | — | {"type": "json_object"} or {"type": "json_schema", ...} for JSON mode |
parallel_tool_calls |
boolean | No | true |
Allow the model to emit multiple tool calls at once |
reasoning_effort |
string | No | medium |
Reasoning depth. GPT-5.6 accepts none, low, medium, high, xhigh, or max (see below). |
n |
integer | No | 1 |
Number of completions; values other than 1 are unsupported by Gemini 3.8/3.7 |
Feature coverage by model family:
| Feature | Gemini | Claude | GPT |
|---|---|---|---|
| Function calling (non-stream & stream) | ✅ except Gemini 3.8/3.7 on the OpenAI-compatible route | ✅ | ✅ |
role:"tool" follow-up (multi-turn) |
✅ except Gemini 3.8/3.7 on the OpenAI-compatible route | ✅ | ✅ |
tool_choice (auto / required / specific) |
✅ except Gemini 3.8/3.7 on the OpenAI-compatible route | ✅ | ✅ |
| Parallel tool calls | ✅ except Gemini 3.8/3.7 on the OpenAI-compatible route | ⚠️ (serialised) | ✅ |
JSON mode / JSON schema (response_format) |
✅ | ✅ | ✅ |
| Stop sequences | ✅ | ✅ | ⚠️ (dropped on some GPT models) |
| Vision (image_url / base64) | ✅ | ✅ | ✅ |
| Video input for text analysis | ✅ token-gated Gemini chat only | — | — |
| Extended reasoning | ✅ via reasoning_effort or -non-thinking suffix |
✅ auto on thinking-enabled models | ✅ via reasoning_effort or -high / -low model suffix |
Notes on reasoning:
For gemini-3.8-flash and gemini-3.7-flash, tool turns are supported only
through the native Gemini generateContent route. The OpenAI-compatible route rejects tools,
tool_choice, and role:"tool" instead of dropping Google's required
function-call IDs or thought signatures.
- The
reasoning_effortfield (low/medium/high) maps to each model's native reasoning budget. On Claude thinking-enabled modelstemperaturemust be absent — the gateway strips it automatically. - Compatible Gemini models additionally honour a
-non-thinkingsuffix on the model id to disable reasoning entirely.gemini-3.8-flashandgemini-3.7-flashare excluded: their canonical IDs accept onlylow,medium, orhighthinking levels. - GPT reasoning models accept suffixes like
-high,-lowon the model id as shorthand forreasoning_effort.
Message object:
{
"role": "system" | "user" | "assistant",
"content": "text content"
}
For multimodal requests, content may be an array of content parts:
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this video in one paragraph."},
{
"type": "input_video",
"input_video": {
"format": "mp4",
"data": "BASE64_VIDEO_BYTES"
}
}
]
}
Gemini Video Input for Chat
Use this when you want a Gemini text model to analyze an existing video and return text. This is different from the async Video Generation Models section, which creates new videos.
POST /v1/chat/completions
Supported on token-enabled Gemini text models whose IDs match gemini-*, for
example gemini-2.5-flash, gemini-2.5-pro, gemini-3.5-flash and preview
Gemini text models when they are visible in GET /v1/models for your token.
Supported client formats:
- API429 OpenAI-compatible chat extension:
content[]item withtype: "video_url"andvideo_url.url. - API429 OpenAI-compatible chat extension:
content[]item withtype: "input_video"and base64input_video.data. - Gemini native:
contents[].parts[].fileData.fileUriwithmimeType: "video/mp4"or another supported video MIME type.
The client keeps the same OpenAI-compatible request envelope, base URL, and API
key flow. Video input is an API429-supported extension inside that envelope; the
balancer downloads and validates video input, prepares temporary media storage,
and sends provider-readable fileData to Gemini CLI where supported. Malformed video parts return 400 with a specific validation message.
Supported OpenAI-compatible video input parts:
| Part type | Shape | Notes |
|---|---|---|
input_video |
{"type":"input_video","input_video":{"format":"mp4","data":"<base64>"}} |
Best for SDK integrations that already have local video bytes. |
video_url |
{"type":"video_url","video_url":{"url":"https://.../clip.mp4","mime_type":"video/mp4"}} |
URL must be a direct public HTTP(S) file. Redirects are not followed. |
Supported formats: mp4, mov, avi, webm.
Current limits:
- Maximum original client video size: 150 MB.
- Maximum video parts passed to Gemini CLI: 4.
- Large videos may be split into several temporary parts so Gemini CLI can fetch them.
- If a video cannot be prepared without exceeding the part limit, the request returns a clear error instead of silently falling back to a provider that cannot see the video.
Other behavior:
stream:falseandstream:trueare both supported.- The response is text. Use
/v1/videos/generationsfor video output. - The gateway temporarily stages video in storage, passes a signed file URL to Gemini, and deletes the staged object after the request finishes.
- Full base64 video bodies are redacted from durable request logs.
Python (OpenAI SDK, local video)
import base64
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
with open("clip.mp4", "rb") as f:
video_b64 = base64.b64encode(f.read()).decode("ascii")
response = client.chat.completions.create(
model="gemini-2.5-flash",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Describe what happens in this video."},
{
"type": "input_video",
"input_video": {
"format": "mp4",
"data": video_b64,
},
},
],
}],
max_tokens=300,
)
print(response.choices[0].message.content)
cURL (direct video URL)
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Summarize this video in 5 bullets."},
{
"type": "video_url",
"video_url": {
"url": "https://example.com/videos/clip.mp4",
"mime_type": "video/mp4"
}
}
]
}],
"max_tokens": 500
}'
cURL (streaming)
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash",
"stream": true,
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Describe this video in one sentence."},
{
"type": "input_video",
"input_video": {
"format": "mp4",
"data": "BASE64_VIDEO_BYTES"
}
}
]
}]
}'
Examples
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY"
)
response = client.chat.completions.create(
model="gemini-3.1-pro",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain quantum computing in 3 sentences."}
],
temperature=0.7,
max_tokens=200
)
print(response.choices[0].message.content)
Python (Streaming)
stream = client.chat.completions.create(
model="gemini-3.1-pro",
messages=[{"role": "user", "content": "Write a poem about AI"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
Python (Gemini 3.5 Flash multimodal input)
response = client.chat.completions.create(
model="gemini-3.5-flash",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Summarize the visual details in this image."},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}},
],
}],
max_tokens=500,
)
print(response.choices[0].message.content)
Python (Gemini 3.5 Flash structured output)
response = client.chat.completions.create(
model="gemini-3.5-flash",
messages=[{"role": "user", "content": "Extract title, date and people from this text."}],
response_format={"type": "json_object"},
)
print(response.choices[0].message.content)
Python (Function Calling)
response = client.chat.completions.create(
model="gemini-3-flash-preview",
messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}
}
}],
tool_choice="auto"
)
Python (Web Search)
# Append -search to enable grounded web search
response = client.chat.completions.create(
model="gemini-3.1-pro-search",
messages=[{"role": "user", "content": "What happened in tech news today?"}]
)
cURL
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-flash-preview",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 100
}'
cURL (Streaming)
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-flash-preview",
"messages": [{"role": "user", "content": "Hello!"}],
"stream": true
}'
JavaScript / TypeScript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://gateway.api429.com/v1",
apiKey: "YOUR_API_KEY",
});
const response = await client.chat.completions.create({
model: "gemini-3.1-pro",
messages: [{ role: "user", content: "Hello!" }],
max_tokens: 100,
});
console.log(response.choices[0].message.content);
Response Format
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1712345678,
"model": "gemini-3.1-pro",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! How can I help you today?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 8,
"total_tokens": 20
}
}
Streaming Response (SSE)
data: {"id":"chatcmpl-abc123","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc123","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc123","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc123","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]
Responses API
POST /v1/responses
POST /openai/v1/responses
OpenAI Responses API — newer alternative to Chat Completions with a unified
response object, native tool handles, and built-in reasoning state.
Works with all supported model families: Gemini, GPT and Claude.
How it works per model family
| Model family | Behavior |
|---|---|
GPT (gpt-5.6, gpt-5.6-sol, gpt-5.6-terra, gpt-5.5, …) |
Native Responses API with tool, streaming and reasoning support. |
Gemini (gemini-*) |
Transparently translated to/from Chat Completions internally. |
Claude (claude-*) |
Transparently translated to/from Chat Completions internally. |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | Yes | Any supported model ID |
input |
string or array | Yes | User input (string for simple, array for multi-turn) |
instructions |
string | No | System instructions |
stream |
boolean | No | Enable SSE streaming (default: false) |
tools |
array | No | Function definitions for tool use |
temperature |
number | No | Sampling temperature |
max_output_tokens |
integer | No | Maximum output tokens |
top_p |
number | No | Nucleus sampling |
Input format
Simple string:
{"model": "gpt-5.3-codex", "input": "Write hello world in Python"}
Multi-turn conversation:
{
"model": "gpt-5.3-codex",
"input": [
{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "What is 2+2?"}]},
{"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "4"}]},
{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "Now multiply by 3"}]}
],
"instructions": "You are a math tutor."
}
With tool calls:
{
"model": "gpt-5.3-codex",
"input": [
{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "Weather in NYC?"}]},
{"type": "function_call", "name": "get_weather", "call_id": "call_1", "arguments": "{\"city\":\"NYC\"}"},
{"type": "function_call_output", "call_id": "call_1", "output": "{\"temp\":72,\"condition\":\"sunny\"}"}
],
"tools": [
{"type": "function", "name": "get_weather", "description": "Get weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}}
]
}
With images:
{
"model": "gemini-3.1-pro",
"input": [
{"type": "message", "role": "user", "content": [
{"type": "input_text", "text": "Describe this image"},
{"type": "input_image", "image_url": "https://example.com/photo.jpg"}
]}
]
}
Examples
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
# Simple request
resp = client.responses.create(
model="gpt-5.3-codex",
input="Write a Python function to sort a list",
)
print(resp.output_text)
Python (Streaming)
stream = client.responses.create(
model="gpt-5.3-codex-high",
input="Explain quantum computing in simple terms",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="")
Python (With tools)
resp = client.responses.create(
model="gemini-3.1-pro",
input="What is the weather in London?",
tools=[{
"type": "function",
"name": "get_weather",
"description": "Get current weather",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
},
}],
)
for item in resp.output:
if item.type == "function_call":
print(f"Call: {item.name}({item.arguments})")
cURL (non-streaming)
curl https://gateway.api429.com/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.3-codex",
"input": "Hello!",
"stream": false
}'
cURL (streaming)
curl -N https://gateway.api429.com/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.3-codex",
"input": "Write a hello world in Rust",
"stream": true
}'
Non-streaming Response
{
"id": "resp_abc123",
"object": "response",
"created_at": 1712345678,
"status": "completed",
"model": "gpt-5.3-codex",
"output": [
{
"id": "msg_def456",
"type": "message",
"role": "assistant",
"content": [
{"type": "output_text", "text": "Here is the code..."}
]
}
],
"usage": {
"input_tokens": 12,
"output_tokens": 45,
"total_tokens": 57
}
}
Streaming Events (SSE)
When stream: true, the server sends SSE events:
event: response.created
data: {"type":"response.created","response":{"id":"resp_abc","status":"in_progress"},"sequence_number":1}
event: response.output_item.added
data: {"type":"response.output_item.added","output_index":0,"item":{"id":"msg_1","type":"message","role":"assistant"},"sequence_number":2}
event: response.output_text.delta
data: {"type":"response.output_text.delta","output_index":0,"delta":"Hello","sequence_number":3}
event: response.output_text.delta
data: {"type":"response.output_text.delta","output_index":0,"delta":" world","sequence_number":4}
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_abc","status":"completed","usage":{...}},"sequence_number":10}
data: [DONE]
Event types:
| Event | Description |
|---|---|
response.created |
Stream started |
response.in_progress |
Processing |
response.output_item.added |
New message/reasoning/function_call item |
response.content_part.added |
New text content part |
response.output_text.delta |
Text chunk |
response.output_text.done |
Text content finished |
response.reasoning_summary_text.delta |
Reasoning/thinking chunk |
response.function_call_arguments.delta |
Tool call arguments chunk |
response.function_call_arguments.done |
Tool call complete |
response.output_item.done |
Item finished |
response.completed |
Stream done, includes usage |
Image Generation via Responses API
GPT models can generate images through the image_generation tool in
the Responses API. The gateway fulfils the tool call through the
dedicated GPT Image route and returns a base64 image.
resp = client.responses.create(
model="gpt-5.5",
input="Draw a cute orange cat sitting on a windowsill",
tools=[{"type": "image_generation"}],
)
for item in resp.output:
if item.type == "image_generation_call":
import base64
with open("cat.png", "wb") as f:
f.write(base64.b64decode(item.result))
GPT Image 2
Use model:"gpt-image-2" for GPT Image workloads. It is served by the
dedicated GPT Image path on both:
POST /v1/images/generationsPOST /v1/images/edits
Clients using the OpenAI SDK can point their existing Images API calls
at the API429 base URL and keep model:"gpt-image-2".
Text-to-image:
curl https://gateway.api429.com/v1/images/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A cinematic product photo of a matte black espresso machine",
"size": "1024x1024",
"quality": "low",
"response_format": "b64_json"
}'
Image edit / reference image:
curl https://gateway.api429.com/v1/images/edits \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "model=gpt-image-2" \
-F "prompt=Replace the background with a clean white studio backdrop" \
-F "image=@product.png;type=image/png" \
-F "size=1024x1024" \
-F "quality=low" \
-F "response_format=b64_json"
Supported edit upload formats: PNG, JPEG and WebP. A request may include
multiple image form fields and an optional mask image. background: "transparent" is not supported for gpt-image-2; use opaque or omit it.
GPT Image 2 billing is token-based. OpenAI publishes these token rates:
| Component | API429 list price |
|---|---|
| Text input | $5.00 / 1M tokens |
| Cached text input | $1.25 / 1M tokens |
| Image input | $8.00 / 1M tokens |
| Cached image input | $2.00 / 1M tokens |
| Image output | $30.00 / 1M tokens |
For convenience, OpenAI's image calculator gives these approximate output prices for common GPT Image 2 sizes:
| Quality | 1024x1024 | 1024x1536 | 1536x1024 |
|---|---|---|---|
low |
$0.006 | $0.005 | $0.005 |
medium |
$0.053 | $0.041 | $0.041 |
high |
$0.211 | $0.165 | $0.165 |
The final request cost is the sum of text input tokens, image input tokens
for edits/reference images, and output image tokens. For smoke tests and
drafts, use quality:"low" and a 1024-class size.
Gemini Batch Images
Gemini image batches are async/non-realtime jobs for large image runs. The public submit flow follows the OpenAI-compatible Files + Batch pattern:
curl https://gateway.api429.com/v1/files \
-H "Authorization: Bearer YOUR_API_KEY" \
-F purpose="batch" \
-F file="@batchinput.jsonl"
curl https://gateway.api429.com/v1/batches \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input_file_id": "file_abc123",
"endpoint": "/v1/responses",
"completion_window": "24h",
"metadata": {"job": "nightly-image-generation"}
}'
Official OpenAI-compatible Phase 1 rows target /v1/responses and request the
image_generation tool:
{"custom_id":"row-000001","method":"POST","url":"/v1/responses","body":{"model":"gemini-3.1-flash-image","input":"studio product photo of a red ceramic mug","tools":[{"type":"image_generation"}]}}
Reference images (image editing / compose) are supported via input_image
content parts. Inline the image as a data: URI (base64) or use a gs://
URI; external http(s) URLs are rejected at submit because batch workers
cannot fetch them at execution time:
{"custom_id":"row-000002","method":"POST","url":"/v1/responses","body":{"model":"gemini-3.1-flash-image","input":[{"role":"user","content":[{"type":"input_text","text":"replace the mug logo with the one from the reference"},{"type":"input_image","image_url":"data:image/png;base64,iVBORw0KGgo..."}]}],"tools":[{"type":"image_generation"}]}}
/v1/images/generations in batch JSONL is an API429 extension only; it is not
an official OpenAI Batch endpoint. If you use the API429 image edits extension,
prefer JSONL-friendly image_url inputs rather than inline base64. The official
Phase 1 endpoint remains /v1/responses.
Batch limits and behavior:
| Area | Contract |
|---|---|
| Runtime | Async/non-realtime. OpenAI-compatible completion_window is 24h; Google may queue jobs for capacity for up to 72h. |
| Output size | Google batch image output is 1K only. Do not submit unsupported 2K/4K batch image requests. |
| Input file | JSONL uploaded with purpose=batch; size limit follows GEMINI_BATCH_MAX_INPUT_FILE_BYTES (default 1GB). |
| Billing | API429 reserves balance at submit, charges completed rows only, and releases failed rows. Batch image price is 50% of the configured realtime image unit price, or the separate gemini_batch provider rows when configured. |
| Storage | Completed outputs are exposed through API429 file IDs; generated image artifacts include CDN URLs when present. |
| Admin flag | Allow with gemini_batch_images; this is separate from realtime image. |
| Deployment | Worker pods need GEMINI_BATCH_WORKER_ENABLED=true. Each service account must have a per-SA bucket mapping; there is no shared GCS bucket fallback. |
GPT Models
All GPT-family models (including the Codex sub-family) are available through two endpoints:
POST /v1/chat/completions— standard Chat Completions formatPOST /v1/responses— OpenAI Responses API format (recommended for GPT-5.x reasoning models)
The gateway picks the right path automatically based on the model id.
Available Models
| Model | Input $/1M | Cached input | Cache write | Output $/1M | Context | Best For |
|---|---|---|---|---|---|---|
| GPT-5.6 | ||||||
gpt-5.6 |
$5.00 | $0.50 | $6.25 | $30.00 | 1.05M | Official alias of gpt-5.6-sol |
gpt-5.6-sol |
$5.00 | $0.50 | $6.25 | $30.00 | 1.05M | Highest capability tier for complex reasoning and agents |
gpt-5.6-terra |
$2.50 | $0.25 | $3.125 | $15.00 | 1.05M | Balanced capability, latency and cost |
| Frontier (GPT-5.5) | ||||||
gpt-5.5 |
$5.00 | — | — | $30.00 | — | Agentic coding, computer use and research |
| Flagship (GPT-5.4) | ||||||
gpt-5.4 |
$2.50 | — | — | $15.00 | — | Reasoning, tool use and agentic workflows |
gpt-5.4-mini |
$0.75 | — | — | $4.50 | — | Fast, efficient, lightweight tasks |
| Coding Specialists (GPT-5.3) | ||||||
gpt-5.3-codex |
$1.75 | — | — | $14.00 | — | Coding workflows |
| Previous Gen | ||||||
gpt-5.2 |
$1.75 | — | — | $14.00 | — | Deep debugging and analysis |
Use the exact model IDs above for new integrations. Compatibility IDs
gpt-5.6 resolves to gpt-5.6-sol. Compatibility IDs such as
gpt-5, gpt-5-mini, and gpt-5.1 are still accepted for
older clients and bill at the resolved gpt-5.2 rate, but they are not
advertised as separate selectable models. Older gpt-5*-codex variants
are not public model IDs unless they appear in your token's
GET /v1/models response.
Reasoning effort presets — use reasoning_effort or append a suffix to the model ID:
| Suffix | Effect | Latency Impact | Example |
|---|---|---|---|
-max |
Maximum GPT-5.6 reasoning depth | Highest | gpt-5.6-sol-max |
-xhigh |
Very high reasoning depth | Higher | gpt-5.6-terra-xhigh |
-high |
Deeper reasoning | +30-50% | gpt-5.3-codex-high |
-medium or no suffix |
Medium reasoning | baseline | gpt-5.6 |
-low |
Lighter reasoning, faster | -10-20% | gpt-5.3-codex-low |
-none |
Skip reasoning entirely | -30-50% | gpt-5.3-codex-none |
All presets bill at the same token rate as the base model. GPT-5.6 accepts all six values; older GPT models may support a subset.
GPT-5.6 long-context and cache billing
When usage.input_tokens is greater than 272,000, the long-context rates apply to the entire request:
| Model | Input | Cached input | Cache write | Output |
|---|---|---|---|---|
gpt-5.6 / gpt-5.6-sol |
$10.00 | $1.00 | $12.50 | $45.00 |
gpt-5.6-terra |
$5.00 | $0.50 | $6.25 | $22.50 |
Automatic prompt caching is supported. Responses API reports cache usage in
usage.input_tokens_details.cached_tokens and cache_write_tokens; Chat
Completions exposes the same values under usage.prompt_tokens_details.
Explicit cache-control fields are not currently accepted on the GPT gateway
route. reasoning.mode: "pro" is also not currently available; use
reasoning.effort: "max" for the deepest supported reasoning. The current
gateway route does not enforce max_output_tokens, so clients should stop
generation locally when they require a stricter output cap.
GPT-5.6 Responses requests may use the built-in web_search tool. Each
web_search_call is billed at $10.00 per 1,000 calls ($0.01 per call), and
the search-content tokens returned to the model are billed at the selected
model's input-token rate. The response output array contains the
web_search_call item used for transparent request accounting.
For Instructor clients, Mode.MD_JSON (markdown_json_mode) is supported as
a client-side fallback: Instructor adds the schema to the prompt and parses
the markdown-fenced JSON response locally. Do not send
markdown_json_mode as an API request field. Prefer strict
response_format: {"type":"json_schema", ...} when possible.
Using Responses API (recommended for GPT-5.x)
GPT-5.x models support the OpenAI Responses API natively. Use this endpoint when you want built-in reasoning state and native tool handles.
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
# Simple request
resp = client.responses.create(
model="gpt-5.6",
input="Write a Python quicksort implementation",
)
print(resp.output_text)
# With reasoning effort
resp = client.responses.create(
model="gpt-5.6-sol",
input="Find the bug in this code and explain your reasoning",
instructions="You are a senior code reviewer.",
reasoning={"effort": "max"},
)
print(resp.output_text)
# Streaming
stream = client.responses.create(
model="gpt-5.6-terra",
input="Explain async/await in Python",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="")
Using Chat Completions (also supported)
Examples
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY"
)
# GPT-5.6 Sol with high reasoning
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[
{"role": "system", "content": "You are a senior developer."},
{"role": "user", "content": "Review this Python function for bugs."}
],
reasoning_effort="high",
)
print(response.choices[0].message.content)
Python (Streaming)
stream = client.chat.completions.create(
model="gpt-5.6-terra",
messages=[{"role": "user", "content": "Write a hello world in Rust"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
cURL
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4-mini",
"messages": [{"role": "user", "content": "Hello!"}]
}'
Grok & Extended Catalogue
xAI Grok models and an extended set of vendor-prefixed chat IDs use the same
Bearer token and OpenAI SDK configuration as Gemini, GPT and Claude. Always
send the exact model id returned by your token's GET /v1/models response.
Grok (xAI)
grok-4.6 is the canonical current xAI flagship. It is available on
POST /v1/chat/completions and POST /v1/responses, including streaming.
It accepts text and image input and produces text, function calls, or
structured JSON output. On the Responses API, send the complete input context;
previous_response_id continuation is not enabled for this route yet.
| Model | Input $/1M | Cached $/1M | Output $/1M | Context | Best For |
|---|---|---|---|---|---|
grok-4.6 |
$2.00 | $0.50 | $6.00 | 500K | Current xAI flagship: reasoning, vision, function calling, structured output |
The rates above are the official xAI Standard list rates before API429 or client-specific discounts. For requests with 200,000 or more input tokens, the whole request uses the long-context rates: $4 input, $1 cached input, and $12 output per 1M tokens. Reasoning tokens are output tokens for billing.
Use reasoning_effort with low, medium, high, or xhigh. If omitted,
xAI defaults to high. stop, presence_penalty, and frequency_penalty are
not accepted by Grok 4.6. Local function tools are supported; xAI-hosted web,
X-search, and code-execution tools are not exposed by API429 yet because they
have separate per-call pricing.
Additional Grok catalogue IDs
The following vendor-prefixed compatibility IDs are separate catalogue
entries. Their x-ai/ prefix is part of the model id.
| Model | Input $/1M | Output $/1M | Best For |
|---|---|---|---|
x-ai/grok-4 |
$1.25 | $2.50 | Grok 4 compatibility tier — general chat and reasoning |
x-ai/grok-4-reasoning |
$1.25 | $2.50 | Grok 4 with extended reasoning / thinking |
x-ai/grok-3 |
$1.25 | $2.50 | Fast, cost-effective general-purpose Grok |
x-ai/grok-3-reasoning |
$1.25 | $2.50 | Grok 3 with extended reasoning |
Extended vendor-prefixed chat IDs
These IDs offer additional GPT and Gemini tiers alongside the native catalogue above. They are billed per the table below and accept the same chat parameters.
| Model | Input $/1M | Output $/1M | Notes |
|---|---|---|---|
openai/gpt-5 |
$1.00 | $8.00 | GPT-5 standard |
openai/gpt-5-instant |
$1.25 | $10.00 | Low-latency GPT-5 variant |
openai/gpt-5-thinking |
$1.25 | $10.00 | GPT-5 with extended reasoning |
google/gemini-3-pro |
$2.00 | $12.00 | Gemini 3 Pro |
google/gemini-2.5-pro |
$1.25 | $10.00 | Gemini 2.5 Pro |
google/gemini-2.5-flash |
$0.30 | $2.50 | Fast, low-cost Gemini |
Availability of every model above is gated by your token. Always check your token's
GET /v1/modelsresponse for the authoritative selectable list and current pricing.
Example
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
resp = client.chat.completions.create(
model="grok-4.6",
messages=[{"role": "user", "content": "Explain quantum entanglement in two sentences."}],
reasoning_effort="high",
)
print(resp.choices[0].message.content)
Claude Models
Claude models are available through two public API surfaces:
| Surface | Endpoint | Auth | Use when |
|---|---|---|---|
| OpenAI-compatible | POST /v1/chat/completions |
Authorization: Bearer <token> |
Your client already uses OpenAI Chat Completions or Responses-style tooling. |
| Anthropic-compatible | POST /v1/messages |
x-api-key: <token> |
Your client already uses Anthropic Messages API / Anthropic SDK shape and you want to change only the base URL and token. |
Use the canonical claude-* model IDs below for public integrations. API429
may route requests internally for availability, but clients should not depend
on internal route names or provider-specific aliases.
All Claude models listed here support chat, streaming, tool calling, web search and vision/image input unless otherwise noted. Vision means text + image input with text output; these models do not generate images.
Available Models
Model IDs use dash separators. Dotted aliases are accepted for compatibility,
but new integrations should send the canonical model ID from the first column.
For 1M context, use the canonical -1m model IDs shown below, or Anthropic's
bracket-style aliases such as claude-opus-4.8[1m].
The prices below are API429 list prices per 1 million tokens before your
client-level discount.
| Model ID | Accepted Alias(es) | Input $/1M | Output $/1M | Context | Best For |
|---|---|---|---|---|---|
claude-fable-5 |
— | $10.00 | $50.00 | 1M | Most capable Claude model for the hardest reasoning and long-horizon work |
claude-opus-5 |
— | $5.00 | $25.00 | 1M | Newest Opus for demanding reasoning, coding and analysis |
claude-sonnet-5 |
claude-sonnet-5.0 |
$2.00 | $10.00 | 1M | Newest Sonnet for coding, agents and professional work |
claude-opus-4-8 |
claude-opus-4.8 |
$5.00 | $25.00 | 1M | Highest quality reasoning, coding, analysis |
claude-opus-4-8-1m |
claude-opus-4.8-1m, claude-opus-4.8[1m] |
$5.00 | $25.00 | 1M | Opus with explicit 1M-context ID |
claude-opus-4-7 |
claude-opus-4.7 |
$5.00 | $25.00 | 1M | Highest quality reasoning, coding, analysis |
claude-opus-4-7-1m |
claude-opus-4.7-1m, claude-opus-4.7[1m] |
$5.00 | $25.00 | 1M | Opus with explicit 1M-context ID |
claude-opus-4-6 |
claude-opus-4.6 |
$5.00 | $25.00 | 1M | Complex analysis and long-form work |
claude-opus-4-6-1m |
claude-opus-4.6-1m, claude-opus-4.6[1m] |
$5.00 | $25.00 | 1M | Opus 4.6 with explicit 1M-context ID |
claude-sonnet-4-6 |
claude-sonnet-4.6 |
$3.00 | $15.00 | 1M | Balanced intelligence, speed and cost |
claude-sonnet-4-5 |
claude-sonnet-4.5 |
$3.00 | $15.00 | 200k | General Claude chat and writing workloads |
claude-haiku-4-5-20251001 |
claude-haiku-4-5, claude-haiku-4.5 |
$1.00 | $5.00 | 200k | Lowest latency and lowest cost Claude model |
You can also call GET /v1/models with your API key to see the exact Claude
models enabled for your token.
Anthropic-compatible Messages API
Use this endpoint when your code already targets Anthropic's Messages API. The request body and response body follow the Anthropic Messages shape; API429 selects and rotates upstream Claude credentials server-side.
POST https://gateway.api429.com/v1/messages
Required headers:
x-api-key: YOUR_API_KEY
content-type: application/json
anthropic-version: 2023-06-01
anthropic-version is accepted for SDK compatibility and may be omitted; when
it is omitted API429 forwards 2023-06-01 upstream.
cURL
curl -X POST https://gateway.api429.com/v1/messages -H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" -H "anthropic-version: 2023-06-01" --data @payload.json
payload.json:
{
"model": "claude-sonnet-5",
"max_tokens": 512,
"system": "You are a concise technical assistant.",
"messages": [
{"role": "user", "content": "Explain Mutex vs RwLock in Rust."}
]
}
Response
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"model": "claude-sonnet-5",
"content": [
{"type": "text", "text": "..."}
],
"stop_reason": "end_turn",
"usage": {
"input_tokens": 23,
"output_tokens": 87
}
}
Native streaming
Set "stream": true on /v1/messages to receive Anthropic-style SSE events:
curl -N -X POST https://gateway.api429.com/v1/messages -H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" -H "anthropic-version: 2023-06-01" --data @payload.json
payload.json:
{
"model": "claude-sonnet-5",
"max_tokens": 512,
"stream": true,
"messages": [
{"role": "user", "content": "Write a haiku about Rust."}
]
}
Events arrive in Anthropic order:
message_start
content_block_start
content_block_delta
content_block_stop
message_delta
message_stop
Anthropic may also send ping events between content events. Usage is split
across the stream: message_start includes input usage, and message_delta
includes final output usage.
Native request fields
| Field | Type | Required | Notes |
|---|---|---|---|
model |
string | Yes | Use a Claude model ID from GET /v1/models. |
messages |
array | Yes | Anthropic message list: role is user or assistant; content may be a string or content blocks. |
max_tokens |
integer | Yes | Maximum output tokens. |
system |
string or array | No | System prompt, including content blocks with cache_control where supported upstream. |
stream |
boolean | No | Returns Anthropic SSE events when true. |
temperature |
number | No | Sampling temperature. |
tools |
array | No | Anthropic tool-use format, including server tools. |
stop_sequences |
array | No | Anthropic stop sequences. |
Native usage and billing
Native responses expose Anthropic-style usage:
{
"usage": {
"input_tokens": 123,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"output_tokens": 45
}
}
These numbers are also recorded in API429 usage analytics and billing. For Claude requests, billable input tokens are:
input_tokens + cache_creation_input_tokens + cache_read_input_tokens
Billable output tokens are output_tokens. On the OpenAI-compatible surface,
the same values are exposed as prompt_tokens, completion_tokens, and, when
available, prompt_tokens_details.
If upstream returns prompt-cache fields such as cache_creation_input_tokens
or cache_read_input_tokens, API429 passes them through in native usage and
includes them in analytics. When those fields are absent, clients should bill
and display the reported input_tokens / output_tokens values and use the
client usage endpoints for the final charged amount.
Web search for Claude models
Claude models on this gateway accept Anthropic's stable
web_search_20250305 server tool. On the Anthropic-compatible /v1/messages
surface, this is a native Anthropic tool-use contract: the model may return
stop_reason: "tool_use" with a content block of type tool_use, and the
client continues the tool loop in the next request.
Declare it as:
{
"model": "claude-sonnet-5",
"messages": [{"role": "user", "content": "Latest Anthropic news?"}],
"tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 3}]
}
For convenience the balancer also accepts two non-canonical input shapes and rewrites them automatically:
| Sent by client | Forwarded to Anthropic | Notes |
|---|---|---|
{"type": "web_search_preview"} (OpenAI Responses API style) |
web_search_20250305 |
OpenAI-only fields (search_context_size, user_location, include_domains, exclude_domains, search_content_types) are stripped — Anthropic 400s on unknown keys. |
{"type": "web_search_20260209"} (newer Anthropic dated variant) |
web_search_20250305 |
name and max_uses are preserved. The newer variant is not yet broadly available, so the rewrite avoids a "tools unavailable" response. |
The gateway forwards this server-tool declaration to the Claude route. On the
OpenAI-compatible surface, the final shape is still a Chat Completions
response and structured citation metadata is not exposed. On the
Anthropic-compatible Messages surface, inspect returned tool_use content
blocks and continue the native tool loop when the model stops with
stop_reason: "tool_use".
Behaviour change (2026-04-25): Before this release, requests with
web_search_previewwere silently dropped at the balancer (model answered "I have no real-time access"). They now activate a real web search — the response text changes accordingly. Clients that passedweb_search_preview"defensively" should remove it if they don't actually want search.
Examples
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
response = client.chat.completions.create(
model="claude-sonnet-5",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain the difference between TCP and UDP."},
],
)
print(response.choices[0].message.content)
cURL (vision / image input)
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-opus-4-8",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image in one sentence."},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,BASE64_IMAGE"}}
]
}],
"max_tokens": 256
}'
Python (Streaming, frontier model)
stream = client.chat.completions.create(
model="claude-opus-4-7",
messages=[{"role": "user", "content": "Write a Python async web scraper"}],
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
cURL (fastest / cheapest — Haiku snapshot)
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-4-5-20251001",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 256
}'
Optional headers for batch / long-running Claude workflows
Two optional headers are useful for long-running Claude integrations. Clients that do not send them get normal synchronous behavior.
| Header | Endpoints | Effect |
|---|---|---|
X-Session-Key |
POST /v1/chat/completions, POST /v1/balancer/jobs/chat-completions |
Stable string per logical conversation. Helps API429 reuse server-side conversation/cache state across multi-turn batches. Tenant-namespaced server-side. Format: 1–256 chars [a-zA-Z0-9._/+-]. Full contract: client-facing X-Session-Key guide. |
X-Async-Jobs-Optin: true |
POST /v1/chat/completions |
Allows API429 to move a non-streaming request into the durable jobs queue during overload. Normal success still returns 200 inline. If queued, the response is 202 with Location: /v1/balancer/jobs/{id}/result; poll that URL for the final result. Ignored for stream=true because jobs are non-streaming. |
Recommended combo for batch screenwriter clients:
curl https://gateway.api429.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Session-Key: scenario/iceberg/run-001/scene-3" \
-H "X-Async-Jobs-Optin: true" \
-d '{
"model": "claude-sonnet-4-5",
"messages": [{"role": "user", "content": "Draft scene 3 of the iceberg scenario."}]
}'
Streaming note: plain Claude stream:true is token-progressive
SSE. Jobs API responses are never streaming; use polling for durability.
Image Generation Models
Available Models
| Model | Status | Cost per Image | Notes |
|---|---|---|---|
gpt-image-2 |
Stable | $0.005-$0.211 output image estimate + input tokens | GPT Image; exact price depends on text/image input, quality, and size |
gemini-2.5-flash-image |
Stable | $0.039 | Alias: nano-banana |
gemini-3.1-flash-lite-image |
Stable | $0.0336 | Nano Banana 2 Lite. Alias: nano-banana-2-lite; compatibility alias: nana-banana-2-lite. |
nano-banana-2 |
Stable alias | $0.067 | Alias of gemini-3.1-flash-image; identical routing, allowlist semantics, capabilities, and pricing. |
imagen-4 |
Stable | $0.040 | Imagen 4 |
flower-image |
Stable | $0.040 | General-purpose text-to-image |
gpt-image-1 |
Stable | $0.040 | OpenAI GPT Image 1 |
grok-imagine-image |
Stable | $0.020 (1K/2K) | Native xAI Images API through the Grok OAuth pool; text-to-image |
grok-imagine-image-quality |
Stable | $0.050 (1K), $0.070 (2K) | Native xAI quality image model; text-to-image |
grok-image |
Stable alias | $0.050 (1K), $0.070 (2K) | Backward-compatible alias for grok-imagine-image-quality |
gemini-3.1-flash-image |
Stable | $0.067 | Gemini 3.1 Flash Image (native). Higher-resolution output (up to 4K), balanced speed/quality. The retired gemini-3.1-flash-image-preview ID remains accepted as a compatibility alias. |
gemini-3-pro-image |
Stable | $0.134 | Canonical GA Nano Banana Pro ID. Compatibility aliases: gemini-3-pro-image-preview, nano-banana-pro, nana-bana-pro. Highest visual fidelity for edits and 4K. |
FLUX.2-pro |
Stable | $0.030+ | Azure AI Foundry / Black Forest Labs FLUX.2 pro. Billed by generated megapixels and reference-image megapixels (1 MP = 1024×1024). |
sora-images |
Stable | $0.040 | OpenAI Sora Images (alias gpt-image-1); up to 4 per call via n |
dalle-3 |
Stable | $0.040 | DALL·E 3 (variants: dalle-3-openai, dalle-3-bing). Bing channel accepts 4:7 / 7:4 aspect ratios. |
midjourney-7.0-fast |
Stable | $0.021 | Midjourney v7 fast tier; 4-image batch, billed per job. Also: midjourney-7.0-relax ($0.011); midjourney-6.1-*, midjourney-8.1-* |
flux-1 |
Stable | $0.040 | Flux.1 generations; width/height 600–1600 px, copies 1–2 |
qwen-image |
Stable | $0.040 | Qwen text-to-image; supports width/height, style, n=1..2 |
qwen-image-edit |
Stable | $0.040 | Qwen edit with reference image. Subtypes (same price): qwen-image-remove-bg, -remove-watermark, -restore, -colorize-1, -colorize-2, -contour, -depth, -extract-clothing, -make-old, -make-young, -stylize, -3d |
acc-upper / acc-lower / acc-full |
Stable | $0.060 | AI Change Clothes (upper / lower / full body). Needs person photo in image + clothing reference in images[0] |
Gemini image resolution pricing:
| Canonical model | 1K official / API429 standard* | 2K official / API429 standard* | 4K official / API429 standard* |
|---|---|---|---|
gemini-3.1-flash-image (nano-banana-2) |
$0.067 / $0.0201 | $0.101 / $0.0303 | $0.151 / $0.0453 |
gemini-3-pro-image (nano-banana-pro) |
$0.134 / $0.0402 | $0.134 / $0.0402 | $0.240 / $0.0720 |
* API429 standard amounts apply the standard 70% client discount. A per-client billing profile may override that discount.
All image models are exposed on the same /v1/images/generations
endpoint. No extra credentials are needed on the client side. The
gateway picks the right backend for the requested model. For
model:"gpt-image-2", the request uses the dedicated GPT Image route,
not the Gemini image model family.
Resolution tiers. The rates in the main model table are 1K rates unless a row says otherwise. Gemini Flash is $0.067 / $0.101 / $0.151 at 1K / 2K / 4K. Gemini Pro is $0.134 / $0.134 / $0.240.
imagen-4has Fast / Standard / Ultra tiers ($0.02 / $0.04 / $0.06).FLUX.2-prouses Azure FLUX megapixel billing: first generated MP is $0.030, each additional generated MP is $0.015, and each reference-image MP is $0.015. xAIgrok-imagine-imagecosts $0.020 at either 1K or 2K;grok-imagine-image-qualitycosts $0.050 at 1K and $0.070 at 2K. Pickaspect_ratio/sizeaccordingly.
Grok OAuth image limits. API429 does not impose a made-up local RPM or weekly quota. Each OAuth account is rotated according to the live
x-ratelimit-*,Retry-After, and 429 reset data returned by xAI. A model-scoped limit only pauses that model on that account; an explicitly account/subscription-scoped limit pauses image use for the whole account. If xAI omits a reset time, API429 performs a synchronized probe instead of assuming a 24-hour cooldown.
Example:
curl https://gateway.api429.com/v1/images/generations \
-H "Authorization: Bearer $API429_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "grok-imagine-image-quality",
"prompt": "Editorial product photo on a clean studio background",
"resolution": "2K",
"aspect_ratio": "16:9",
"response_format": "url"
}'
The native xAI OAuth route currently supports text-to-image at 1K or 2K.
It rejects 4K, reference images, masks, negative_prompt, style, and
seed explicitly instead of silently dropping them. Use a model documented
for image editing when reference-image fidelity is required.
Output format note: the gateway preserves the MIME type of the bytes the
provider actually returned; it does not label every image .png. With
response_format:"url", every item has a url: normally a hosted URL, or a
data:<actual-mime>;base64,… URL if the uploader is unavailable or fails.
With response_format:"b64_json", every item has raw standard base64 in
b64_json. PNG, JPEG, and WebP are all possible when supported upstream.
Endpoint
POST /v1/images/generations
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
model |
string | No | nano-banana |
Model ID from table above (the default when omitted) |
prompt |
string | Yes | — | Text description of the image |
n |
integer | No | 1 |
Number of images (1–8). Some models always return 1 regardless. |
size |
string | No | 1024x1024 |
Image dimensions |
aspect_ratio |
string | No | — | 1:1, 16:9, 9:16, 4:3, 3:4 |
resolution |
string | No | 1K |
Output tier: 1K (default), 2K, 4K. Aliases: standard, hd, ultra. Also accepts image_size / imageSize. See 4K notes below. |
quality |
string | No | — | OpenAI-style tier: standard → 1K, hd → 2K, ultra → 4K. |
image_config |
object | No | — | Nested Google image configuration. Accepts snake_case or camelCase forms of image_size, aspect_ratio, negative_prompt, output_mime_type, and person_generation. Also accepts imageConfig. Top-level wins when both forms are supplied; a non-object returns 422. Supplying outputMimeType or personGeneration makes the request Vertex-only. |
response_format |
string | No | url |
url or b64_json |
outputMimeType / output_mime_type |
string | No | Provider default | Requested Google output MIME: image/png, image/jpeg, or image/webp. Forwarded through a Vertex-backed credential; the response still reports the MIME actually returned. |
personGeneration / person_generation |
string | No | Provider default | Google person-generation policy: ALLOW_ALL, ALLOW_ADULT, ALLOW_NONE, or equivalent Imagen spelling DONT_ALLOW. The gateway translates the deny value for the selected Google model family and forwards it through a Vertex-backed credential. |
background |
string | No | — | For gpt-image-2, use opaque or omit. transparent is not supported. |
output_format |
string | No | png |
For gpt-image-2: png, jpeg, or webp when honored upstream. |
output_compression |
integer | No | — | For jpeg / webp, 0-100 when honored upstream. |
moderation |
string | No | auto |
For GPT Image compatibility: auto or low. |
image |
string | No | — | Reference image (base64, URL, or data URI) |
reference_images |
array | No | — | Multiple reference images — see format below |
negative_prompt |
string | No | — | What to avoid |
Vertex-only image controls. When
outputMimeTypeorpersonGenerationis present at the top level or insideimageConfig, the gateway automatically selects a usable Vertex-backed Google credential. These fields are not sent to the Gemini Developer API. If no Vertex-backed credential is available, the request fails clearly with HTTP503instead of silently dropping the fields or retrying through an incompatible API. Requests for non-Google image models fail with HTTP400because their provider routes cannot honor these Google-specific controls.
Requesting 2K / 4K output
All three of these are equivalent:
{"model": "nano-banana-pro", "prompt": "...", "resolution": "4K"}
{"model": "nano-banana-pro", "prompt": "...", "image_size": "4K"}
{
"model": "nano-banana-pro",
"prompt": "...",
"image_config": {"image_size": "4K", "aspect_ratio": "16:9"}
}
Using the OpenAI SDK:
client.images.generate(
model="nano-banana-pro",
prompt="...",
extra_body={"image_size": "4K"},
)
Model support for 2K / 4K:
| Model | 1K | 2K | 4K | Source |
|---|---|---|---|---|
gemini-3-pro-image (nano-banana-pro alias) |
✅ | ✅ | ✅ | ai.google.dev |
gemini-3.1-flash-lite-image / nano-banana-2-lite |
✅ | — | — | ai.google.dev |
gemini-3.1-flash-image |
✅ | ✅ | ✅ | ai.google.dev — gemini-3.1 flash-image |
gemini-2.5-flash-image / nano-banana |
✅ | — | — | legacy; Google lists shutdown no earlier than 2026-10-02 |
imagen-4 |
✅ | ✅ | — | Imagen 4 / Imagen 4 Ultra cap at 2048×2048 |
FLUX.2-pro |
yes | yes | yes | Azure FLUX.2 pro; billed by rounded-up generated/reference MP |
grok-imagine-image |
yes | yes | — | Native xAI Images API; text-to-image |
grok-imagine-image-quality / grok-image |
yes | yes | — | Native xAI quality model; grok-image is the compatibility alias |
- The balancer forwards the requested tier to the selected image model. If a model does not support the requested tier, the upstream may return HTTP 400. We do not silently downgrade between tiers the model understands.
- Non-Google image models may use different native size primitives; see the caveats below.
Provider caveats for non-Google backends:
FLUX.2-proaccepts either explicit pixel-shapedsize(for example"1024x1024","2048x2048") orresolution/image_size/qualitytiers.quality:"standard"maps to 1K,quality:"hd"maps to 2K, andquality:"ultra"maps to 4K.aspect_ratiois used when deriving dimensions from a tier.- Other non-Google image providers may use different native size primitives.
If your workflow strictly needs 4K, pin model to one of the 4K-capable entries above (gemini-3-pro-image, gemini-3.1-flash-image).
Azure FLUX.2-pro references and billing
FLUX.2-pro supports up to 8 reference images on the JSON image-generation endpoint. References may be supplied through reference_images, or through OpenAI-compatible image / images fields. Extra references above 8 are ignored after the first 8.
Billing is based on rounded-up megapixels:
- generated output: first MP $0.030, each additional MP $0.015;
- each reference image: $0.015 per rounded-up MP;
- 1 MP is treated as 1024x1024 pixels.
Example with two references:
{
"model": "FLUX.2-pro",
"prompt": "Create a premium studio product image using the references",
"quality": "hd",
"aspect_ratio": "16:9",
"reference_images": [
{"image_url": "https://cdn.example.com/ref-1.png"},
{"image_base64": "data:image/jpeg;base64,..."}
],
"n": 1,
"response_format": "url"
}
Image editing (reference images + edit prompt)
For edit/reference-image workflows, prefer gemini-3-pro-image when visual fidelity to the input image is
critical. Flash image models remain suitable for fresh generations and
lower-cost drafts, but Pro is the safer choice for production edits.
If you want Pro explicitly from the caller side, pin
model: "gemini-3-pro-image". The older names remain input aliases only.
reference_images format
Accepts either structured objects or bare URL strings in the same array:
{
"reference_images": [
"https://cdn.example.com/ref_1.jpg",
{
"name": "ref_2",
"image_base64": "<base64-without-data-uri-prefix>",
"mime_type": "image/png"
},
{
"image_url": "https://cdn.example.com/ref_3.webp"
}
]
}
- A bare string is treated as
{"image_url": "<string>"}— the server fetches the URL and base64-encodes it at provider boundary. - Object form requires at least one of
image_base64/image_url.nameandmime_typeare optional. - Base64 inputs may use standard base64 or URL-safe base64, with or without padding. API429 validates the bytes and canonicalizes forwarded/output base64 to padded standard base64 (
+,/,=), so a gateway response can be sent back unchanged in a later edit request. image_urlfetch timeout is controlled byIMAGE_INPUT_FETCH_TIMEOUT_SECONDS(default 30s). A failed fetch returns HTTP 400 with the underlying error message.
Examples
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY"
)
response = client.images.generate(
model="gemini-2.5-flash-image",
prompt="A futuristic city at sunset, cyberpunk style",
n=1,
size="1024x1024"
)
print(response.data[0].url)
Python (FLUX)
response = client.images.generate(
model="FLUX.2-pro",
prompt="Product photography of a ceramic teapot, studio light",
n=1,
quality="hd",
extra_body={
"aspect_ratio": "16:9",
"reference_images": [
{"image_url": "https://cdn.example.com/ref-1.png"},
],
},
)
print(response.data[0].url)
Python (Base64 Response)
response = client.images.generate(
model="gemini-3-pro-image",
prompt="A cute robot reading a book",
n=1,
size="1024x1024",
response_format="b64_json"
)
import base64
image_data = base64.b64decode(response.data[0].b64_json)
with open("robot.png", "wb") as f:
f.write(image_data)
cURL
curl https://gateway.api429.com/v1/images/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash-image",
"prompt": "A mountain landscape at sunrise",
"n": 1,
"size": "1024x1024"
}'
Response Format
{
"created": 1712345678,
"data": [
{
"url": "https://storage.googleapis.com/generated/...",
"revised_prompt": "A futuristic city at sunset, cyberpunk style"
}
]
}
With response_format: "b64_json":
{
"created": 1712345678,
"data": [
{
"b64_json": "/9j/4AAQSkZJRgABAQ...",
"revised_prompt": "A futuristic city at sunset"
}
]
}
With response_format: "url", the response always uses the url field. If
object storage upload is unavailable or fails, the value is a valid data URI
using the actual returned MIME type; the gateway does not silently switch the
field to b64_json.
nobalancerapi models
A separate catalogue enabled per account rather than served by default. If you
do not see these models in GET /v1/models, your token is not entitled to
them — ask us to enable it.
Pricing: on request. These models are billed from the actual cost of each
job rather than a flat per-image rate, so the price depends on the model,
size, speed tier and — for Midjourney — how many images a job returns. We
quote per account; your effective charge always appears in
/api/client/usage/daily and in the request log.
Image generation
| Model | Notes |
|---|---|
midjourney |
Midjourney, current default version (8.1, standard queue). Returns 4 images per job |
midjourney-6.1-relax / midjourney-6.1-fast |
Version 6.1 |
midjourney-7.0-relax / midjourney-7.0-fast |
Version 7.0 |
midjourney-8.1-relax / midjourney-8.1-fast |
Version 8.1 |
flux-1 |
FLUX.1; optional checkpoint_id, sampler_id, steps, and style controls |
qwen-image |
Qwen Images, text-to-image |
sora-images |
Sora Images |
dalle-3 |
DALL·E 3 |
Midjourney flags (--ar, --s, --cref, --sref, --ow, …) are written
inside prompt and passed through unchanged, so references and blends work as
they do upstream. The request-level size / aspect_ratio fields are ignored
for these models — use --ar in the prompt instead.
A generation job always produces 4 images, you are billed for the job as a
whole, and all four are returned by default. Pass n explicitly only if you
want fewer back — it does not reduce the price.
FLUX.1 controls
Use either flux-1 or flux.1 with POST /v1/images/generations. When
omitted, the defaults are checkpoint_id=1, sampler_id=1, and steps=20.
| Field | Accepted value |
|---|---|
checkpoint_id |
Positive integer. checkpointId is an alias. |
sampler_id |
Positive integer. samplerId is an alias. |
steps |
Integer from 10 through 30. |
style |
One to three unique comma-separated indices from 0 through 49. 0 and 1 may only be used alone. |
curl https://gateway.api429.com/v1/images/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"flux-1","prompt":"A sunlit botanical illustration of native wildflowers, delicate ink lines and soft watercolor washes","checkpoint_id":5,"sampler_id":6,"steps":25,"style":"3,6,12"}'
The following authenticated discovery endpoints are non-billable:
GET /v1/yesai/flux/checkpointsGET /v1/yesai/flux/samplersGET /v1/yesai/flux/lora/models
LoRA remains prompt syntax: <lora:model_id:weight>. These controls add no
public model and do not change routing for Qwen, Nano Banana, Veo, or Gemini
Omni.
Midjourney modifications
Every generated image comes back with an id. Pass it as source_image_id
together with one of the models below to act on that image. No prompt is
needed except for mj-remix.
| Model | Result |
|---|---|
mj-upscale |
Upscale ×2, faithful to the original. Returns 1 image |
mj-upscale-creative |
Upscale ×2, adds invented detail. Returns 1 image |
mj-outpaint-x2 |
Extend on all four sides, area ×2 |
mj-outpaint-x1.5 |
Extend on all four sides, area ×1.5 |
mj-outpaint-left / mj-outpaint-right / mj-outpaint-up / mj-outpaint-down |
Extend in one direction |
mj-variations-subtle |
Variations close to the original |
mj-variations-strong |
Variations only loosely related |
mj-remix |
Re-render from new text — requires prompt |
# 1) generate — note the id on each returned image
curl https://gateway.api429.com/v1/images/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "midjourney", "prompt": "a red fox in the snow --ar 16:9"}'
# 2) upscale the one you liked
curl https://gateway.api429.com/v1/images/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "mj-upscale", "source_image_id": "103"}'
source_image_id is the numeric image id, not the image URL. An id we cannot
act on returns 400 rather than quietly producing something else.
Queue speed. Generations and modifications run on the relax queue by
default (1–12 minutes). Add "speed": "fast" to any Midjourney request to use
the fast queue (1–3 minutes) — it works for the mj-* modification models
too, which carry no speed word of their own. speed beats the speed in the
model alias, so midjourney-7.0-relax with "speed": "fast" runs fast.
Image editing
| Model | Result |
|---|---|
qwen-image-edit |
Edit by text instruction |
qwen-image-remove-bg |
Remove the background |
qwen-image-remove-watermark |
Remove watermarks |
qwen-image-colorize-1 / qwen-image-colorize-2 |
Colourise |
qwen-image-restore |
Restore damaged or low-quality photos |
qwen-image-contour |
Contour / line extraction |
qwen-image-depth |
Depth map |
qwen-image-extract-clothing |
Extract clothing |
qwen-image-make-old / qwen-image-make-young |
Age the subject up or down |
qwen-image-stylize |
Apply a style |
qwen-image-3d |
3D-style render |
acc-upper / acc-lower / acc-full |
Replace clothing from a photo — upper body, lower body, or full outfit |
Video
| Model | Result |
|---|---|
veo |
Text-to-video |
kling |
Animate a still image |
pika |
Animate a still image, Pika engine |
deepface-video |
Face replacement in video |
video-upscale |
Upscale an existing video |
Video jobs are long-running: submit, then poll for the result the same way as the other asynchronous media endpoints.
Embeddings
POST /v1/embeddings
POST /openai/v1/embeddings
POST /hf/v1/embeddings
OpenAI-compatible embedding endpoint backed by Google's Gemini embedding models. Load is spread across multiple backend pools automatically — you get high availability without managing keys or quotas.
| Model | Status | Cost | Output dim |
|---|---|---|---|
gemini-embedding-001 |
Stable | Free | 3072 (default), configurable via dimensions |
gemini-embedding-2-preview |
Preview | Free | 3072 (default) |
Single input
response = client.embeddings.create(
model="gemini-embedding-001",
input="Hello world"
)
print(response.data[0].embedding[:5])
Batch (list input)
input accepts an array of strings — all of them are embedded in a
single call:
response = client.embeddings.create(
model="gemini-embedding-001",
input=["First document", "Second document", "Third document"]
)
for emb in response.data:
print(emb.index, len(emb.embedding))
Custom output dimensionality
Pass dimensions to reduce vector size — useful for hybrid search,
nearest-neighbour indexes, or storage-constrained applications. Supported
values for gemini-embedding-001: 128, 256, 512, 768, 1536, 3072 (default).
response = client.embeddings.create(
model="gemini-embedding-001",
input="Hello world",
dimensions=768
)
assert len(response.data[0].embedding) == 768
cURL
curl https://gateway.api429.com/v1/embeddings \
-H "Authorization: Bearer $YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-embedding-001",
"input": "Hello world",
"dimensions": 768
}'
Response shape
{
"object": "list",
"model": "gemini-embedding-001",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [-0.0343, 0.0116, -0.0214, ...]
}
],
"usage": {
"prompt_tokens": 2,
"total_tokens": 2
}
}
Notes
- Endpoint is optimised for query-time embeddings (search input, RAG retrieval). Documents-for-index embeddings work the same way — vector quality is identical.
- Empty
inputreturns HTTP 400. - No streaming — embedding responses are always returned in full.
Music Generation
Music generation is asynchronous. Submit a job, poll until it finishes, then
use the returned HTTPS URL. The API token must have the async audio scope.
New active external-customer tokens receive this scope by default. Existing
managed customer and project-token policies are upgraded automatically;
explicit policies remain unchanged. A restricted model allowlist must also
contain lyria-3-pro-preview.
Available model
| Model | Output | Maximum requested duration | Price |
|---|---|---|---|
lyria-3-pro-preview |
MP3 | 184 seconds | $0.08 per completed song |
duration_seconds guides the composition but is not a frame-exact duration
guarantee. A generated song can be shorter or longer than requested.
Create a music job
curl https://gateway.api429.com/v1/music/generations \
-H "Authorization: Bearer $API429_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: launch-theme-001" \
-d '{
"model": "lyria-3-pro-preview",
"prompt": "Cinematic synth-pop at 112 BPM, restrained verse, wide uplifting chorus",
"duration_seconds": 120,
"lyrics": "[Verse]\nCity lights begin to glow\n\n[Chorus]\nWe are ready, let it show",
"instrumental": false,
"output_format": "mp3"
}'
| Field | Type | Required | Notes |
|---|---|---|---|
model |
string | No | Defaults to lyria-3-pro-preview. |
prompt |
string | Yes | Musical direction, genre, mood, instruments, tempo and structure. |
duration_seconds |
integer | No | 1..184; treated as an approximate target. |
lyrics |
string | No | May include [Verse], [Chorus] and similar section tags. |
instrumental |
boolean | No | true cannot be combined with lyrics. |
output_format |
string | No | Currently mp3 only. |
google/lyria-3-pro-preview is accepted as an input compatibility alias and
is normalized to the canonical lyria-3-pro-preview ID in job responses.
Idempotency-Key is required. Reusing the same key with the same authenticated
client returns the original job instead of creating and charging for another
generation. A new key starts a new paid generation.
The submit response is HTTP 202:
{
"id": "job_...",
"object": "music.generation.job",
"status": "queued",
"model": "lyria-3-pro-preview"
}
Poll and retrieve the song
curl https://gateway.api429.com/v1/music/generations/job_... \
-H "Authorization: Bearer $API429_TOKEN"
While work is pending, the endpoint returns the current job status. A completed job returns:
{
"object": "music.generation",
"model": "lyria-3-pro-preview",
"data": [
{
"url": "https://cdn.example/song.mp3",
"mime_type": "audio/mpeg",
"bytes": 1544920,
"sha256": "..."
}
],
"billing": {
"charged_amount_usd": "0.08",
"unit_price_usd": "0.08",
"currency": "USD",
"pricing_status": "charged"
}
}
If the final upstream outcome cannot be determined safely, the job is marked
ambiguous and is not retried automatically. This prevents a second paid song
from being created behind the same job. Use a new idempotency key only after
checking the final status.
Video Generation Models
Video generation is asynchronous. Submit a job, poll until it finishes, then use the returned HTTPS CDN URL. The gateway does not return direct upstream storage URLs to clients.
The API token must have the async video scope. New active tokens classified
as external customers receive both video and audio by default; either can
be revoked in the admin UI. Async text and image remain opt-in, and existing
explicit token policies are never overwritten by the managed customer
default.
Available Models
| Model | Mode | Price per second, audio | Price per second, no audio | Durations | Samples | Resolutions |
|---|---|---|---|---|---|---|
gemini-omni-1.1-flash |
Omni 1.1 | resolution-dependent token usage, plus input/thinking | Not supported; audio is always generated | 3-10 sec | 1 | 360p, 720p, 1080p, 4k |
veo-3.1-generate-001 |
Standard | $0.40 (720p/1080p), $0.60 (4k) |
$0.20 (720p/1080p), $0.40 (4k) |
4, 6, 8 sec | 1-4 | 720p, 1080p, 4k |
veo-3.1-fast-generate-001 |
Fast | $0.10 (720p), $0.12 (1080p), $0.30 (4k) |
$0.08 (720p), $0.10 (1080p), $0.25 (4k) |
4, 6, 8 sec | 1-4 | 720p, 1080p, 4k |
veo-3.1-lite-generate-001 |
Lite | $0.05 (720p), $0.08 (1080p) |
$0.03 (720p), $0.05 (1080p) |
4, 6, 8 sec | 1-4 | 720p, 1080p |
veo-3-fast |
Fast | n/a | $0.50 base (5s) | 5 sec | 1 | 9:16, 16:9, auto |
veo-3-quality |
Quality | n/a | $1.50 base (5s) | 5 sec | 1 | 9:16, 16:9, auto |
pika-2.2 |
Image-animation | n/a | $0.50 per video | up to 6s | 1 | image-driven |
kling-1.6 / kling-2.0 / kling-2.5 / kling-3.0 |
Image+prompt → video | n/a | $0.375 base (5s); scales linearly for 10s/15s | 5, 10, 15 sec (15s on kling-3.0 only) |
1 | 1:1, 9:16, 16:9 |
deepface-video |
Face swap in video | n/a | $0.05 base | input video length | 1 | inherits input |
upscale-video-hd / -fhd / -4k |
Video upscaler | n/a | $0.30 / $0.60 / $2.40 base (30s clip) | input video length | 1 | output: 720p / 1080p / 2160p |
Gemini Omni 1.1 Flash
Use the stable client model ID gemini-omni-1.1-flash. The deprecated
gemini-omni-flash-preview and short gemini-omni-flash spellings are accepted
as input-only aliases and resolve to the new canonical ID. API429 does not
silently substitute Veo or another video provider.
API429 currently authenticates this route through Google Cloud Enterprise
Agent Platform, where Google exposes the 1.1 model under the provider-specific
wire ID gemini-omni-1.1-flash-preview. The job response therefore keeps
model:"gemini-omni-1.1-flash" as the client contract and reports the actual
Google wire ID separately in metadata.actual_model. The no-suffix ID is the
stable Gemini Developer API ID; the transport distinction is intentional and
observable rather than hidden.
Supported Omni workflows:
mode / task |
Required input | Notes |
|---|---|---|
text_to_video |
prompt |
Default when no media is supplied. |
image_to_video / first_last_frame / interpolation |
image |
Animate one image, or send image plus last_frame for first/last-frame interpolation. The aliases normalize to image_to_video. |
reference_to_video |
reference_images |
Up to 10 image references. |
edit |
video or previous_job_id |
Edit one source video under 10 seconds or continue a prior Omni result. |
extend / video_extension |
video |
Generate a 3-10 second continuation at the end of one source video. |
Omni media can be supplied as a public HTTPS URL, a gs:// URI, a base64/data
URI string, or an object such as
{"url":"https://.../image.png","mime_type":"image/png"}. API429 stages
external inputs privately before calling Google.
Omni accepts duration from 3 through 10 seconds, aspect_ratio of 16:9 or
9:16, one output, and resolution of 360p, 720p (default), 1080p, or
4k. The 1080p and 4k outputs are upscaled by Google. Optional controls are
temperature (0..2), top_p (0..1), and thinking_level (minimal, low,
medium, high). Audio is always generated: omit audio or send
audio:true; audio:false is rejected.
seed exists in the generic Interactions schema but is not documented as a
Gemini Omni model parameter, so API429 rejects it instead of pretending the
result is reproducible.
Official Agent Platform list rates used by API429 are $1.50 per 1M input tokens,
$9.00 per 1M text/thought output tokens, and $17.50 per 1M video output tokens.
Google accounts for video output at 1,931 tokens/sec for 360p, 5,792 for
720p, 8,688 for 1080p, and 17,376 for 4k (about $0.0338, $0.1014,
$0.1520, and $0.3041 per generated second respectively). API429 reserves a
conservative resolution-aware maximum before the worker calls Google and
refunds the difference after Google returns native usage. If native usage is
unavailable, the resolution-specific fallback is retained and the job is
marked accordingly instead of being billed as zero.
The Omni model does not support Chat Completions, system instructions, structured/JSON output, context caching, grounding/search, function calling, code execution, or audio references. Unsupported combinations return a validation error rather than silently degrading to another behavior.
Omni Submit Example
curl -X POST "https://gateway.api429.com/v1/videos/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: omni-video-001" \
-d '{
"model": "gemini-omni-1.1-flash",
"prompt": "A cinematic five-second product shot of a blue cup",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"thinking_level": "high"
}'
Image-to-video changes only the mode and input:
{
"model": "gemini-omni-1.1-flash",
"mode": "image_to_video",
"prompt": "The camera slowly moves around the product",
"image": {
"url": "https://example.com/product.png",
"mime_type": "image/png"
},
"duration": 6,
"aspect_ratio": "9:16"
}
To continue editing a completed Omni result, submit a new request owned by the
same API key with mode:"edit" and previous_job_id set to the previous API429
job ID. API429 follows Google's official multi-turn format: it loads the prior
safe Agent Platform history (user_input, thought signature/summary, and
model_output) from encrypted, owner-checked job state and appends the new
instruction as a user_input step. Inline media bytes are not retained in the
history; private gs:// references are used instead. Clients never submit a
raw Google interaction ID or upstream GCS path. Continuation availability
follows the API429 async-job and GCS lifecycle configured by the operator.
Veo 3.1
For Veo, total estimated charge is
price_per_second * duration_seconds * sample_count. The gateway reserves the
estimated amount when the job is accepted. If the request fails before upstream
video generation starts, the reservation is released. If the upstream operation
has started, billing is finalized even if the final status is ambiguous.
Supported aspect ratios are 16:9 and 9:16. seed, when supplied, must be
an unsigned 32-bit integer. audio / generateAudio is forwarded to Vertex as
generateAudio.
Supported API429 mode values:
mode |
Required input | Notes |
|---|---|---|
text_to_video |
prompt |
Used when no media input is provided. |
image_to_video |
image |
Uses Vertex instances[].image. |
first_last_frame |
image, last_frame |
Uses Vertex instances[].image and instances[].lastFrame. |
frame_interpolation |
image, last_frame |
Alias for the same first/last frame Vertex shape. |
video_extension |
video |
Uses Vertex instances[].video. |
reference_guided |
reference_images |
Veo 3.1 supports referenceType: "asset" subject/product/person references. Style references are rejected for Veo 3.1. |
first_last_frame requires image and last_frame and is executed only by
Google Vertex Veo. video_extension requires video; clients must omit both
duration_seconds and duration, and the balancer omits Vertex
durationSeconds because extension adds a fixed seven seconds. Neither mode
falls back to an alternate video backend. After an uncertain upstream submit the async
job may become ambiguous; poll that original job and do not automatically
create a replacement paid request.
If mode is omitted or set to auto, API429 infers it from the supplied media
fields: video → video_extension, reference_images → reference_guided,
image + last_frame → first_last_frame, image → image_to_video, and no
media → text_to_video.
API429/OpenAI-style Endpoint
POST /v1/videos/generations
GET /v1/videos/generations/{job_id}
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
model |
string | Yes | - | One of the video model IDs above |
mode / task |
string | No | auto |
Workflow supported by the selected model. Omni: text_to_video, image_to_video (first_last_frame / interpolation aliases), reference_to_video, edit, extend (video_extension / extension aliases). Veo modes are listed above. |
prompt |
string | Yes | - | Text prompt |
duration / duration_seconds |
integer | No | 8 |
Omni: 3-10. Veo: 4, 6, or 8; omit both fields for video_extension. |
n / sampleCount / sample_count |
integer | No | 1 |
Omni: exactly 1. Veo: 1-4. |
aspectRatio / aspect_ratio |
string | No | 16:9 |
16:9 or 9:16 |
resolution |
string | No | 720p |
Omni: 360p, 720p, 1080p, or 4k. Veo: 720p, 1080p, or 4k where supported. |
audio / generateAudio |
boolean | No | model-specific | Omni always generates audio. Veo forwards this control where supported. |
resizeMode / resize_mode |
string | No | - | crop or pad for image inputs |
cameraControl / camera_control |
string | No | - | Image-driven modes only; forwarded to Vertex as-is so preview/advanced camera controls can work when supported |
compressionQuality / compression_quality |
string | No | - | Advanced passthrough to Vertex; unsupported combinations return the Vertex error |
negativePrompt / negative_prompt |
string | No | - | Content to avoid |
personGeneration / person_generation |
string | No | - | Person generation policy |
seed |
integer | No | - | Veo only: unsigned 32-bit seed. Omni rejects it. |
temperature |
number | No | provider default | Omni only, 0..2. |
top_p / topP |
number | No | provider default | Omni only, 0..1. |
thinking_level / reasoning_effort |
string | No | provider default | Omni: minimal, low, medium, or high. |
previous_job_id |
string | No | - | Continue editing a prior Omni job owned by the same API key. |
image, lastFrame, referenceImages, video, inputs |
string/object/array | No | - | Optional media references. Public HTTPS URLs, gs://, data/base64, and media objects are accepted for Omni. |
Submit Example
curl -X POST "https://gateway.api429.com/v1/videos/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: video-job-001" \
-d '{
"model": "veo-3.1-fast-generate-001",
"mode": "text_to_video",
"prompt": "A calm ocean wave at sunrise, cinematic",
"duration": 4,
"n": 1,
"aspectRatio": "16:9",
"resolution": "720p",
"audio": false
}'
Image-to-video uses the same endpoint with mode: "image_to_video":
{
"model": "veo-3.1-generate-001",
"mode": "image_to_video",
"prompt": "A slow cinematic push-in over the product",
"image": {"gcsUri": "gs://client-inputs/product.png", "mimeType": "image/png"},
"cameraControl": "push_in",
"resizeMode": "crop",
"duration_seconds": 8,
"resolution": "1080p",
"audio": false
}
First/last frame generation uses mode: "first_last_frame" with image and
last_frame. Video extension uses mode: "video_extension" with video and
no duration field.
Reference-guided subject/product generation uses mode: "reference_guided" and
up to three reference_images entries with referenceType: "asset".
API429 does not silently downgrade requested Veo capabilities. Preview-gated
features such as 4k, advanced camera controls, or account/region-specific
model behavior are forwarded when the request is syntactically valid. If Vertex
rejects the combination, the async job fails with the upstream validation error
and a sanitized summary of the requested model, mode, media fields, and
parameters. Reservations are released when rejection happens before the Vertex
operation starts.
Successful submit returns 202 with a job object:
{
"id": "01HYVIDEOJOB",
"object": "video.generation.job",
"status": "queued",
"endpoint": "videos.generations"
}
Poll until status is succeeded:
curl "https://gateway.api429.com/v1/videos/generations/01HYVIDEOJOB" \
-H "Authorization: Bearer YOUR_API_KEY"
Completed jobs return data[].url values that point to downloadable video/mp4
files on the gateway CDN. A completed Omni result can also include native usage
and settled billing:
{
"object": "video.generation",
"model": "gemini-omni-1.1-flash",
"data": [
{"url": "https://cdn.example.com/video.mp4", "mime_type": "video/mp4"}
],
"usage": {
"input_tokens": 312,
"output_tokens": 28960,
"thought_tokens": 144,
"total_tokens": 29416,
"input_tokens_by_modality": {"text": 24, "image": 288},
"output_tokens_by_modality": {"video": 28960}
},
"billing": {
"charged_amount_usd": "0.508564",
"currency": "USD",
"pricing_status": "usage"
},
"metadata": {
"route_provider": "google",
"actual_model": "gemini-omni-1.1-flash-preview"
}
}
Token values above illustrate the response shape; actual usage and price depend on the request and Google's returned accounting.
Vertex-compatible Endpoints (Veo only)
These routes are intended for clients migrating from a Vertex-style SDK or REST
integration. Keep the same request body shape and change the base URL/token.
Gemini Omni uses the API429/OpenAI-style endpoint above and is not exposed as a
Vertex predictLongRunning model.
POST /v1/projects/{project}/locations/{location}/publishers/google/models/{model}:predictLongRunning
POST /v1/projects/{project}/locations/{location}/publishers/google/models/{model}:fetchPredictOperation
Auth can be sent as x-goog-api-key: YOUR_API_KEY, ?key=YOUR_API_KEY, or
Authorization: Bearer YOUR_API_KEY.
Submit Example
curl -X POST "https://gateway.api429.com/v1/projects/gateway/locations/us-central1/publishers/google/models/veo-3.1-fast-generate-001:predictLongRunning" \
-H "x-goog-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"instances": [{"prompt": "A calm ocean wave at sunrise, cinematic"}],
"parameters": {
"durationSeconds": 4,
"sampleCount": 1,
"aspectRatio": "16:9",
"resolution": "720p"
}
}'
The gateway returns an API429-managed operation name:
{
"name": "api429/jobs/01HYVIDEOJOB",
"done": false,
"metadata": {"api429JobId": "01HYVIDEOJOB", "status": "queued"}
}
Fetch operation state:
curl -X POST "https://gateway.api429.com/v1/projects/gateway/locations/us-central1/publishers/google/models/veo-3.1-fast-generate-001:fetchPredictOperation" \
-H "x-goog-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"operationName":"api429/jobs/01HYVIDEOJOB"}'
If the feature is not enabled for your account, the route returns 403, 404,
or 503. If your balance is too low for the estimated video cost, submit
returns 402.
Text-to-Speech
POST /v1/audio/speech
Single OpenAI-compatible endpoint for TTS. The Gemini model currently
supported here is gemini-3.1-flash-tts-preview. The request surface is intentionally small:
required model and input, plus optional voice and response_format.
Omitting model fails request validation with HTTP 422; the gateway does
not silently substitute a Gemini TTS model.
For Gemini TTS models the response is a full WAV body (audio/wav,
24 kHz mono PCM-16). ElevenLabs models return MP3 (audio/mpeg).
response_format is accepted for SDK compatibility, but it does not change
Gemini output.
TTS surface support matrix
| Surface | Route / API | Supported controls | Output / caveats |
|---|---|---|---|
| OpenAI-compatible gateway | POST /v1/audio/speech |
model, input, voice, response_format, delivery |
Full-body response. Gemini returns WAV; ElevenLabs returns MP3. No temperature, languageCode, first-class multi-speaker, streaming, or Cloud audioConfig passthrough. |
| Gemini-native gateway | POST /gemini/v1beta/models/{model}:generateContent |
responseModalities: ["AUDIO"], speechConfig.voiceConfig, multiSpeakerVoiceConfig, languageCode, temperature |
Non-streaming through this balancer. Response is Gemini JSON with base64 raw PCM; wrap into WAV client-side. |
| Cloud Text-to-Speech direct | Google Cloud text:synthesize / text:streamingSynthesize |
prompt + text, audioEncoding, sampleRateHertz, speed, volume gain, MultiSpeakerMarkup, streaming, advancedVoiceOptions.safetySettings |
Use Google Cloud auth directly. These controls are not proxied by /v1/audio/speech. |
Available models
| Model | Status | Text in / 1M | Audio out / 1M tokens | Derived base / 1K chars | API429 / 1K chars* | Output |
|---|---|---|---|---|---|---|
gemini-3.1-flash-tts-preview |
Current API429 Gemini TTS model | $1.00 | $20 | $0.0370 | $0.0111 | audio/wav |
Google API surface matters.
gemini-2.5-flash-ttsis a model ID for Google's separate Cloud Text-to-Speech API. It is not valid on GeminigenerateContent, and API429 does not currently proxy Cloud TTStext:synthesizeortext:streamingSynthesize. A400 INVALID_ARGUMENTfromgenerateContentfor that ID is an endpoint/model mismatch, not a missing Cloud API switch on the API429 gateway.
ElevenLabs model
| Model | Best for | Official / 1K chars | API429 / 1K chars* | Output |
|---|---|---|---|---|
elevenlabs-gen |
Expressive ElevenLabs speech and character voices, 70+ languages | $0.100 | $0.030 | audio/mpeg |
* The API429 column applies the standard 70% client discount to the $0.0370 base rate: $0.0370 × 30% = $0.0111 per 1K characters. A per-client billing profile may override the discount shown here.
elevenlabs-gen is the single canonical ElevenLabs model. Pass the native
ElevenLabs voice ID in the standard OpenAI-compatible voice field; if you
omit it or pass an unrecognized name, a default voice is used.
It is served by three interchangeable backends tried in order until one
returns audio. You are always billed at the elevenlabs-gen rate above no
matter which backend served the request, so the price is identical every
time. Long input is chunked and returned as a single joined MP3 — you never
receive an archive.
The legacy ids eleven_v3, eleven_multilingual_v2, eleven_flash_v2_5
and api429-tts remain accepted for backward compatibility but are no
longer listed in GET /v1/models; new integrations should use
elevenlabs-gen.
If the speech provider's content filter blocks part of your text, the
request returns 422 naming how many fragments were rejected; rephrase
the flagged wording and retry.
curl https://gateway.api429.com/v1/audio/speech \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "elevenlabs-gen",
"voice": "hpp4J3VqNfWAUOO0d1Us",
"input": "Привет! Это озвучка ElevenLabs через API429."
}' \
--output speech.mp3
Fish Audio model
| Model | Best for | Official / 1K chars | API429 / 1K chars* | Output |
|---|---|---|---|---|
fish-s2.1-pro |
Long-form narration, 80+ languages, large public voice library | $0.015 | $0.0045 | audio/mpeg |
* The API429 column shows the standard 70% client discount. A per-client billing profile may override the discount shown here.
Pass a Fish voice id (the 32-character hex id of a voice) in the standard
voice field. Omit it, or pass a name the provider does not recognize, and a
default voice is used. Voices carry their own language tags, and many are
multilingual — one voice often covers several languages, so you rarely need a
separate voice per market.
Output format. fish-s2.1-pro honours response_format: mp3 (default),
wav, pcm and opus. Use wav when the consumer requires RIFF/WAVE — some
post-processing pipelines reject MP3. WAV is roughly six times larger than the
same audio as MP3, so prefer mp3 unless you specifically need RIFF.
Long input is handled for you. Text longer than a few thousand characters
is split on sentence boundaries, synthesised in parallel and returned as a
single joined clip — never an archive, and never a word cut in half. An hour of
narration (~60 000 characters) takes roughly three minutes end to end. opus
is the one exception: it cannot be joined safely, so long input in that format
returns 400 — use mp3, wav or pcm instead.
Billing note. The provider meters UTF-8 bytes, while the rate above is per character. Latin text is one byte per character, but Cyrillic is two and CJK three, so non-Latin narration costs proportionally more upstream than the per-character figure suggests. Always use the authoritative bill in
/api/client/usage/dailyfor budgeting.
curl https://gateway.api429.com/v1/audio/speech \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "fish-s2.1-pro",
"input": "Привет! Это озвучка Fish Audio через API429.",
"response_format": "wav"
}' \
--output speech.wav
Getting a link instead of a file
An hour of narration is about 10 MB as MP3 and far more as WAV, which is
awkward to carry in a synchronous response body. Set "delivery": "url" and
the clip is uploaded to our CDN and described by a small JSON body instead:
curl https://gateway.api429.com/v1/audio/speech \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "fish-s2.1-pro",
"input": "…длинный текст ролика…",
"delivery": "url"
}'
{
"url": "https://api429.lon1.cdn.digitaloceanspaces.com/api429/tts/…mp3",
"mime": "audio/mpeg",
"bytes": 10452992
}
Omit delivery (or send "inline") and you get the raw audio bytes exactly as
before — the default is unchanged.
gemini-3.1-flash-tts-preview currently has a documented 8,192 input-token
limit and 16,384 output-token limit. Upstream Batch API is supported for that
model, while caching, function calling, Live API, structured output, code
execution, grounding, and URL context are not.
* How we derive the effective rate. Google bills TTS per audio token: 1 second of output = 25 audio tokens. English speech averages 13.5 chars/sec, so 1M audio tokens ≈ 40 000 s ≈ 540 000 chars.
$20 / 1M audio tokens × (1M / 540K) = $0.03704 per 1K chars (Gemini 3.1) $0.0370 rounded base rate × 30% after the standard 70% discount = $0.0111 billedRussian / CJK speech is slower (~10–12 chars/sec) → our per-char rate slightly under-bills non-English traffic (error <25%). For budget planning always use the authoritative bill reported by
/api/client/usage/daily— it reflects the actual Google charge, not this estimate.Text input ($1.00 / 1M text tokens) adds <5 % to the total for typical TTS requests, so clients can usually plan on just the audio-output rate.
Quick start (OpenAI-compatible)
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
response = client.audio.speech.create(
model="gemini-3.1-flash-tts-preview", # current Gemini TTS model
voice="Kore",
input="Hello, welcome to our API."
)
response.stream_to_file("output.wav")
curl https://gateway.api429.com/v1/audio/speech \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-o output.wav \
-d '{
"model": "gemini-3.1-flash-tts-preview",
"voice": "Kore",
"input": "Hello, welcome to our API."
}'
// Node.js / TypeScript via the official OpenAI SDK
import OpenAI from "openai";
import { writeFile } from "node:fs/promises";
const client = new OpenAI({
baseURL: "https://gateway.api429.com/v1",
apiKey: process.env.BALANCER_API_KEY!,
});
const speech = await client.audio.speech.create({
model: "gemini-3.1-flash-tts-preview",
voice: "Kore",
input: "Hello, welcome to our API.",
});
await writeFile("output.wav", Buffer.from(await speech.arrayBuffer()));
// Node.js / browser via plain fetch (no SDK dependency)
const res = await fetch("https://gateway.api429.com/v1/audio/speech", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.BALANCER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gemini-3.1-flash-tts-preview",
voice: "Kore",
input: "Hello, welcome to our API.",
}),
});
if (!res.ok) {
const err = await res.json();
throw new Error(`TTS failed: ${err.error?.message ?? res.status}`);
}
const wav = Buffer.from(await res.arrayBuffer());
require("node:fs").writeFileSync("output.wav", wav);
OpenAI SDK example with expressive tags
Gemini 3.1 Flash TTS Preview adds expressive bracket tags for narrative control. Keep the tags in English even when the spoken text is Russian or another language.
response = client.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Puck",
input=(
"Прочитай как тревожный рассказчик: "
"Я открыл дверь. [short pause] Там никого не было. [gasp]"
),
)
response.stream_to_file("tagged.wav")
response_formatfield. All Gemini TTS calls returnaudio/wavregardless of whatresponse_formatyou pass. The OpenAI SDK exposesresponse_formatfor compatibility, but the upstream doesn't honourmp3/opus/aac/flac/pcm— you'll always get the same 24 kHz mono PCM-16 WAV body. Convert withffmpegclient-side if you need a different container.
Voice library (30 prebuilt voices)
Gemini TTS ships with 30 distinct voices. Each carries a unique tonal character; pick one that matches your use case.
All previews speak the same English pangram ("The quick brown fox jumps over the lazy dog.") so you can A/B them by ear. Russian / CJK delivery sounds slightly different but maintains the same character.
Female voices (14):
| Voice | Character | Preview |
|---|---|---|
Achernar |
Soft | |
Aoede |
Breezy | |
Autonoe |
Bright | |
Callirrhoe |
Easy-going | |
Despina |
Smooth | |
Erinome |
Clear | |
Gacrux |
Mature | |
Kore ⭐ |
Firm | |
Laomedeia |
Upbeat | |
Leda |
Youthful | |
Pulcherrima |
Forward | |
Sulafat |
Warm | |
Vindemiatrix |
Gentle | |
Zephyr |
Bright |
Male voices (16):
| Voice | Character | Preview |
|---|---|---|
Achird |
Friendly | |
Algenib |
Gravelly | |
Algieba |
Smooth | |
Alnilam |
Firm | |
Charon |
Informative | |
Enceladus |
Breathy | |
Fenrir |
Excitable | |
Iapetus |
Clear | |
Orus |
Firm | |
Puck |
Upbeat | |
Rasalgethi |
Informative | |
Sadachbia |
Lively | |
Sadaltager |
Knowledgeable | |
Schedar |
Even | |
Umbriel |
Easy-going | |
Zubenelgenubi |
Casual |
⭐ Kore is the balancer default if voice is omitted or unknown.
Unknown voice names silently fall back to Kore — the balancer
whitelists names before forwarding to upstream.
Note for offline / GitHub readers. The previews above are hosted at
https://hostkey24760.api429.com/admin-panel/front-max/voice-samples/<Voice>.mp3— public, no auth required. If you're reading this on GitHub or in an offline mirror, pop the URLs into your browser to listen. Alternative: Google's interactive AI Studio Voice Library plays each voice with multiple sample phrases.
Voice picker by use-case
Quick guide to narrow 30 → 1 by what you're building. All recommendations are subjective — listen to the previews and trust your ears.
| Use-case | Recommended voices | Why |
|---|---|---|
| Audiobook narration (calm, sustained) | Sulafat, Charon, Rasalgethi, Vindemiatrix |
Warm, even, easy to listen to for hours |
| Podcast / talk-show host (energetic) | Puck, Zephyr, Laomedeia, Sadachbia |
Upbeat, engaging, expressive intonation |
| News / weather / formal | Kore, Charon, Algieba, Schedar |
Firm, neutral, "anchor"-like delivery |
| Voice assistant / chatbot | Kore, Orus, Aoede, Achird |
Friendly, balanced, doesn't fatigue |
| Children's content | Leda, Aoede, Achird |
Youthful, breezy, approachable |
| Suspense / dramatic narration | Enceladus, Algenib, Gacrux, Fenrir |
Breathy, gravelly, mature, excitable — can carry tension |
| Russian / CJK | Kore, Charon, Sulafat, Puck |
These four hold their character cleanest in non-English |
| Two-speaker dialogue | One bright (Puck/Zephyr/Aoede) + one firm (Kore/Charon) |
Maximum tonal contrast for clarity |
Languages
Gemini TTS auto-detects the language from the input text. 24 languages GA:
Arabic (Egypt), Bangla (Bangladesh), Dutch, English (India, US), French, German, Hindi, Indonesian, Italian, Japanese, Korean, Marathi, Polish, Portuguese (Brazil), Romanian, Russian, Spanish (Spain), Tamil, Telugu, Thai, Turkish, Ukrainian, Vietnamese.
50+ more in Preview (Chinese Mandarin, Greek, Hebrew, Norwegian, Swedish, Czech, and more — see Google's official list).
# Russian — just write the text, no extra parameter needed
response = client.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Kore",
input="Привет, как твои дела сегодня?",
)
Style control
Two mechanisms can shape delivery:
1. Natural-language style prefix
Prepend a style instruction to the text.
client.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Enceladus",
input="Say in a spooky whisper: Something wicked this way comes.",
)
client.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Puck",
input="Read excitedly, like breaking news: The rocket has landed!",
)
2. Expressive audio tags
Square-bracket tags mid-sentence control non-speech sounds and pacing. Google does not publish an exhaustive taxonomy; treat the list below as official/common examples from Gemini API and Cloud TTS docs, then test the exact phrasing with your voice and language.
client.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Puck",
input="That joke was amazing. [laughs] I cannot stop thinking about it. [short pause] But seriously…",
)
Common modes:
Non-speech sounds — vocal inserts:
| Tag | Effect |
|---|---|
[sigh] / [sighs] |
Exhale |
[laughs] / [laughing] / [giggles] |
Chuckle or laughter |
[gasp] |
Surprised inhale |
[uhm] |
Filler sound |
[cough] / [coughs] |
Cough |
[chuckling] |
Low laugh while speaking |
Style modifiers — change delivery characteristics:
| Tag | Effect |
|---|---|
[whispers] / [whispering] |
Lower volume, breathy |
[shouting] |
Higher energy, louder |
[sarcasm] / [sarcastically] |
Dry, deadpan delivery |
[robotic] |
Synthetic, flat affect |
[extremely fast] / [very fast] |
Accelerated pace |
[very slow] |
Slower delivery |
Vocalized markup — emotional colouring:
| Tag | Effect |
|---|---|
[amazed] |
Amazed tone |
[crying] |
Crying tone |
[excited] / [excitedly] |
Raised pitch and pace |
[scared] |
Trembling, higher pitch |
[curious] |
Questioning intonation |
[bored] |
Flat, drawn out |
[reluctantly] / [mischievously] |
Hesitant or playful tone |
[serious] / [tired] / [panicked] / [trembling] |
Mood modifiers |
Pacing — silence gaps:
| Tag | Effect |
|---|---|
[short pause] |
~250 ms silence |
[medium pause] |
~500 ms silence |
[long pause] |
~1 s silence |
Language note: keep audio tags in English regardless of the spoken language.
[laughs]works inside a Russian sentence;[смеётся]may be read aloud literally.
Temperature (creativity control)
Gemini TTS supports a temperature parameter in the range (0.0, 2.0].
Higher values give more expressive / varied reads; lower values stay
predictable. The OpenAI-compatible endpoint doesn't expose it yet — use
the Gemini-native non-streaming endpoint if you need it:
curl "https://gateway.api429.com/gemini/v1beta/models/gemini-3.1-flash-tts-preview:generateContent" \
-H "x-goog-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"parts": [{"text": "Tell me about the stars"}]}],
"generationConfig": {
"responseModalities": ["AUDIO"],
"temperature": 1.5,
"speechConfig": {
"voiceConfig": {"prebuiltVoiceConfig": {"voiceName": "Kore"}}
}
}
}'
The Gemini-native response contains base64 raw PCM in
candidates[0].content.parts[0].inlineData.data; decode it and wrap as
24 kHz mono PCM-16 WAV client-side.
Sane starting points:
- 0.2–0.5 — narration, consistent reads, audiobooks
- 0.8–1.2 — conversational, default feel
- 1.5–2.0 — theatrical, emotional, podcast hosts
Multi-speaker dialogue
Gemini TTS can voice a conversation between up to 2 speakers in a
single call. The balancer's OpenAI-compatible endpoint doesn't
expose speaker_voice_configs yet — use the Gemini-native
non-streaming endpoint for multi-speaker output:
curl "https://gateway.api429.com/gemini/v1beta/models/gemini-3.1-flash-tts-preview:generateContent" \
-H "x-goog-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"parts": [{"text":
"TTS the following conversation:\nJoe: How is it going today Jane?\nJane: Not too bad, how about you?"
}]}],
"generationConfig": {
"responseModalities": ["AUDIO"],
"speechConfig": {
"multiSpeakerVoiceConfig": {
"speakerVoiceConfigs": [
{"speaker": "Joe", "voiceConfig": {"prebuiltVoiceConfig": {"voiceName": "Kore"}}},
{"speaker": "Jane", "voiceConfig": {"prebuiltVoiceConfig": {"voiceName": "Puck"}}}
]
}
}
}
}' | jq -r '.candidates[0].content.parts[0].inlineData.data' \
| base64 --decode > dialogue.pcm
# Wrap raw PCM 16-bit 24kHz mono into a WAV:
ffmpeg -f s16le -ar 24000 -ac 1 -i dialogue.pcm dialogue.wav
Two ways to format the dialogue in contents.parts[0].text:
(a) Freeform (shown above) — Speaker: … line prefixes in plain text.
Simplest to generate from an LLM.
(b) Structured — explicit turn list (Python SDK only):
from google import genai
from google.genai import types
client = genai.Client(
vertexai=True,
project="YOUR_GCP_PROJECT",
location="global",
)
turns = [
types.Content(role="user", parts=[
types.Part(text="Joe: How's it going today Jane?"),
]),
types.Content(role="user", parts=[
types.Part(text="Jane: Not too bad, how about you?"),
]),
]
response = client.models.generate_content(
model="gemini-3.1-flash-tts-preview",
contents=turns,
config=types.GenerateContentConfig(
response_modalities=["AUDIO"],
speech_config=types.SpeechConfig(
multi_speaker_voice_config=types.MultiSpeakerVoiceConfig(
speaker_voice_configs=[
types.SpeakerVoiceConfig(speaker="Joe",
voice_config=types.VoiceConfig(
prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Kore"))),
types.SpeakerVoiceConfig(speaker="Jane",
voice_config=types.VoiceConfig(
prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Puck"))),
]
)
),
temperature=1.5,
),
)
Pro tip: if you want multi-speaker via the OpenAI-compatible
endpoint, pre-format the text with Speaker: prefixes and let a
single voice read both parts — the model still uses the speaker
context to vary intonation slightly. Open a ticket if you need
first-class speaker_voice_configs on /v1/audio/speech.
Audio output format
| Field | Value |
|---|---|
| Container | WAV (our gateway wraps raw PCM) |
| Codec | PCM linear 16-bit little-endian |
| Sample rate | 24 000 Hz |
| Channels | Mono (1) |
| Upstream raw | 16-bit PCM 24 kHz (no header) — we prepend the 44-byte WAV header |
Input / output limits
| Constraint | Limit |
|---|---|
Recommended /v1/audio/speech chunk |
3.5–4 KB UTF-8 for reliable prosody and retries; no local 4 KB limiter was found in the gateway code |
Cloud Text-to-Speech direct prompt + text |
Up to 8 000 bytes total upstream; prompt and text are each limited to 4 000 bytes |
Vertex direct contents |
Up to 8 000 bytes upstream |
| Speech generation session/context | 32k tokens upstream |
| Gemini 3.1 Flash TTS Preview | 8,192 input tokens, 16,384 output tokens |
| Output audio duration | Around 655 seconds upstream; quality can degrade after several minutes |
| Per-minute rate | Coordinated by the balancer; no per-client cap configured by default |
Latency profile
Measured 2026-04-23 against production (median of 5 cold-start requests, 60 chars input, Kore voice):
| Model | p50 | typical | Notes |
|---|---|---|---|
gemini-3.1-flash-tts-preview |
2.2 s | 2–5 s | Current API429 Gemini TTS model |
Voice / model compatibility
gemini-3.1-flash-tts-preview supports all 30 voices listed above.
Error responses
All errors follow the OpenAI error envelope: HTTP status + a JSON body
of {"error": {"message": "...", "type": "...", "code": "..."}}. The
table covers what you'll actually encounter from /v1/audio/speech
under normal operation:
| Status | When it happens | Example body | Retryable? |
|---|---|---|---|
| 400 | A syntactically valid request is rejected by the selected TTS provider, for example empty input or an unsupported non-Gemini provider model | {"error":{"message":"input must not be empty","type":"invalid_request_error","code":"invalid_request"}} |
No — fix the request |
| 422 | Missing or blank required model, missing input, unsupported Gemini TTS ID, malformed JSON, or invalid field types |
FastAPI validation error envelope | No — fix the request |
| 401 | Missing or invalid Authorization: Bearer … header |
{"error":{"message":"Invalid authentication token","type":"invalid_request_error","code":"invalid_token"}} |
No — rotate the key |
| 413 | Provider rejects oversized input, for example Cloud/Vertex prompt + text beyond upstream byte limits |
Upstream-shaped 413 — pre-chunk, see Long-form audio below | No — split client-side |
| 429 | Per-key or per-binding rate limit hit upstream. Response carries Retry-After (seconds) |
{"error":{"message":"Rate limit exceeded","type":"rate_limit_error","code":"rate_limit"}} + Retry-After: 30 |
Yes — sleep Retry-After then retry |
| 500 | Upstream Gemini returned a 5xx, or balancer Python exception un-wrapped to FastAPI | {"error":{"message":"Internal server error","type":"internal_error","code":"500"}} |
Yes — exponential backoff, see Retry pattern |
| 502 | host nginx couldn't reach the balancer (deploy window, ~35 s) — the host nginx auto-translates this to 503 + Retry-After: 10 | (already converted to 503; see below) | n/a |
| 503 | Backend temporarily unavailable: balancer redeploy or upstream queue timeout | {"error":{"message":"Backend temporarily unavailable, retry in 10 seconds","type":"backend_unavailable","code":503,"retry_after":10}} + Retry-After: 10 |
Yes — sleep Retry-After then retry |
| 504 | Long upstream stall — rare for TTS (single-shot is short) | OpenAI-shaped 504 | Yes with caution — at most 1 retry |
How to read errors safely (Python):
from openai import OpenAI, APIError, RateLimitError, APIStatusError
client = OpenAI(base_url="https://gateway.api429.com/v1", api_key="...")
try:
resp = client.audio.speech.create(model="gemini-3.1-flash-tts-preview", voice="Kore", input=text)
except RateLimitError as e: # 429 — respect Retry-After
retry_after = int(e.response.headers.get("retry-after", "30"))
...
except APIStatusError as e:
if e.status_code in (502, 503, 504): # transient — retry
retry_after = int(e.response.headers.get("retry-after", "10"))
...
elif e.status_code in (400, 401, 413): # permanent — surface
raise
else:
raise
Retry pattern
Three rules that keep retries safe and cheap:
- Honour
Retry-Afterwhen the server sets it (429 / 503 always do). That value reflects current capacity — beating it just queues you server-side without speedup. - Exponential backoff with jitter for transient 5xx without
Retry-After. Recommended schedule:
2 s → 8 s → 30 s(max 3 attempts, ±20 % jitter). - Don't retry 400/401/413 — re-issuing the same request with the same input gets the same error and burns budget. Surface it.
Reference Python implementation
import asyncio
import random
from openai import AsyncOpenAI, APIStatusError, RateLimitError
client = AsyncOpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
async def synthesize_with_retry(*, model: str, voice: str, input: str,
max_attempts: int = 4) -> bytes:
"""Synthesize speech with bounded retry. Honours Retry-After.
Returns the full WAV bytes. Raises on permanent errors or after
``max_attempts`` transient failures.
"""
backoff_s = [2, 8, 30, 60]
for attempt in range(max_attempts):
try:
resp = await client.audio.speech.create(
model=model, voice=voice, input=input,
)
return await resp.aread()
except RateLimitError as e: # 429
wait = int(e.response.headers.get("retry-after", "30"))
except APIStatusError as e:
if e.status_code in (400, 401, 413): # permanent
raise
if e.status_code in (429, 502, 503, 504, 500) and attempt < max_attempts - 1:
wait = int(e.response.headers.get("retry-after",
str(backoff_s[attempt])))
else:
raise
wait *= (1 + random.uniform(-0.2, 0.2)) # ±20 % jitter
await asyncio.sleep(wait)
raise RuntimeError("synthesize_with_retry: all attempts failed")
Reference TypeScript implementation
import OpenAI, { APIError } from "openai";
const client = new OpenAI({
baseURL: "https://gateway.api429.com/v1",
apiKey: process.env.BALANCER_API_KEY!,
});
const BACKOFF_S = [2, 8, 30, 60];
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
export async function synthesizeWithRetry(args: {
model: string;
voice: string;
input: string;
maxAttempts?: number;
}): Promise<Buffer> {
const max = args.maxAttempts ?? 4;
for (let attempt = 0; attempt < max; attempt++) {
try {
const r = await client.audio.speech.create({
model: args.model,
voice: args.voice,
input: args.input,
});
return Buffer.from(await r.arrayBuffer());
} catch (e) {
if (!(e instanceof APIError)) throw e;
const status = e.status ?? 0;
if ([400, 401, 413].includes(status)) throw e; // permanent
if (![429, 500, 502, 503, 504].includes(status)) throw e;
if (attempt === max - 1) throw e;
const headerRetry = Number(e.headers?.["retry-after"]) || BACKOFF_S[attempt];
const jittered = headerRetry * (1 + (Math.random() - 0.5) * 0.4);
await sleep(jittered * 1000);
}
}
throw new Error("synthesizeWithRetry: exhausted");
}
Cloud-only technical controls
Google Cloud Text-to-Speech exposes lower-level controls that are useful for
direct Cloud integrations, but they are not fields on our /v1/audio/speech
route.
curl -X POST "https://texttospeech.googleapis.com/v1/text:synthesize" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "x-goog-user-project: $PROJECT_ID" \
-H "Content-Type: application/json" \
-d '{
"input": {
"prompt": "Read the following in a curious, restrained tone.",
"text": "OK, so... tell me about this [uhm] AI thing."
},
"voice": {
"languageCode": "en-us",
"name": "Kore",
"model_name": "gemini-2.5-flash-tts"
},
"audioConfig": {
"audioEncoding": "LINEAR16",
"sampleRateHertz": 24000,
"speakingRate": 1.0,
"volumeGainDb": 0.0
},
"advancedVoiceOptions": {
"safetySettings": []
}
}'
advancedVoiceOptions.safetySettings is a Cloud Text-to-Speech direct API
feature. It is intentionally not documented as a balancer request field.
Legacy relax_safety_filters / safety_settings knobs are not passed through
by the gateway.
What /v1/audio/speech does NOT expose
For completeness, these controls are not fields on the narrow OpenAI-compatible speech endpoint. Some are available through the Gemini-native gateway as shown above; Cloud-only controls require a direct Google Cloud integration:
| Feature | Upstream support | Why not exposed |
|---|---|---|
temperature |
✅ Gemini-native generateContent |
Use /gemini/v1beta/models/{model}:generateContent; /v1/audio/speech stays OpenAI-compatible |
languageCode |
✅ Gemini-native / Cloud TTS direct | Gemini auto-detects on /v1/audio/speech; explicit BCP-47 is not exposed there |
| First-class multi-speaker config | ✅ Gemini-native multiSpeakerVoiceConfig / Cloud MultiSpeakerMarkup |
Use Gemini-native route or Cloud direct for speaker-to-voice mapping |
| Alternate audio encodings (MP3, OGG_OPUS, ALAW, MULAW, PCM) | ✅ Cloud TTS direct unary calls | Gemini path returns a WAV container; some alternate aliases may return MP3 |
Custom sample rate (sampleRateHertz) |
✅ Cloud TTS direct | Gemini gateway path is fixed 24 kHz mono PCM |
| Streaming TTS (chunked audio) | ✅ Cloud TTS StreamingSynthesize; ✅ Vertex direct streaming |
Gemini Developer API TTS and our /v1/audio/speech are non-streaming full responses |
| Batch API (async bulk TTS) | ✅ Upstream for gemini-3.1-flash-tts-preview |
Not proxied by the balancer |
advancedVoiceOptions.safetySettings |
✅ Cloud TTS direct | Not a /v1/audio/speech request field |
| Custom voice cloning | ❌ Not supported by Google | Only 30 prebuilt voices — Google has no voice-cloning public API |
Full Google reference:
- Gemini Developer API: https://ai.google.dev/gemini-api/docs/speech-generation
- Vertex AI Gemini TTS: https://cloud.google.com/text-to-speech/docs/gemini-tts
- Interactive voice library: https://aistudio.google.com/apps/bundled/voice-library
Long-form audio (10+ minutes)
For audiobooks, podcasts, or any narration over several minutes, the client should split the script into chunks, synthesize them in parallel, and concatenate the WAV files locally. The balancer does not chunk, batch, or stream-merge automatically.
Use 3.5–4 KB UTF-8 as a safe recommended chunk size. The old docs
overstated this as a local cap, but no such gateway limiter was found; the real
upstream Cloud/Vertex direct prompt + text limit is 8,000 bytes, and long
single requests can degrade in quality after several minutes. Upstream output
is around 655 seconds at the high end, but chunking remains the safer
production pattern.
Sizing math
| Target audio duration | Approximate chars (English, 13.5 ch/s) | Chunks at 3 500 bytes | Wall-clock at 8 parallel × 4 s/chunk |
|---|---|---|---|
| 30 min | ~24 000 | 7 | ~4 s |
| 60 min | ~49 000 | 14 | ~8 s |
| 90 min | ~73 000 | 21 | ~12 s |
| 120 min | ~97 000 | 28 | ~16 s |
Russian / CJK speech is slower (~10–12 ch/s), so character counts run ~25 % lower for the same duration. Cost scales linearly with input characters at the rate listed in Available models above (e.g. 90 min Flash ≈ $1.35).
Chunking strategy
- Split at sentence boundaries so prosody isn't broken mid-phrase.
- Bin-pack chunks around 3 500 bytes UTF-8 (leaving head-room for style prefixes, transcript tags, and retries).
- Preserve order — parallel synthesis must reassemble in input order on concat, not in completion order.
Parallel synthesis
5–10 concurrent requests is a safe ceiling. The balancer spreads parallel calls across multiple bindings automatically; pushing past 10 just queues server-side without speedup.
Concatenation
All Gemini TTS responses are 24 kHz mono PCM-16 WAV (see Audio output format above). Identical sample rate / channel layout means you can concatenate the audio payloads directly without re-encoding. Two practical options:
- Python
wavestdlib — read all WAVs, write one combined file. Zero external dependencies. - ffmpeg —
ffmpeg -f concat -safe 0 -i list.txt -c copy out.wavwithlist.txtlisting chunk filenames in order.
Full Python example (split → gather → concat)
import asyncio
import io
import re
import wave
from openai import AsyncOpenAI
client = AsyncOpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY",
)
CHUNK_BUDGET_BYTES = 3500 # leave 500 B for the balancer's style prefix
PARALLELISM = 8 # 5-10 is safe; >10 just queues server-side
def split_into_chunks(text: str, budget: int = CHUNK_BUDGET_BYTES) -> list[str]:
"""Split text at sentence boundaries, bin-pack to ≤budget bytes UTF-8."""
sentences = re.split(r"(?<=[.!?])\s+", text.strip())
chunks: list[str] = []
buf = ""
for sent in sentences:
candidate = (buf + " " + sent).strip()
if len(candidate.encode("utf-8")) > budget and buf:
chunks.append(buf)
buf = sent
else:
buf = candidate
if buf:
chunks.append(buf)
return chunks
async def synthesize_one(idx: int, text: str, sem: asyncio.Semaphore) -> tuple[int, bytes]:
async with sem:
resp = await client.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Kore",
input=text,
)
return idx, await resp.aread()
async def synthesize_long(text: str, out_path: str) -> None:
chunks = split_into_chunks(text)
sem = asyncio.Semaphore(PARALLELISM)
results = await asyncio.gather(
*(synthesize_one(i, c, sem) for i, c in enumerate(chunks))
)
# Reassemble in original order (gather preserves input order, but
# we tag explicitly so partial-result paths stay safe).
results.sort(key=lambda x: x[0])
with wave.open(out_path, "wb") as out_wav:
params_set = False
for _, wav_bytes in results:
with wave.open(io.BytesIO(wav_bytes), "rb") as in_wav:
if not params_set:
out_wav.setparams(in_wav.getparams())
params_set = True
out_wav.writeframes(in_wav.readframes(in_wav.getnframes()))
# Usage:
# asyncio.run(synthesize_long(open("script.txt").read(), "narration.wav"))
Failure handling tips
- Wrap
synthesize_onein afor attempt in range(3)retry loop — individual chunks may hit upstream 429 / 5xx independently. The balancer already retries internally, but a top-level client retry protects against rare wall-clock timeouts. - If one chunk consistently fails after retries, you can either fail
the whole job, or skip with silence padding (
b"\x00" * bytes_per_second * estimated_seconds) so the WAV stays the expected length — depends on whether your downstream tolerates gaps. - Track per-chunk usage: each call is billed independently
(
/api/client/usage/dailyaggregates them).
When to ask for server-side support
If you're regularly generating audio over ~30 minutes and the
client-side concat is operationally painful (e.g. mobile clients,
browser environments without wave stdlib), open a ticket — we can
prioritise a server-side /v1/audio/speech/long endpoint that
chunks, fans-out, and returns one WAV in a single HTTP response.
Integration recipes
End-to-end snippets for common products. Each is self-contained and
uses only the public /v1/audio/speech endpoint.
1. Telegram bot — voice replies
# pip install python-telegram-bot openai
import io, os
from openai import OpenAI
from telegram import Update
from telegram.ext import Application, MessageHandler, ContextTypes, filters
tts = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key=os.environ["BALANCER_API_KEY"],
)
async def voice_reply(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
text = update.message.text or "Hello!"
if len(text.encode("utf-8")) > 4000:
await update.message.reply_text("Sorry, message too long for TTS.")
return
speech = tts.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Kore",
input=text,
)
# Telegram accepts WAV directly via send_voice (or send_audio for file).
await update.message.reply_voice(io.BytesIO(speech.read()))
app = Application.builder().token(os.environ["TELEGRAM_BOT_TOKEN"]).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, voice_reply))
app.run_polling()
2. Audiobook from a .txt file
Reuses the chunking helper from Long-form audio — wires it to a
plain text file and produces one WAV. Picks Sulafat (warm, sustained)
which works well for hours of narration.
import asyncio
from pathlib import Path
# ...split_into_chunks, synthesize_one, synthesize_long defined in
# the "Long-form audio" section above...
async def audiobook(in_path: str, out_path: str, voice: str = "Sulafat") -> None:
text = Path(in_path).read_text(encoding="utf-8")
# Override the default voice in synthesize_one by using a partial
# or just pass it through — see Long-form Python example.
await synthesize_long(text, out_path, voice=voice, model="gemini-3.1-flash-tts-preview")
# CLI: python audiobook.py book.txt narration.wav
if __name__ == "__main__":
import sys
asyncio.run(audiobook(sys.argv[1], sys.argv[2]))
3. Chat narration — LLM reply read aloud
Pipes a chat-completions response through TTS. Uses two streams in parallel: the text stream is consumed by the speaker, the audio job runs on the assembled chunks.
import os
from openai import OpenAI
llm = OpenAI(base_url="https://gateway.api429.com/v1",
api_key=os.environ["BALANCER_API_KEY"])
# 1) Get a chat reply
chat = llm.chat.completions.create(
model="claude-sonnet-4-5",
messages=[{"role": "user", "content": "Tell me a 3-sentence bedtime story."}],
max_tokens=200,
)
reply_text = chat.choices[0].message.content
# 2) TTS it (single-shot — short replies fit comfortably)
speech = llm.audio.speech.create(
model="gemini-3.1-flash-tts-preview",
voice="Despina", # smooth, calming for bedtime
input=reply_text,
)
with open("story.wav", "wb") as f:
f.write(speech.read())
4. Web-app preview button
Browser fetches via the same Bearer token. Keep the token server-side in production — this snippet is for an authenticated admin UI where the token is already in scope.
<button id="preview" data-text="Hello, this is a preview." data-voice="Puck">▶</button>
<audio id="player" controls></audio>
<script>
document.getElementById("preview").addEventListener("click", async (e) => {
const btn = e.currentTarget;
const res = await fetch("https://gateway.api429.com/v1/audio/speech", {
method: "POST",
headers: {
"Authorization": `Bearer ${window.YOUR_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gemini-3.1-flash-tts-preview",
voice: btn.dataset.voice,
input: btn.dataset.text,
}),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
alert("TTS failed: " + (err.error?.message ?? res.status));
return;
}
const blob = await res.blob();
document.getElementById("player").src = URL.createObjectURL(blob);
document.getElementById("player").play();
});
</script>
Integration Cookbook
Use this section when adapting an existing client or debugging a request that works against one vendor SDK but fails through the gateway.
Pick the endpoint by workload
| Workload | Endpoint | Model examples | Notes |
|---|---|---|---|
| Text chat | POST /v1/chat/completions |
gemini-3.1-pro, claude-sonnet-5, gpt-5.4 |
Standard OpenAI Chat Completions shape. |
| GPT reasoning / tool workflows | POST /v1/responses |
gpt-5.5, gpt-5.4, gpt-5.3-codex |
Recommended for GPT-5.x reasoning and tool state. |
| Text-to-image | POST /v1/images/generations |
gpt-image-2, gemini-3-pro-image, FLUX.2-pro |
JSON request body. |
| Image edit / image-to-image | POST /v1/images/edits |
gpt-image-2, gemini-3-pro-image |
Multipart form request with one or more image files. |
| Embeddings | POST /v1/embeddings |
gemini-embedding-001 |
Non-streaming vector output. |
| TTS | POST /v1/audio/speech |
gemini-3.1-flash-tts-preview |
Full audio body response; Gemini returns WAV. |
| Gemini native multimodal | /gemini/v1beta/models/{model}:generateContent |
gemini-* |
Use when your client already sends Google contents.parts with inline_data or fileData. |
Always call GET /v1/models with the same API key you will use in production
before exposing a model in your UI. The response is filtered by the token's
allowed models.
Multimodal request formats
OpenAI-compatible chat vision:
{
"model": "gemini-3.1-pro",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image"},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}}
]
}]
}
Gemini-native multimodal:
{
"contents": [{
"role": "user",
"parts": [
{"text": "Describe this image"},
{"inline_data": {"mime_type": "image/jpeg", "data": "<BASE64_IMAGE_DATA>"}}
]
}]
}
Use the native Gemini route only when your client already speaks Gemini's
contents.parts format. OpenAI SDK clients should use the OpenAI-compatible
messages[].content[] format above.
For Gemini-native media, inlineData.data / inline_data.data and
thoughtSignature inputs accept either standard base64 or URL-safe base64,
with or without padding. API429 responses use canonical padded standard
base64. This makes response → next-request round trips safe without a client
re-encoding step.
Streaming clients
- Read SSE until
data: [DONE]. - Ignore SSE comments and empty lines.
- Do not convert "stream returned 0 chunks" into an immediate second non-streaming request for long jobs; that can duplicate work and cost.
- If the HTTP request fails before any SSE data is processed, retry with exponential backoff.
- If an
event: errorarrives after text/audio/image work has started, treat it as a failed attempt and retry only according to your product's idempotency policy.
Retries and rate limits
- Respect
Retry-Afterwhen present. - Retry 429, 503, 504 and transient network errors with backoff.
- Do not hot-loop retries. Use jitter and cap retries.
- For long Claude text jobs, prefer
stream:truefor interactive UX orX-Async-Jobs-Optin: truefor non-streaming durable execution.
Common request fixes
| Symptom | Likely cause | Fix |
|---|---|---|
404 on a documentation .md link |
Separate markdown guides are not served publicly | Use this /documentation page; all public examples are here. |
model_not_found or model_not_allowed |
Token allowlist does not include the requested model | Call GET /v1/models with the same key and use one of those IDs. |
| Image edit fails with JSON body | /v1/images/edits expects multipart form |
Send -F "image=@file.png" and -F "prompt=...". |
| Gemini image-to-image payload is rejected | Client sends Google inline_data to an OpenAI-compatible endpoint |
Use /gemini/v1beta/models/{model}:generateContent for Gemini-native payloads, or use /v1/images/edits multipart. |
| TTS response cannot be parsed as JSON | /v1/audio/speech returns binary audio |
Read the response as bytes/blob and save/play it as WAV or MP3. |
| Claude streaming appears idle | Client waits for final response instead of reading SSE | Use stream:true, parse chunks incrementally, and keep a long read timeout. |
temperature rejected on a reasoning model |
Some reasoning modes require provider-specific sampling rules | Omit temperature unless you need it; use reasoning_effort for reasoning depth. |
Files API
Native Gemini Files API, proxied 1:1. Useful for uploading large inputs
(video, long PDFs) that will be referenced from generateContent calls.
| Method | Path | Description |
|---|---|---|
POST |
/upload/v1beta/files |
Initialise a resumable upload |
GET/POST/PUT |
/upload/{upload_path} |
Continue a resumable upload |
GET |
/v1beta/files |
List files |
GET |
/v1beta/files/{file_id} |
Get file metadata |
DELETE |
/v1beta/files/{file_id} |
Delete a file |
The same routes are exposed under /gemini/upload/v1beta/files and
/gemini/v1beta/files[/…]. Auth is x-goog-api-key: <token> or ?key=<token>.
Client Usage & Balance
These endpoints describe the state of the Bearer token that called them — no admin access required.
| Method | Path | Description |
|---|---|---|
GET |
/api/client/balance |
Current balance state for the calling token |
GET |
/api/client/usage/daily |
Last 24h: call counts, token usage, image counts, top models |
GET |
/api/client/usage/summary |
Day/week/month usage and cost rollups |
POST |
/api/client/usage/daily/telegram |
Send the last-24h report to Telegram (server-managed bot) |
curl https://gateway.api429.com/api/client/balance \
-H "Authorization: Bearer YOUR_API_KEY"
{
"token_id": "tok_…",
"token_last4": "a1b2",
"balance": {
"currency": "USD",
"available": "12.3400",
"spent_today": "0.5120"
}
}
The POST /api/client/usage/daily/telegram body accepts:
{
"chat_id": "123456789",
"message_thread_id": 42
}
chat_id is required on first send; subsequent calls may omit it and reuse
the stored one.
Client Portal (Web)
A browser-based self-service dashboard is available at:
https://client.api429.com/
Sign in. Paste your bearer token (the same gb_… value you use for API
calls) into the Sign in input and click the button. The token is kept only
in sessionStorage of the current browser tab and is cleared as soon as you
close the tab — no cookies, no password, no separate account.
What it shows.
- Current balance in USD, with a low-balance warning when you approach the threshold configured on your token.
- Day / week / month breakdown: total calls, success vs. failure counts, input / output / image tokens, official price and your discounted price.
- Top 10 models over the last 30 days — requests, tokens, cost.
Refresh / sign out. The Refresh button re-fetches balance and usage. Sign out clears the token from the tab and returns you to the login view.
Error Handling
HTTP Status Codes
| Code | Meaning | What to Do |
|---|---|---|
200 |
Success | — |
400 |
Bad request | Fix request body or model name |
401 |
Unauthorized | Check your API key |
402 |
Insufficient balance | Top up the client token |
403 |
Forbidden / token context missing | Check token scope |
429 |
Rate limited | Retry after 30–60 seconds |
500 |
Server error | Retry request |
503 |
No keys available | Wait for key cooldown (1–10 min) |
Error Response Format
{
"error": {
"code": "http_error",
"message": "Human-readable error description"
}
}
Common Errors
| Error Message | Cause | Fix |
|---|---|---|
Missing Authorization header |
No Bearer token | Add Authorization: Bearer KEY header |
Capacity exhausted, please retry shortly |
All capacity for the requested model is temporarily saturated | Back off and retry (see strategy below) |
Model not found |
Invalid model name | Check model tables above |
Content blocked by safety filters |
Prompt flagged | Modify your prompt |
Retry Strategy
import time
from openai import OpenAI, APIError
client = OpenAI(
base_url="https://gateway.api429.com/v1",
api_key="YOUR_API_KEY"
)
for attempt in range(3):
try:
response = client.chat.completions.create(
model="gemini-3-flash-preview",
messages=[{"role": "user", "content": "Hello"}]
)
break
except APIError as e:
if e.status_code in (429, 503):
time.sleep(30)
continue
raise
Rate Limits
- The gateway multiplexes requests across a pool of capacity and retries transient errors transparently on your behalf.
- If capacity is briefly saturated you'll receive an HTTP
429or503. Back off with exponential jitter and retry — in practice a second or two is usually enough. - Very long-running generations (certain audio / image models) may
return
504past the internal timeout; retry with the same prompt. - Per-client quotas, if configured, are enforced via HTTP
403with a descriptive message. Contact your administrator to raise your limit.
Supported SDK Clients
Any OpenAI-compatible SDK works out of the box:
| Language | SDK | Compatibility |
|---|---|---|
| Python | openai |
Full |
| JavaScript/TS | openai |
Full |
| Go | go-openai |
Full |
| Rust | async-openai |
Full |
| Ruby | ruby-openai |
Full |
| Java | OpenAI Java SDK | Full |
| cURL | — | Full |
Set base_url / baseURL to https://gateway.api429.com/v1 and use your
API key. For Gemini-native or Vertex Express SDKs, point them at
https://gateway.api429.com/v1beta or
https://gateway.api429.com/vertex-express/v1beta respectively and use
the x-goog-api-key header (or ?key= query parameter).