Skip to content

Migration guidesFrom direct OpenAI and Anthropic SDKs

From direct SDK calls to one control plane

Most teams start by calling OpenAI or Anthropic with the vendor's own SDK and a key in an environment variable. That works until there are several services, several keys and a monthly invoice nobody can attribute. This page is the edit that puts INFRO in front of those calls without changing SDK, provider account or contract.

Your own code, calling each provider's SDK with that provider's key

INFRO accounts are self-serve. The catalog, the docs, and the API contract are public, the gateway is deployed, and anything beyond v1 is marked Later. Plans and trial

Where things stand

What you have

Provider keys in each service's environment, retries and timeouts written per codebase, and cost visible only on the provider's invoice or usage page, by key or project at best.

What changes

Each client points at https://api.infro.io with an INFRO gateway key. Your provider keys move into INFRO as connections, sealed; your providers keep billing you directly at your own rates.

What does not

The SDKs, the request and response shapes, streaming, tool calls and structured outputs on chat completions. INFRO answers OpenAI's Chat Completions and Responses shapes and Anthropic's Messages shape.

A gateway is one more hop and one more vendor. For some setups it is not worth it yet, and this list is the honest version of that.

  • One service, one provider, one key, and a bill one person reads. A gateway adds a hop and a subscription before it adds anything you need.
  • Your workload is mostly embeddings, Batch, fine-tuning, Files, vector stores or the Realtime API. INFRO serves none of them; those calls would stay direct anyway.
  • You rely on a provider feature the chat shapes do not carry, and you only use that provider. Calls INFRO cannot carry are better left direct than half-converted.
  • You need every request to stay inside one cloud region. INFRO runs on Cloudflare's network and region pinning is not available today.

The edits, one row each. Everything not listed here stays as it is.

 Direct SDK callsINFRO
Base URLThe SDK default: api.openai.com/v1, api.anthropic.com.https://api.infro.io/v1 for the OpenAI SDK; https://api.infro.io for the Anthropic SDK (it appends /v1/messages).
KeyOPENAI_API_KEY, ANTHROPIC_API_KEY in each service.An INFRO gateway key (Authorization: Bearer; the Anthropic SDK's x-api-key is accepted too). The provider keys are entered once, in the console, as connections.
Model idgpt-5.6-terra, claude-sonnet-5-5.openai/gpt-5.6-terra on chat completions, or a route name. The Anthropic SDK can keep claude-sonnet-5-5: /v1/messages reads Anthropic's own ids.
AttributionUsually nothing, or the provider's user field.metadata.user_id, metadata.session_id, metadata.tags in the body, or X-INFRO-User-Id / X-INFRO-Feature headers. Recorded on the request, never sent to the provider.

Before · provider SDKs

import OpenAI from "openai";
import Anthropic from "@anthropic-ai/sdk";

const openai = new OpenAI(); // reads OPENAI_API_KEY
const anthropic = new Anthropic(); // reads ANTHROPIC_API_KEY

await openai.chat.completions.create({
  model: "gpt-5.6-terra",
  messages: [{ role: "user", content: "Hello" }],
});

await anthropic.messages.create({
  model: "claude-sonnet-5-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello" }],
});

After · INFRO

import OpenAI from "openai";
import Anthropic from "@anthropic-ai/sdk";

const openai = new OpenAI({
  baseURL: "https://api.infro.io/v1",
  apiKey: process.env.INFRO_API_KEY,
});
const anthropic = new Anthropic({
  baseURL: "https://api.infro.io",
  apiKey: process.env.INFRO_API_KEY,
});

await openai.chat.completions.create({
  model: "openai/gpt-5.6-terra",
  messages: [{ role: "user", content: "Hello" }],
});

await anthropic.messages.create({
  model: "claude-sonnet-5-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello" }],
});

Failover without new code

Connect Claude on Anthropic and on Vertex AI, or two Anthropic keys, and a request naming the model fails over between them. A named route sets the order and the per-failure rules (429, 5xx, timeout) in configuration.

Budgets before the call

Budgets at the organization, project, member and key reserve a request's worst case before the provider is called. At the ceiling the answer is 402 budget_exceeded, in the API's own error envelope.

What to leave alone

Embeddings, Batch, Files, fine-tuning, vector stores, moderations and Realtime keep their direct client. A single service can hold both clients: one through INFRO, one direct.

What your setup does today against INFRO, checked against what the gateway implements. Two rows say INFRO has nothing.

Direct SDK callsWhat it does thereIn INFRO
Provider key per servicedifferentEach service holds the provider's key in its environment.The key is a connection, sealed in INFRO; services hold scoped gateway keys that can be limited to providers, models, IP ranges and an environment, rotated or switched off.
Retries and timeoutsdifferentThe SDK's own retries, plus whatever each codebase adds.Routes with priority or weighted targets across your connections and failure rules per kind (429, 5xx, timeout). The SDK's own retries still apply on top.
CostdifferentThe provider's usage page and invoice, by key or project.An estimated provider cost on each response (usage.cost, usage.price_source), by project, key, user and tag; reconciled daily against OpenAI's and Anthropic's own cost APIs with an admin key you add.
Spend limitsdifferentProvider-side project limits, where the provider offers them.Budgets that refuse at the ceiling with 402, across every provider at once, at organization, project, member, key and end-customer level.
Chat Completions and Responsessame shapeOpenAI's two text APIs.Both, at /v1/chat/completions and /v1/responses. previous_response_id and background are refused: INFRO keeps no responses, so send the conversation each turn.
Anthropic Messagessame shape/v1/messages, with thinking, cache_control and server tools./v1/messages in Anthropic's shape. On an Anthropic connection, or Claude on Vertex AI, the body reaches the provider as written.
Images, speech, transcription, videosame shapeThe provider's media endpoints./v1/images, /v1/audio, /v1/videos with async jobs, on the providers that serve each model.
Embeddingsnothing/v1/embeddings.Not served. Keep the direct client for embeddings.
Batch, Files, fine-tuning, RealtimenothingAccount-level provider APIs.Not served, and not planned as gateway features. They stay on the provider.

What INFRO does not do

  • Embeddings, Batch, Files, fine-tuning, vector stores, moderations, Assistants and the Realtime API.
  • Stored responses: previous_response_id, conversation and background: true on /v1/responses are refused with 400.
  • Region pinning. INFRO runs on Cloudflare's network; residency is on the roadmap, not available.
  • A self-hosted deployment without an enterprise agreement.

What does not come across

  • Usage history from before the switch. The provider's own dashboard keeps it; INFRO records from the first request it serves.
  • Provider-side project limits. Set INFRO budgets instead; the provider's limits still apply on its side.

Questions

Do I still pay OpenAI and Anthropic directly?
Yes. INFRO calls your own provider accounts with your keys, so your providers bill you at your own rates. INFRO charges a subscription and adds 0% to model spend.
Do I need to change SDK?
No. The OpenAI SDK takes a baseURL of https://api.infro.io/v1, the Anthropic SDK a baseURL of https://api.infro.io, and both take the INFRO key as their API key.
What has to stay on the provider directly?
Embeddings, Batch, Files, fine-tuning, vector stores, moderations and Realtime. INFRO does not serve them.

Move with us, or on your own

The migration program maps your direct OpenAI and Anthropic SDKs setup to INFRO connections, routes and budgets on a call and moves the first service with you. Your providers keep billing you directly; INFRO is a subscription and adds 0% to model spend.

Sources

The SDK behaviour on this page comes from these, read on 19 October 2026.