DocsGet started
Connect a provider
Connect your own AI provider accounts to INFRO: how credentials are sealed, how a request resolves to one, environments, health and failover.
INFRO routes your requests through your own provider accounts. You connect a credential you already hold — OpenAI, Anthropic, Google AI (Gemini), Google Vertex AI, Azure OpenAI, AWS Bedrock, xAI, Mistral, OpenRouter, media providers such as fal.ai, Replicate and ElevenLabs, or any OpenAI-compatible endpoint (every provider and what it serves is listed on Providers) — and your provider bills you directly for what those requests cost, at whatever rates you have negotiated with them. INFRO takes 0% of it.
Nothing serves until something is connected. A request from an organization with no connection that can serve its model returns 503 with code: "no_provider_connected", naming the provider to connect. That is the expected first response, not a fault.
Google Vertex AI takes a service-account key. Paste the service account's JSON key file and your Google Cloud project ID (the project_id in that file). INFRO signs short-lived access tokens with the key and calls Vertex AI in your project, in the global location (Lyria music in us-central1). Grant the service account only roles/aiplatform.user, and enable each Claude model you want on its Model Garden card first.
When INFRO stops offering a provider. A provider INFRO no longer offers leaves the console's pickers and new connections to it are refused with 400 provider_unavailable; keys you already connected keep serving. If INFRO suspends a provider, its keys read Suspended by INFRO in the console and serve no request until it is restored: routes fail over to their next provider, and a test of that key returns 400 provider_suspended. Your keys and settings are kept either way.
Connecting one
- Open Providers in the console — or the provider step of guided setup — and choose the provider kind. The kind decides the wire protocol, which models it can serve, and what configuration it needs beyond a key — Azure OpenAI wants a resource and a deployment, Bedrock wants a region. A provider you already use is listed once, with Add key to add another of its keys.
- Paste the key. It is sent once, sealed at the gateway, and never returned by any endpoint.
- Test it. INFRO calls your provider with the key and the connection's real base URL and auth, and shows what came back — whether it was accepted, and what the provider reports about it (expiry, spend limit, models) — before anything is saved. A key the provider refuses leaves nothing behind, so a typo is caught here rather than by your first production request.
- Name it, and save. INFRO suggests a name that leads with the provider — OpenAI key 1, then OpenAI key 2 — or the name your provider reports for the key when it reports one, so a key named on its own still says whose it is. Names are unique within a provider. Several keys of one provider — a production key, a key for batch jobs, a backup — each appear by name on routes and requests. Without a route, requests spread across the provider's active keys; a route uses them in order or by weight.
How the credential is stored
- Encrypted before it is stored, with AES-256-GCM under a key held as a Worker secret rather than in the database. A database dump on its own opens nothing.
- Bound to your organization and that one connection. The binding is part of the encryption, so a sealed credential copied into another organization's row — or even into your own second connection — fails to decrypt rather than silently authenticating as the wrong account.
- Never returned. No endpoint, console screen, export or support tool will show you the value again. What you can see is the last four characters and when it was set. There is no reveal, for anyone, including us: a reveal turns one compromised session into every provider credential an organization holds.
- Replaceable at any time. Replacing a credential reaches every request within five seconds. Replacing it here does not revoke the old one at your provider — do that too.
Because we cannot show you a credential back, we also cannot recover one. If you lose the original, issue a new one at your provider and replace it here.
How a request finds a connection
In this order, and the first step that produces a candidate wins:
- A route. If
modelmatches one of your route slugs, that route's targets are used in its own order. - A model. If
modelis a catalog id likeanthropic/claude-sonnet-5, or a bare provider model id, every enabled and healthy connection whose kind serves that vendor, and that covers that model, is a candidate: providers in the order you connected them, and within one provider the requests are spread across its active keys. Standby keys, keys that just answered429, and keys that just said they cannot serve the model are tried last. - The provider's own model id.
<provider>/<model id>— for examplelaozhang/gpt-5.6-sol,together/Qwen/Qwen3.5-9Boraws-bedrock/openai.gpt-oss-120b-1:0— is sent to that provider's connections only, with everything after the first/exactly as written. No model map is needed. - Nothing.
503 no_provider_connected, naming what to connect.
Step 3 is for providers whose ids INFRO cannot derive from a catalog id: laozhang, mistral, cohere, groq, together, fireworks, minimax, alibaba, cerebras, aws-bedrock and openai-compatible. A catalog id always wins, so mistral/… reaches step 3 only for an id the catalog does not carry. Whether the model exists is your provider's decision, and its error is returned when it does not.
An id that INFRO knows as a catalog model (laozhang/gpt-5.6-sol is openai/gpt-5.6-sol) is estimated at that model's provider rate and checked against model allowlists under the catalog id. Any other id is served unpriced, and a key with a model allowlist reaches it only if the list allows <provider>/* or that exact id.
openai-compatible/<model id> works while your organization has one OpenAI-compatible endpoint connection. Two such connections are two different servers, so the id is refused with 400 ambiguous_model rather than failed over from one to the other; call the model through a route, or map it on one connection.
Two keys of one provider is the simplest useful reliability setup and needs no configuration at all: they share the traffic, either one carries a request the other could not, and the request's trace names which one served it. Mark a key standby to keep it for failures only.
Environments
A connection can be scoped to some of your organization's environments — every organization starts with production, staging and development, and can add, rename, recolour or delete its own (the console's environment chips offer New environment in place, and the environment filter has Manage environments) — or left at All environments, which is what guided setup creates. Pick one environment or several: one OpenAI connection can serve staging and development while another serves production. An API key names one environment (or none); guided setup asks for it on the gateway-key step. Matching is deliberately fail-closed in both directions: a key that names an environment reaches connections that list it and connections set to every environment, and a key that names none reaches only connections set to every environment.
The direction that surprises people is the second one. It means the easiest key to issue — the one where nobody thought about environments — cannot reach a connection somebody deliberately marked production. That is the point: scoping a connection is a narrowing act, and a key that has not said where it belongs has not proved it belongs there.
Health and ejection
- Consecutive failures eject a connection from rotation for a cool-off rather than letting it keep taking traffic: five in a row for availability errors, two for a rejected credential. The cool-off starts at 30 seconds and grows while the failures continue, to at most 15 minutes. It re-enters on its own; nobody has to notice and re-enable it.
- A
429from your provider is your own account's rate limit, not a fault: it does not count toward ejection, the next connection is tried, and if none can serve the request you get429with codeprovider_rate_limitedand your provider'sRetry-Afterwhen it sent one. - While a connection is ejected, requests go to the next one that can serve the model — another of your connections for that vendor, or the next target on the route.
- An ejected connection is not a missing connection. The console says so, and the
503for a model whose only connection is disabled, in another environment or missing a model map carries codeconnection_out_of_scopeand names the reason, instead of telling you to connect a provider you already connected. When every connection that serves the model is ejected, the503carries codeconnections_unavailableandRetry-After, the seconds until the first one returns: retry after it. - Disabling a connection is a separate act from clearing its credential, and neither implies the other. Doing one as a side effect of the other surprises somebody mid-rotation.
Standby keys and alternate hosts
- Share of traffic. Each key is active (the default) or standby. Active keys share the requests that name a model directly; a standby key is tried only after every active key of that provider failed. A key that just answered
429goes to the back of the line for your provider'sRetry-After(at most five minutes, 30 seconds when it sent none). Routes name their keys explicitly and ignore the setting. - Alternate hosts. A key can list up to five more API hosts, tried in order when its host cannot be reached: a DNS, TLS or connection failure, a timeout, or an edge
502/503/504. A host that failed is skipped for a minute. Switching host is the same key on the same account, so it spends no route retry and does not count toward ejection. A provider's own error, such as a500or a429, does not switch hosts. - Where a host may be. The key is sent to every host, and it is write-only, so a host anywhere else would be a way to read it. On a provider whose API host INFRO fixes, an alternate must be on a domain that provider owns and INFRO lists (LaoZhang:
laozhang.ai, withapi2.laozhang.aiandapi-vip.laozhang.aioffered in the console); other such providers take no alternate. For a server whose URL you type (OpenAI-compatible), an alternate may be any HTTPS host that is not a private address. - An async video job is polled on the host that accepted it.
Models each key covers
Some providers sell keys per model group: a LaoZhang token in its Seedance group calls Seedance and nothing else, another token on the same account calls GPT Image 2 and Nano Banana 2. Each key says which models it covers, when you add it (on the review step, after the provider has answered the test) or later on the key's Models section. Every model is the default and covers every model the provider serves, including ones INFRO adds later. Only selected sends the key only the models you tick; the provider's other keys serve the rest.
- The list offers the catalog models the provider serves through INFRO, grouped by medium and searchable. When the provider listed the key's models at the test, those are marked Listed by this key and one button selects them. Each row names the provider's other keys that already cover it.
- On a provider that takes its own ids (
laozhang/<model id>), an id outside the catalog can be added by hand and is matched as written. - Every path honours it: a request that names a model, a
<provider>/<model id>request and a route target. A route target on a key that does not cover its model is skipped, and the route's dry run says why. - When no key covers the model, the
503carries codeconnection_out_of_scopeand names the key, instead of telling you to connect a provider you already connected. - The Playground, Studio and every model picker in the console offer a key only the models it covers.
What your provider sees
Your request, under your credential, on your account — the same request they would have received had your application called them directly. INFRO does not add an account identifier of yours, does not rewrite the model id, and does not substitute a different model. Because the account is yours, your provider's own terms, data-handling commitments and retention settings apply to it, and each party's data-protection role follows the actual processing and agreements. See subprocessors.
Model mapping
A connection can carry a map from a catalog slug to the id that connection calls the model by. Azure OpenAI addresses a deployment name rather than a model name, a self-hosted server may name a model whatever it likes, and an aggregator may prefix it. Set the mapping once on the connection and your application keeps sending the catalog id. For kinds that need a map — AWS Bedrock, Together AI, Fireworks AI and an OpenAI-compatible endpoint — a model with no entry is not served through that connection.
An aggregator's audio and video models are served only under the ids INFRO has verified in that aggregator's own model list. OpenRouter, for example, serves text by the catalog slug, but speech, transcription and video only for the models it lists, under its own spelling (kwaivgi/…, x-ai/…). A model map entry on the connection still adds one.
Settings on your provider account
Some providers serve a model only to a key configured a certain way on their side, which INFRO cannot change for you. The console shows the requirement beside the model when you pick it, and a request that fails for that reason names it in the error.
- LaoZhang API — Seedance video. LaoZhang serves Seedance only to a token in its
SeeDance2group, with usage-based billing. Any other token is answered503"no available channels". A token has one group, so create a SeeDance2 token at api.laozhang.ai/token and add it as another LaoZhang key; keep your default token for everything else. - LaoZhang API — Wan video. LaoZhang serves Wan only to a token in its
Wangroup. Any other token is answered503"no available channels". Create a Wan token at api.laozhang.ai/token and add it as another LaoZhang key.
Which models your key can call
Providers add and retire models without notice, and an aggregator can stop serving a model to one token group overnight. So INFRO asks your own key for its model list — a request your provider does not bill — when the key is connected and then every three hours, and keeps the model ids only.
- A model your key stops listing is no longer offered after two lists in a row without it: it leaves
GET /v1/modelsand moves to Not listed by your keys in the console, the Playground and Studio, with the date — "Not listed by your LaoZhang key since 16 Oct". When the key lists it again, it is offered again at once. - A request that names it is still sent, with that key tried last, because a list can lag the provider. If the provider then refuses it, the error says since when your key has not listed it.
- Your key or the provider. The console says whether other accounts on that provider still list the model (your key's group, project or plan is the likely cause) or none does (the provider may have retired it). It never names or counts other accounts.
- A route target whose key stopped listing its model is marked on the route, and owners and admins receive one email about it.
- Refresh. Each key shows how many models it lists and when it was last checked; Refresh reads the list again now.
- Providers with no model list INFRO reads (fal.ai, Replicate, KIE and others) are unaffected: their models are offered as before, and INFRO reviews the refusals they return.
When a provider refuses a request
Every request runs on your own provider account, so a failure carries your provider's own words: the error names each connection that was tried, the provider's HTTP status and the message it sent — cleaned, capped and with anything shaped like a credential redacted. The connection's last error on the Providers screen and the request's trace carry the same reason. A provider saying a key has no channel for a model (an aggregator token in the wrong group) is treated as that key's limitation, not an outage: the next key is tried and the connection is not ejected.