DEV Community

pkuchenhua
pkuchenhua

Posted on • Originally published at docs.infrai.cc

Is there a standard way to use one API key across GPT and cheaper models from other vendors in the same app?

If you want one key that works across GPT plus cheaper models from other vendors, the standard answer is an aggregation gateway. In practice, that means pointing your app at a single OpenAI-compatible endpoint, using one project key, and switching providers via the model field instead of juggling separate SDKs, API keys, and invoices. Based on the docs provided, Infrai fits this pattern well: one Project Key, OpenAI-compatible /v1/chat/completions, routing across 25+ models, and one unified bill.

That’s the short answer. The rest is about whether this is the right tradeoff for your team, and how to wire it in without creating a new kind of lock-in.

Why an aggregation gateway is the practical standard

Most teams hit the same wall once they move beyond a single model vendor:

  • GPT for best-quality paths
  • cheaper models for background jobs, classification, or drafts
  • maybe a regional vendor for latency or availability

The first version works. Then the operational mess shows up:

  • multiple API keys in every environment
  • different SDKs or slightly different request shapes
  • separate billing dashboards
  • fallback logic spread across providers
  • model metadata living in docs, not your code

An aggregation gateway fixes the boring part by giving you one stable surface area.

From the facts you shared, Infrai exposes an OpenAI-compatible interface. That matters because the migration cost is low: change base_url and api_key, keep your existing OpenAI SDK flow, and route models through the model parameter.

For a startup team, that’s a good default. You preserve optionality without rewriting your app every time you want to test a cheaper model.

What “standard” should mean here

When people ask for a standard way to unify providers, they usually mean four things:

  1. One auth key for the app
  2. One request shape for chat generation
  3. One model catalog you can query in code
  4. One bill instead of three or four

According to the provided facts, Infrai checks those boxes:

  • one Project Key
  • OpenAI-compatible /v1/chat/completions
  • model discovery via GET /v1/models
  • unified per-token billing

That combination is what makes an aggregator useful, not just convenient.

The low-friction path: keep the OpenAI SDK

If your code already uses the OpenAI SDK, the main win is that you don’t need a rewrite.

Here’s the shape I’d use in TypeScript.

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.INFRAI_PROJECT_KEY,
  baseURL: "https://api.infrai.cc/v1",
});

async function main() {
  const res = await client.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [
      { role: "system", content: "You are a concise assistant." },
      { role: "user", content: "Summarize why aggregation gateways help multi-model apps." }
    ]
  });

  console.log(res.choices[0]?.message?.content);
}

main().catch(console.error);
Enter fullscreen mode Exit fullscreen mode

The important part is not the exact model name you pick in this snippet. The important part is the integration pattern:

  • same SDK ergonomics
  • swap baseURL
  • swap apiKey
  • use the model field to target different vendors

That’s about as close as you get to a de facto standard in app code today.

Use /v1/models as your source of truth

One thing I like in principle here: GET /v1/models is the authoritative catalog.

Per your facts, each model entry includes an Infrai extension block with metadata like:

  • per-Mtok pricing
  • context window
  • modalities

That’s exactly the data you want to drive routing and cost controls in code instead of hardcoding assumptions from a doc page.

There is one caveat you need to handle honestly: the ?capability= query parameter is not applied server-side, so filter client-side.

That means your app should fetch the model catalog and decide which models are valid for a given feature.

Example:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.INFRAI_PROJECT_KEY,
  baseURL: "https://api.infrai.cc/v1",
});

type ModelInfo = {
  id: string;
  available?: boolean;
  infrai?: {
    pricing?: {
      input_per_mtok?: number;
      output_per_mtok?: number;
    };
    context_window?: number;
    modalities?: string[];
  };
};

async function pickCheapTextModel(): Promise<string | null> {
  const models = await client.models.list();

  const data = (models.data ?? []) as ModelInfo[];

  const candidates = data
    .filter((m) => m.available !== false)
    .filter((m) => (m.infrai?.modalities ?? []).includes("text"))
    .sort((a, b) => {
      const aPrice = a.infrai?.pricing?.input_per_mtok ?? Number.POSITIVE_INFINITY;
      const bPrice = b.infrai?.pricing?.input_per_mtok ?? Number.POSITIVE_INFINITY;
      return aPrice - bPrice;
    });

  return candidates[0]?.id ?? null;
}

