Skip to content
Salyro
Guide

Switch providers without changing your code

With one interface in front of four providers, moving a request from OpenAI to Anthropic is a change of model id — and nothing else.

The practical value of a unified interface is not that it exists — it is what it costs to change your mind. On Salyro, sending the same request to a different provider is a change of one string. No second SDK, no second set of request shapes, no second error format to handle.

This guide connects two providers to one gateway, sends the same request to both, and compares what comes back.

Connect a second provider

A gateway holds one active credential per provider, and it can hold all four at once. Under the gateway's Providers, connect a second one alongside the first.

Nothing about your existing traffic changes when you do. A credential is inert until a request names one of its models.

Find out what you can name

GET /v1/models returns what this gateway can actually reach — models that are active and whose provider has a live credential. It is the authoritative answer, and it changes the moment you connect or revoke a credential:

Shell
curl https://api.salyro.com/v1/models \
  -H "Authorization: Bearer $SALYRO_API_KEY"
JSON
{
  "object": "list",
  "data": [
    { "id": "openai/gpt-4o-mini", "object": "model", "owned_by": "openai" },
    { "id": "anthropic/claude-sonnet-4-5", "object": "model", "owned_by": "anthropic" }
  ]
}

Two providers, one list, one shape. That is the whole mechanism: an id is provider/model, and the provider half decides which of your credentials pays for the call.

Send the same request to both

Nothing changes but the id:

TypeScript
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.SALYRO_API_KEY,
  baseURL: 'https://api.salyro.com/v1',
});

const prompt = 'Summarise this changelog entry in one sentence: ...';

for (const model of ['openai/gpt-4o-mini', 'anthropic/claude-sonnet-4-5']) {
  const completion = await client.chat.completions.create({
    model,
    messages: [{ role: 'user', content: prompt }],
  });

  console.log(model, '→', completion.choices[0].message.content);
  console.log('   tokens:', completion.usage);
}

Both calls return the same response shape, with usage counted the same way. That is what makes the comparison meaningful: you are comparing the models, not two client libraries' idea of what a response looks like.

Compare what it cost

Token counts come back on every response, which is enough for a quick side-by-side. For the money, read the gateway's usage: it prices token counts per model and per provider from a catalogue that keeps historical rates, so the figure for last week's request does not move when a provider changes its prices this week.

Usage broken down by model is the comparison you want here; usage broken down by provider is the one you want when the question is which account you are spending against. Both are in Usage & costs.

Make the model a configuration value

The point of all this is lost if the model id is a literal in twenty places. Read it from configuration and switching becomes a deploy rather than a change set:

TypeScript
const model = process.env.SALYRO_MODEL ?? 'openai/gpt-4o-mini';

That is also what makes a provider comparison something you can run in production on a fraction of traffic, rather than only in a script.

What this does not do

Two more things worth knowing before you treat providers as interchangeable:

  • Capabilities differ between models. Structured output and vision are supported where the model supports them. Sending response_format to a model that cannot honour it fails with an explicit error rather than being ignored — which is the behaviour you want, because the alternative is prose that does not parse. See Get structured JSON output.
  • Prompts are not portable in the way requests are. The wire format is identical across providers; the way a given model responds to a given prompt is not. Compare outputs before switching something that matters, rather than assuming the response will be equivalent because the request was.

Where this leads

Once switching is a configuration value, the gateway split becomes the more interesting decision: which traffic is measured together, and which is kept apart. Attribute cost per feature or customer covers choosing that boundary before the traffic runs, which is the only time it can be chosen.