Surfaces

Calling the gateway

OpenAI, Anthropic, Gemini, and curl: non-streaming, streaming, and cross-protocol.

Point the client you already use at your application gateway and pass an end-user ak_. The inbound wire (SDK + path) is independent of which entitled model the call reaches. That is what cross-protocol routing is.

Point the client

import OpenAI from "openai"

const client = new OpenAI({
  baseURL: "https://<app>.gw.ourseams.com/v1",
  apiKey: endUserKey,
})

Anthropic's base URL is the host without /v1. OpenAI's includes /v1. Gemini puts the model in the path (/v1beta/models/{model}:generateContent).

One call

const res = await client.chat.completions.create({
  model: "acme/smart",
  messages: [{ role: "user", content: "Say hello" }],
})
console.log(res.choices[0]?.message.content)

Streaming

Same clients, stream: true (or the SDK's stream helper). Spend is re-checked while chunks arrive; a ceiling can end the stream mid-answer.

const stream = await client.chat.completions.create({
  model: "acme/smart",
  messages: [{ role: "user", content: "Count to three." }],
  stream: true,
})
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "")
}

Cross-protocol

Your customer can keep an OpenAI client while acme/claude resolves to Anthropic, or call Anthropic's Messages API against a model that lands on OpenAI. Only the gateway does that pivot; vendor APIs cannot speak another provider's wire.

InboundModel providerWhat happens
OpenAI chat / responsesAnthropic or Gemini modelRequest and stream frames are translated
Anthropic messagesOpenAI or Gemini modelSame; caller still speaks Messages
Gemini generateContentOpenAI or Anthropic modelSame; model stays in the path
// OpenAI client, Anthropic (or Gemini) model behind the alias
const res = await client.chat.completions.create({
  model: "acme/claude",
  messages: [{ role: "user", content: "Say hello" }],
})
// res.model is the provider wire id; the caller still asked for acme/claude

Where a field cannot survive the pivot, the gateway refuses or drops it rather than inventing fidelity. See lossy protocol conversions for the known list.

Tools and images

On the OpenAI wire, tools and images go through /v1/responses; chat.completions is text-only inbound. Anthropic and Gemini carry tools on their usual messages / generateContent shapes, including when the model that answers is a different provider.

// tools and images on the OpenAI wire use /v1/responses
const res = await client.responses.create({
  model: "acme/claude",
  input: "What is the weather in London?",
  tools: [{
    type: "function",
    name: "get_weather",
    description: "Get the weather for a city",
    parameters: {
      type: "object",
      properties: { city: { type: "string" } },
      required: ["city"],
    },
  }],
})

Protocols

IdPath
openai.chatPOST /v1/chat/completions
openai.responsesPOST /v1/responses
anthropic.messagesPOST /v1/messages
google.generatePOST /v1beta/models/{model}:generateContent (+ stream form)