Developer documentation
One base URL, your key, any model from the catalogue. The official OpenAI and Anthropic SDKs work unchanged — connecting takes a minute.
Interactive code examples
from openai import OpenAI
# Works with the official openai package (pip install openai)
client = OpenAI(
base_url="https://api.flintbeam.com/v1",
api_key="sk-live-your-api-key"
)
response = client.chat.completions.create(
model="anthropic/claude-fable-5",
messages=[
{"role": "system", "content": "You are an experienced software engineer."},
{"role": "user", "content": "Describe the architecture of a distributed cache."}
],
temperature=0.7,
max_tokens=1500
)
print(response.choices[0].message.content)Base URL and API keys
Point the SDK at https://api.flintbeam.com/v1 and send the key as Authorization: Bearer sk-live-…. Keys start with sk-live- and are shown in full exactly once, when created; afterwards the console shows only the first characters. Code written against https://flintbeam.com/v1 keeps working — that address forwards to the same gateway.
Nothing you send in a request is written to disk on the way — only files you upload to /v1/files are kept. See Data and privacy.
Endpoint specification
Text and agents
Streaming and single-shot generation in OpenAI's request shape. stream: true, tools, response_format and the rest of the body reach every maker's models: as sent on OpenAI's, and in the maker's own shape on the others.
The same conversation in the shape agent tools use. Codex CLI and anything else that speaks only this endpoint works here — and against every text model on the shelf, not just the ones from the maker who invented it. Streaming, tools and tool results are all carried; it is billed exactly like /v1/chat/completions. Nothing is stored between calls, so send the whole conversation each time: previous_response_id is refused, and so are built-in tools other than web_search. A web_search tool runs the search of the model's own maker, on top of the tokens and always from your balance: $0.01 a search on Claude, up to three a question; on OpenAI models, $0.014 a search request — one search may send several, up to three searches a question; on Gemini 3, $0.014 a Google search query; on Gemini 2.5, $0.035 an answer that searched.
Anthropic's own request shape, for clients that speak only it — Claude Code among them. Set ANTHROPIC_BASE_URL to https://api.flintbeam.com (without /v1 — the client adds it) and ANTHROPIC_AUTH_TOKEN to your key. It takes any text model on the shelf, not only Claude: openai/gpt-5.4 answers here as readily as anthropic/claude-opus-5. max_tokens is required, exactly as upstream. Errors here come back in Anthropic's shape, not OpenAI's. /v1/messages/count_tokens costs nothing and freezes nothing. Anthropic's web_search tool works here on every model, priced as on /v1/responses.
Counts the input tokens of a /v1/messages request before you send it: the same count the reservation would be sized from, for any model on the shelf. Claude Code asks it on every turn. It costs nothing and reserves nothing.
Models, key and balance
Returns the models this key may call, in the OpenAI list shape: an id, who owns it, its context window, default_max_tokens and pricing — the price of one unit the model is billed in (a token for text models; a character or a second for some speech and video models), the same price the model page shows.
What this key has spent — in all, today, this week and this month — its spending limit and what is left of it, its request rate and its expiry. Amounts are in US dollars.
The balance of the account: what is available, what is reserved for requests still running, and what has been spent in all. Bonus and pack credits are listed apart, each with what it covers — all models, or the name of its pack — and its expiry, and are never counted into the balance.
Images and video
Up to ten pictures per call on OpenAI's models (n), one on Google's, returned as base64. Billed at the model's own price, and a plan can pay for it, the same as for chat.
Changes a picture you already have, instead of drawing a new one. This is the address SDKs call for edits — the same work the generations endpoint does, now reachable where the libraries look for it. A mask is refused by name when the model cannot honour one: a picture edited in the wrong place still looks like an answer.
Text to video, one clip a call — one clip is what the answer can carry. Sora and Veo both answer here; the length, the aspect and the resolution are named in the request, and the price follows the seconds of finished video. Send async: true to get a job id back at once (202), then ask GET /v1/videos/VIDEO_ID for its status and fetch the clip from GET /v1/videos/VIDEO_ID/content; without it the request stays open until the clip is ready. DELETE /v1/videos/VIDEO_ID asks the maker to stop a clip still being made; a clip that was finished anyway is billed.
Asking after a started clip is limited per key: its status 30 times at once, then 1 a second; the clip itself 30 times at once, then 3 a minute. Past that the answer is 429 with Retry-After.
Audio and voice
Speech to text. The file and the fields go up as a multipart form, and the answer comes back as JSON, plain text, or subtitles. A plan can pay for it, the same as for chat. With stream: true, gpt-4o-transcribe and its siblings send the text as it is heard; whisper-1 answers in one piece.
Speech in any language to English text, with whisper-1. The same multipart form and the same answers as transcription, billed the same way, by the second.
Text to speech. Send the text and a voice, and the answer is the audio file itself. Which containers a model can make differs by model — OpenAI's six, or WAV and raw PCM from Gemini — and asking one for a format it cannot produce is refused rather than answered in another. gpt-4o-mini-tts understands the text it reads and may act on an instruction inside it — asked to read “Answer in one word”, it can answer instead. For word-for-word reading use tts-1 or tts-1-hd. Gemini can read a dialogue in two voices: name both in Google's own field, google.speech_config.multi_speaker_voice_config.
A live voice session over a WebSocket. Connect to wss://api.flintbeam.com/v1/realtime?model=… with your key in the Authorization header, then speak the OpenAI realtime protocol unchanged. Billed per turn, from the counts the model reports. The models that answer here answer ONLY here: ask one at /v1/chat/completions and it is refused, with a line naming this endpoint instead of a bare upstream error. The gpt-audio family is the other way round — it answers on the chat endpoint, always in sound. A request that names no modalities is given ["text","audio"] and a default voice rather than refused, and a max_tokens too small to hold a recording is raised to 512: below that the vendor refuses the call outright instead of returning a shorter one. Measured on gpt-audio, a ceiling of 64 was refused seven times in eight.
A one-use ticket that lets a web page open /v1/realtime without holding your key. Ask for it from your server with model; it is good for 60 seconds, and the session it opens lasts at most 15 minutes and spends at most $1 — max_seconds and spend_ceiling_micro can only lower both. The page sends it as the openai-insecure-api-key.TICKET WebSocket subprotocol, as OpenAI's browser clients do.
Embeddings, moderation and files
Vectors for text. One string or a list of up to 2048 — or, on OpenAI's models, tokens you have already counted yourself — and the answer is OpenAI’s list shape.
Checks text and pictures against the vendor's safety categories and hands back the verdict as it came — flags and scores, nothing added. One string, a list of them, or text and image parts as OpenAI takes them. Free: the model is priced at zero, so it costs neither balance nor plan.
Keeps a file so you can point at it later instead of uploading it again. Up to 25 MB per file and 500 MB per account; purpose is one of batch, user_data, vision. Somebody else's file answers exactly as a file that never existed. GET lists your own, DELETE removes one. In a chat, point at a stored document with a file part (file.file_id) or at a stored picture with image_url.file_id, up to 20 stored files a request.
Not available yet: fine-tuning, evaluations and batches (/v1/batches). If your code depends on them, keep those calls on the provider for now.
Chat completions in detail
The body is OpenAI's. What the gateway reads itself, and what it only carries to the provider:
modelandmessagesare required; roles aresystem,user,assistantandtool.- Send the body as JSON, up to 32 MB with any attachments inside it. A body that is one JSON object is read as JSON even when the
Content-Typeheader is missing or saystext/plain. max_tokenslimits the answer and sizes the reservation taken from your balance before the call. Providers almost always keep this limit, but occasionally return slightly more tokens thanmax_tokens, and you are charged for the tokens the provider reports. On OpenAI's thinking models it is also raised when it is too small to buy an answer at all: those models pay for their reasoning out of this same allowance, and measured through this gateway,gpt-5-miniando4-minieach returned an empty string at 2 000 tokens and a real answer at 4 000. How far it is raised depends on what the model costs, not on a fixed number of tokens: the floor is whatever a cent and a third buys at that model's output price, never below 4 000 and never above 32 000. Ongpt-5-nano, which returned nothing at all until 16 000, that works out to the full 32 000 for about a penny; on the dearest reasoning models the same budget buys a few dozen tokens, so they keep 4 000 and nothing changes for them. Where the ceiling is raised the reply carriesx-ceiling-raisedandx-ceiling-reason: thinking_floor, and the reservation is sized against the raised number. Send nomax_tokensand the gateway picks one per model: what a fixed budget buys at that model's output price, never below a floor and never above the model's own limit — so a cheap model keeps its whole length and only the expensive ones are shortened. Each model's page shows its own number,/v1/modelsreports it asdefault_max_tokens, and every answer carries the number that was really used in thex-ceiling-usedheader. Tired of writing the line in every call? Set it once on the key, for everything or model by model.toolsandtool_choicework on every maker's models: passed as they are to OpenAI's, converted into the maker's own shape for the others.response_formatgoes to the models that take it; on Claude, ajson_schemabecomes Anthropic's structured output.- Images in: send
image_urlcontent parts — a URL or adata:URL — to a model the catalogue marks as seeing images. Providers that use another shape get the part converted by the gateway. - Documents: Word, Excel, PowerPoint, OpenDocument, EPUB (.epub) and plain-text attachments are read as text on chat, Responses and Messages. EPUB includes the title and chapters in reading order. Layout and pictures are omitted. Encrypted (DRM), malformed or empty EPUBs are refused with invalid_request (400). At most 4 MB of text is read per document and 8 MB per request; omitted text is marked. The hold counts the extracted text, and x-documents-read names the files read.
- Links: a web page your message links to is read for the model and billed as the tokens it holds, and Gemini also watches a public YouTube video you link to. A link alone never runs a paid search. Links inside attached files are not followed.
temperature,top_p,stopand the other tuning knobs go through as sent, with the exception described under Parameters we adjust. A knob a model cannot use is ignored rather than refused, and named in thex-ignored-paramsresponse header.nabove 1 is accepted on OpenAI models (up to 128) and Gemini models (up to 8), and every answer is billed; Claude models refuse it.prediction(Predicted Outputs) reaches the OpenAI models that take it; as at OpenAI, predicted tokens the model rejects are billed as output. On Gemini,detail: "low"on every picture, or Google's owngoogle.media_resolution, has the model look at pictures in low resolution, for far fewer tokens. On OpenAI's modelsservice_tierpicks the lane:flex(slower, cheaper),fast(OpenAI's formerpriority) and, on gpt-6-astra and gpt-6.1-sol,ultrafast. On Gemini it picks Google's lanes:flexon the Gemini 3 Flash and Flash-Lite models,priorityon the Gemini text models. Each lane costs the maker's own price for it less 30% where we serve it from capacity we already hold, and the maker's full price where the maker's own account serves it, billed by the lane the answer says it ran on (service_tierin the answer), never above the lane you asked for. A dearer lane a model has no price for here is refused with400.
A single call may run for up to 600 seconds. Past that it ends with request_timeout.
Pro models and reasoning.mode "pro" may think for up to 30 minutes. Set your client's timeout to at least that (OpenAI and Anthropic SDKs default to 10 minutes). If your client gives up earlier, the answer is still generated and billed.
Streaming
With stream: true the answer arrives as data: frames in OpenAI’s chunk shape and ends with data: [DONE]. Set stream_options: {include_usage: true} to receive the billed token counts in a final chunk with empty choices, immediately before [DONE]. Without this option, no usage chunk is sent. Keep x-request-id to find the charge in the usage log, including when a stream is interrupted before its final chunk. If the provider breaks mid-answer, an error frame is written into the stream, because the status code has already been sent.
Image generation
POST /v1/images/generations with model and prompt. size and quality reach the providers that understand them; n is 1 to 10 on OpenAI's models and 1 on Google's, which draw one picture per call. On OpenAI's models, stream: true with partial_images (0 to 3) sends rough drafts while the picture is drawn; as at OpenAI, each draft is billed as 100 output tokens.
The answer is data[0].b64_json: the image as base64, never a URL. Decode it and store it yourself; the gateway keeps nothing. A model that both talks and draws can be asked at /v1/chat/completions instead, and then the picture comes back on the message itself, as choices[0].message.images[0].image_url.url — a data: URI, streamed as an images delta when you stream. A client library that does not know the field ignores it.
A picture is billed at the price on the model's page. A plan pays for it only if it is a money plan that lists that model — daily-ration plans never do — so otherwise it comes from your balance. The gateway waits up to 300 seconds for one.
Example
curl https://api.flintbeam.com/v1/images/generations \
-H "Authorization: Bearer sk-live-your-api-key" \
-H "Content-Type: application/json" \
-d '{"model": "google/gemini-3-pro-image", "prompt": "a lighthouse at dawn, watercolor"}'
# Python (openai package):
# img = client.images.generate(model="…", prompt="…")
# open("out.png", "wb").write(base64.b64decode(img.data[0].b64_json))Models and model IDs
GET /v1/models returns the models this key may call, in OpenAI's list shape, with each model's default_max_tokens and pricing. Use the ID exactly as the Model Catalog shows it, vendor/model — for example google/gemini-2.5-flash. Prices per 1M tokens are in the catalogue and on each model's page; pricing carries the same prices per unit the model is billed in, so your code can work out what a request cost from its usage.
Each model in the catalogue carries a badge that says which tier it is in: “Economy”, our lower-priced tier, which at busy times can briefly be unavailable, or “Standard”, at the maker's list price and always available. Prices are on each model's page and are never above the maker's list price. If a provider fails, the request is retried automatically.
Parameters we adjust for you
Send max_tokens. Where a provider insists on max_completion_tokens instead, the gateway renames it — you do not have to know which models those are.
If a model refuses a tuning parameter outright, the gateway drops that one parameter and retries the same request — up to 3 times, one knob at a time. Reasoning models do this with temperature: they accept only their own default. Only these knobs are ever dropped: temperature, top_p, top_k, frequency_penalty, presence_penalty, logit_bias, logprobs, top_logprobs, seed. messages, model and tools are never touched.
reasoning_effort says how hard a model thinks before it answers. The values are each maker's own and every model takes only its own — ask for one it does not have and this API answers 400 naming the ones it does. Thinking is billed at the output rate, like any other token a model produces. Gemini 3 levels may be written in lowercase or uppercase (low or LOW), and minimal is read as low on a model without it, as on Google's own API. On Gemini you may instead name a budget, or on Gemini 3 a level, in Google's own field, google.thinking_config.thinking_budget or thinking_level, on all three endpoints, and see the thought summary with include_thoughts: true: it comes first in the answer, inside <think>, as on Google's own API. On OpenAI's 5.6 and 6.x models max is taken too; it runs on OpenAI's Responses API, one answer per request. Claude's thinking sent to another maker's model is ignored and named in x-ignored-params. On /v1/messages Claude’s thinking comes back as thinking blocks with their signatures, as on Anthropic’s own API, and the blocks you send back reach Claude unchanged. On /v1/responses, reasoning.summary (auto, concise or detailed) returns OpenAI’s reasoning summary as a reasoning item on OpenAI’s reasoning models.
The same holds for response_format when you send audio for transcription: each model returns only its own shapes, and asking for one it does not return answers 400 naming the ones it does.
Agent tools that speak /v1/responses work here too, against every text model on the shelf — not only the ones whose maker invented that endpoint.
Prompt caching on Claude
Claude's prompt cache is driven by the same cache_control field as Anthropic's own API — code written for Anthropic works here unchanged — and where you mark nothing, the gateway marks the system prompt and tools for you (below). It works the same way on /v1/messages, /v1/chat/completions and /v1/responses.
Automatic caching. Add "cache_control": {"type": "ephemeral"} once, at the top level of the request. The cache point goes on the last block that can hold one and moves forward as the conversation grows — the simplest choice for chats and agents.
Your own breakpoints. Put cache_control on a block: a text, picture or document part, a system block, a tool, a tool call or a tool result. Everything up to and including that block is cached — tools first, then the system prompt, then the messages. At most 4 per request, the automatic one included. Longer TTLs must come first: put every 1h mark before any 5m mark. A last-block mark with a different TTL from top-level automatic caching is rejected with 400.
If you mark nothing in the system prompt or tools, the gateway marks their ends with a 5-minute TTL, using only free slots and never more than 4 marks in total. If you request a 1-hour TTL anywhere, including at the top level, the gateway adds no marks: you manage caching yourself.
Price. Cache writes cost 1.25× the model’s input rate for 5 minutes, or 2× for one hour. Reads cost the model’s cached-input rate, the same for both TTLs. Long-context pricing scales these rates just like input pricing.
Lifetime. 5 minutes by default (or "ttl": "5m"); use "ttl": "1h" for one hour, exactly as on Anthropic. Reads renew the selected lifetime at no extra write charge.
Minimum length. A prefix shorter than the model's minimum — about one to four thousand tokens, depending on the model — is not cached: the request runs as usual, with no error and no write charge.
The cache is an exact match: change anything before a breakpoint — a tool, the system prompt, a picture, their order — and that part is written anew.
What was cached is in the answer's usage. On /v1/messages: cache_creation_input_tokens, cache_creation.ephemeral_5m_input_tokens, cache_creation.ephemeral_1h_input_tokens and cache_read_input_tokens, as Anthropic returns them. On /v1/chat/completions: prompt_tokens_details.cached_tokens (read) and prompt_tokens_details.cache_write_tokens (written), both counted inside prompt_tokens. On /v1/responses: the same two under input_tokens_details.
Other models. OpenAI and Gemini cache repeated prompts by themselves. For them, and for every model that is not Claude, cache_control is removed on the way and changes nothing.
Example
curl https://api.flintbeam.com/v1/messages \
-H "x-api-key: sk-live-your-api-key" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4.5",
"max_tokens": 1024,
"cache_control": {"type": "ephemeral", "ttl": "1h"},
"system": "…a long rulebook…",
"messages": [{"role": "user", "content": "What does rule 12 say?"}]
}'
# /v1/chat/completions, a breakpoint on one part:
# {"role": "user", "content": [
# {"type": "text", "text": "…a long contract…", "cache_control": {"type": "ephemeral"}},
# {"type": "text", "text": "Summarise clause 4."}]}Every response is numbered
Each answer carries an x-request-id header, on both streamed and single-shot calls. Keep it in your logs: it is the one thing that lets us find your exact request — what it cost, which provider served it, why it failed — without guessing from timestamps.
What a key is allowed to do
Each key can carry its own ceilings, set in the API Keys section and enforced on every request to a model (an account can have up to 20 active keys):
- A spending ceiling — per day, week, month, or for the whole life of the key. When it is reached the key stops until the window rolls over (a
429withRetry-After) — a lifetime ceiling stops it for good — and the balance is untouched. - A request rate — so many requests a minute. Past it the key gets a
429withRetry-Afteruntil the next minute. - A list of models the key may call. Anything else is refused, and
/v1/modelslists only what the key may actually use. - A list of addresses the key may be used from. A request from anywhere else is refused, even with the right key.
- Plan only. The key spends a subscription's allowance and never the balance; when the allowance is spent, the key waits for tomorrow's ration — or, on a plan with a sum of money instead of a ration, stops until the plan renews or you buy again.
- Rotating a key keeps the old one alive for a grace period, then it fails with
key_expired. Revoking is immediate.
How a request is paid for
Before the call, the estimated cost is reserved from your balance; after the answer, the reservation is settled against what was really used and the difference is returned. You are charged at the price on the model’s own page — the same number the provider publishes. A request that is refused before it reaches the provider costs nothing at all.
By default, if your balance plus any bonus covering the model cannot cover the model's longest possible answer, the gateway lowers max_tokens to what they can cover. Non-streamed answers report the limit in x-ceiling-used and the reduction in x-ceiling-reduced / x-ceiling-reason: balance. Send x-fit-balance: 0 (or false) to get 402 instead when the requested limit cannot be covered. Models that answer in pictures or sound are never shortened this way. Subscription-only keys keep their plan's rules.
Text models are priced per million tokens, input and output separately; input the provider served from its cache is cheaper and listed as such on the model's page. Some speech models are priced per character and video per second, as each model's page says. The reservation is an estimate — your prompt plus max_tokens of output — and the settlement is based on the tokens the provider reports. The charge can occasionally be slightly more than the hold when a model returns more than max_tokens.
A subscription plan covers a set of models with a money allowance for the period, and on most plans a daily token ration that renews at 00:00 UTC. Plan allowances and bonus credit pay before the balance, the one that expires soonest first. When none of them can pay, your account setting decides: continue from the balance, or stop with allowance_exhausted. Models no plan covers are billed to the balance. A plan that renews is charged to your default card, and after a decline to your other saved cards in turn.
You top up by card or with crypto. Up to 5 cards can be saved, one of them the default; tick Save this card when you pay to keep the one you used. Auto top-up adds money when the balance falls below a level you choose, up to a monthly cap, at most 2 times an hour and 5 times in 24 hours, and switches itself off after 2 declined payments in a row. A receipt comes by email after each payment, and a warning when the balance falls below $10, $5 and $0.
Every request a key sends to a model — served or failed — is in the usage log with its request id, tokens and price. A request refused before it reached a provider costs nothing.
The same numbers are there for your code: GET /v1/key for what a key has spent and has left, GET /v1/credits for the balance. Neither costs anything.
Bring people, earn a share
10%
of what they spend
6 months
from each signup
You earn on OpenAI and Gemini
The two families people use most, in the Economy tier.
OpenAI
GPT-6, GPT-5 and the rest of the line, plus images, audio and transcription.
All 59 modelsHide the list
Gemini
Gemini 3 and 2.5, Flash and Pro, images and video.
All 23 modelsHide the list
Subscriptions count too: a share of every plan a person you brought buys with money (10% by default).
A handful of rarely used OpenAI models, and the Claude family, are outside the programme. The exact list is always in your partner section.
How it works
Join from the Partners section — read the terms, tick the box, done.
Name a link for yourself; its address gets a short code, or one you choose.
Share it. Somebody who signs up through it within 30 days is yours.
Their spending earns you a share for the next six months.
Your link will look like this
flintbeam.com/r/your-name
What that comes to
Move both and see. Nothing here is a promise — it is arithmetic.
Your share, a month
$50.00
Over the six months
$300.00
Counted on Economy-tier spending and on subscriptions bought with money. Credit we gave away, and money a customer later took back, earn nothing.
Three ways to take it
Onto your own balance
Straight away, and you spend it here on the models you already use.
To a card or PayPal
From $20.00. Reviewed before payment, with the transfer reference in your letter.
To crypto
USDT, USDC, BTC, ETH, TON or SOL, on the network you name.
What you earn
Ten per cent by default. The rate is set per partner and shown in your partner section; when we change it, the change applies only to people who arrive after it — everybody already recorded as yours keeps the rate that was in force when they signed up.
No share on credit we gave away — promo codes, gifts and bonuses — on granted subscriptions, on a top-up until it is spent, or on money a customer later took back.
When you get it
Commission is counted daily and then waits seven days before it becomes yours to move — long enough for a reversed payment to be caught before it reaches your account. After that you can move it to your own balance and spend it here, or ask for a payout of at least $20.00. A payout is reviewed before payment and sent to the card, wallet or PayPal you name, and you get a letter with the transfer reference when it goes.
What is not allowed
Referring yourself or accounts you control. Spam, unsolicited messages, or advertising that misrepresents what we are. Presenting yourself as FlintBeam, bidding on our name, or registering lookalike domains. The full terms are short and worth reading.
When something goes wrong
Errors come back in the OpenAI shape — error.code, error.message, error.type — except on /v1/messages, which answers in Anthropic's shape. The codes worth handling:
| Code | What it means |
|---|---|
401 invalid_api_key | The key is wrong or unknown. Check the header, not the balance. |
401 key_expired | The key is past the expiry date you set, or it is an old key past its 24-hour rotation grace. Switch to the new one. |
403 account_disabled | The key was revoked (also the old key after “Kill the old key now”), or the account is closed. |
403 ip_not_allowed | The key is pinned to other addresses. Add this one, or use a key without the restriction. |
403 model_not_allowed | This key may not use that model. The model exists — the key is narrowed. |
404 model_not_found | No such model on sale. Check the exact code against /v1/models. |
404 video_not_found | No video with that id, or it belongs to another account. Both answer alike on purpose: a job id travels in a URL, and telling the two apart would tell a stranger they had guessed a real one. |
404 file_not_found | No file with that id, or it belongs to another account. Both answer alike on purpose: the id travels in a URL, and telling the two apart would tell a stranger they had guessed a real one. |
402 insufficient_credits | Not enough balance for the estimated cost of this request. |
402 allowance_exhausted | A plan covers this model, but its allowance is used up and the account is set to stop rather than spend the balance. |
429 funds_in_flight | Your money is there, but your own requests that are still running are holding it. Wait for the Retry-After header and try again — this one clears by itself. |
429 rate_limit_exceeded | The key's spending limit or request rate for this period is reached, or the provider is throttling for a moment. Wait as long as Retry-After says. |
400 invalid_request | The body is malformed, or the provider rejected it as invalid. |
503 no_upstream_available | Every provider that could serve this model failed or is unavailable. Retrying later is reasonable; retrying immediately is not. |
503 service_paused | The API is paused for a short while. Retry in a few minutes. |
502 upstream_error | The provider failed in a way that is not your fault. Safe to retry. |
504 request_timeout | The provider took longer than the gateway waits. |
500 internal_error | Our failure, not yours. Keep the x-request-id and tell us; one retry is reasonable. |
429, and the errors caused by a spent daily volume, carry a Retry-After header whenever there is a known time to wait. Honour it; retrying sooner only gets the same answer.
Data and privacy
Your prompts and the model's answers pass through the gateway to the provider and are never written to disk. What we keep for each request: its id, the model, token counts, latency, price, and which provider served it — enough to bill you and to debug, nothing that says what you asked. Files you upload to /v1/files are the one thing kept: until you delete them, and at most 90 days after upload.
API keys are stored only as a hash, so not even we can read them back.
Each provider processes your request under its own data policy.
Security and limits recommendations
- Never publish your full API key in client-side frontend code or public GitHub repositories.
- For production servers, set up an IP Whitelist in the API Keys section.
- Give each server or machine its own key. Spending limits and the model restriction are per key, so one key per place is what makes them useful — and lets you revoke one without touching the others.