Melious

If you're already using the OpenAI SDK, switching to Melious is two changes: base_url and api_key. Model names have to change too, because we don't run OpenAI's proprietary models.

The diff

from openai import OpenAI

client = OpenAI(
-   api_key=os.environ["OPENAI_API_KEY"],
+   api_key=os.environ["MELIOUS_API_KEY"],
+   base_url="https://api.melious.ai/v1",
)

response = client.chat.completions.create(
-   model="gpt-4o",
+   model="<MODEL_ID>",
    messages=[{"role": "user", "content": "Hello"}],
)
import OpenAI from "openai";

const client = new OpenAI({
-   apiKey: process.env.OPENAI_API_KEY,
+   apiKey: process.env.MELIOUS_API_KEY,
+   baseURL: "https://api.melious.ai/v1",
});

const response = await client.chat.completions.create({
-   model: "gpt-4o",
+   model: "<MODEL_ID>",
  messages: [{ role: "user", content: "Hello" }],
});

That's the whole migration. Streaming, tool calling, vision, structured outputs, embeddings, audio — all work against the same shapes. developer messages are accepted as system messages, and on client.responses the stream() and parse() helpers work too.

Picking a model

We don't run gpt-4o, gpt-4o-mini, o1, or any other OpenAI-proprietary model. We run open-weight models instead, and there's no automatic substitution — you pick one.

Rough mapping as a starting point — reach for the category, then pick a current ID from the hub:

You hadReach for
gpt-4oa flagship general-purpose chat model (GLM, Qwen, DeepSeek families)
gpt-4o-minia smaller, faster chat model (a compact Qwen, GPT-OSS)
o1 / reasoninga reasoning model (DeepSeek-R1, Kimi thinking variants)
gpt-4o visiona vision model (Qwen-VL, Pixtral, Gemma)
text-embedding-3-smallan embedding model (BGE-M3, Qwen embeddings)
whisper-1a transcription model (Whisper-class)
dall-e-3an image model (FLUX)

These are starting points, not claims of equivalence. Browse melious.ai/hub/models to compare context windows, pricing, and capabilities — or hit GET /v1/models?include_meta=true to filter programmatically. See Models for the broader stance.

Steering routing

The OpenAI SDK passes unknown fields through to us — so the Melious-specific extensions work without wrapping the client. Append a flavor suffix to bias routing toward speed, price, or a lower-carbon provider:

response = client.chat.completions.create(
    model="<MODEL_ID>:eco",   # prefer providers running on greener power
    messages=[{"role": "user", "content": "Hello"}],
)

Full list of suffixes and what they do: Routing.

What's different at runtime

Three practical differences to know about:

Responses include extra fields. environment_impact and billing_cost ride on Chat Completions, embeddings, and rerank responses, and on the final usage chunk of a Chat Completions stream. client.responses calls don't get them. The OpenAI SDK ignores unknown fields, so your code won't break — but they're there when you want them. See Environmental impact.

Rate limits are per account, not per key. A tight quickstart key and your production key draw on the same per-minute bucket for each endpoint, unless a key was created with its own limit. See Rate limits.

API-only accounts bill in credits. If your plan doesn't include API energy benefits, requests are paid in credits, not the energy pool that web sessions use. Pricing details in Pricing.

Explicit cache control isn't exposed — there's no field to mark a prefix as cacheable. But transparent prefix caching happens on the provider side: identical prefixes are auto-cached and reported back as usage.cached_tokens (nested in usage.prompt_tokens_details.cached_tokens), billed at the cheaper cache-read rate. See Models.

When it breaks

A migration that "just worked" in three lines and then fails in production is usually one of these:

  • Model ID typo — our errors are explicit. An unknown-model error means we don't have that ID. Check GET /v1/models.
  • Scope on the key — a key scoped to chat only (inference.chat) cannot call embeddings. Create a key with the scopes you need at Account → API keys. See Authentication.
  • Models outside your plan — a model your plan doesn't cover still runs; it's billed in credits instead of the plan. Check billing_cost.paid_with on the response. See Pricing.

Error handling and retry guidance: Errors.

On this page