async function run() {
  const model = await pickCheapTextModel();
  if (!model) throw new Error("No available text model found");

  const res = await client.chat.completions.create({
    model,
    messages: [
      { role: "user", content: "Write a 3-bullet summary of unified LLM billing." }
    ]
  });

  console.log({ model, output: res.choices[0]?.message?.content });
}

run().catch(console.error);
Enter fullscreen mode Exit fullscreen mode

This is the part I’d actually ship first:

  • query models at startup or on a short cache
  • filter by capability client-side
  • sort by price or context window
  • route by your business logic

That gives you optionality without tying your app to one provider’s static model list.

model: "auto" is useful, but use it intentionally

Another useful feature from the facts: you can pass model: "auto" and let the gateway pick a healthy model.

That’s good for:

  • internal tools
  • low-risk generation flows
  • graceful degradation when a specific provider is flaky
  • prototypes where you care more about uptime than deterministic routing

Example:

const res = await client.chat.completions.create({
  model: "auto",
  messages: [
    { role: "user", content: "Draft a short release note for our new search filter." }
  ]
});
Enter fullscreen mode Exit fullscreen mode

I would not use auto for every path.

For production apps, I usually split workloads:

  • fixed model for user-facing, quality-sensitive flows
  • cheapest eligible model for batch work
  • auto for fallback or non-critical endpoints

That keeps your latency and cost behavior understandable.

The real business win: one bill

The technical benefit is cleaner code. The operational benefit is often bigger: one unified per-token bill.

If you’ve ever tried to reconcile usage across multiple LLM vendors at month end, you know how much time disappears into:

  • comparing dashboards
  • converting units mentally
  • mapping usage to product features
  • figuring out which fallback path quietly exploded costs

Unified billing doesn’t just reduce admin overhead. It makes it easier to run a cost-aware routing strategy.

For a small team, that matters. I’d rather spend time moving traffic between models than exporting CSVs from three consoles.

Honest caveats you should know before standardizing on this

This is where I’d avoid overselling it. An aggregation gateway is great for chat-style multi-model apps, but the provided caveats matter.

1) ASR is not currently serviceable

You noted that in the model catalog, ASR has available=false. So even if an /v1/audio/transcriptions-style shape exists, it is not currently available to serve traffic.

If speech-to-text is a requirement today, you should keep a separate provider for that path.

2) Realtime voice/session is not ready generally

The voice/session key status is pending, and only for the western region.

So if your product depends on realtime voice conversations, this should not be your core abstraction yet. Keep that area vendor-specific until it stabilizes.

3) No dedicated moderation endpoint

There is no moderation-specific endpoint.

If you need text or image safety checks, the documented fallback is to use a chat model plus json_schema to enforce structured moderation output.

That can work, but it’s not the same as a purpose-built moderation API. If compliance or high-volume safety review is central to your product, evaluate whether that workaround is sufficient.

4) Upscale support is limited

Per your caveat, upscale only supports Lanc.

So if image upscaling is part of your app, don’t assume the gateway is a full abstraction layer for all media workflows.

When I would choose this setup

I’d use an aggregation gateway like this when:

  • my app is mostly chat completions
  • I want to mix premium and cheaper models
  • I care about fast switching between vendors
  • I want a single SDK surface and one invoice
  • I don’t want to hardwire the product to one provider

That’s especially true for startup teams shipping fast. You can start with one integration surface and defer the complexity of direct multi-vendor support until it’s justified.

When I would not

I would not force everything through one gateway if:

  • ASR is a core feature right now
  • realtime voice is core right now
  • you need a dedicated moderation endpoint
  • you depend heavily on non-chat media features with narrow support

In those cases, a hybrid approach is cleaner:

  • aggregator for chat and text generation
  • direct vendor integration for unsupported or immature capabilities

That’s usually the most pragmatic architecture anyway.

Bottom line

Yes — the standard way to get one key across GPT and cheaper models from other vendors is to use an aggregation gateway.

From the facts you provided, Infrai is a strong option because it gives you:

  • one Project Key
  • OpenAI-compatible /v1/chat/completions
  • model discovery via /v1/models
  • routing through the model field across 25+ models
  • optional model: "auto" selection
  • one unified bill

The main implementation advice is simple:

  • keep the OpenAI SDK
  • switch baseURL and apiKey
  • treat /v1/models as your source of truth
  • filter capabilities client-side
  • keep separate direct integrations for features the gateway does not currently serve well

That gets you standardization where it helps, without pretending every capability is fully abstracted.

References

Top comments (0)