AI From U AI FROM U.COM

Blog / Guides

Point the OpenAI SDK at a new base URL

Two changes move an existing OpenAI-SDK app here: the base URL and the key. Chat completions, responses, streaming and tool calling all arrive unchanged.

An application that already speaks to the OpenAI SDK does not have to be rewritten to speak to us. Two things move: the base URL the client is built with, and the key it authenticates with. Everything above and below those two lines — the call, the messages, the parameters, the way you read the answer back — stays exactly as you wrote it.

The two lines that change

In Python, the base URL and the key are the two arguments the client is constructed with. Nothing after the constructor is ours:

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://aifromu.com/v1",
    api_key=os.environ["AIFROMU_API_KEY"],
)

resp = client.chat.completions.create(
    model="terra",
    messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)

In Node, the same two, in the object the client is constructed from:

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://aifromu.com/v1",
  apiKey: process.env.AIFROMU_API_KEY,
});

const resp = await client.chat.completions.create({
  model: "terra",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(resp.choices[0].message.content);

The key comes from the customer portal: sign in, open the Keys page, and the key you claim there is the one this client sends. Both examples read it out of the environment rather than out of the file, under the name AIFROMU_API_KEY, because a key committed alongside the code is a key that has to be rotated the moment somebody clones the repository.

Both endpoints, streaming and tools

Both /v1/chat/completions and /v1/responses are served here, so whichever of the two your code already calls is the one it can keep calling — there is no migration between them to do on the way in. Streaming passes through unchanged, and so does tool calling: the request goes up in the shape you wrote it, and the events come back in the shape the SDK is already parsing.

What happens to your model names

The four aliases — astra, sol, terra and luna — work directly, so a client that names one is asking for exactly the model on that card. A client that names an OpenAI model is read as its weight class instead: a mini or nano name is served as luna, an ordinary 4-series name as terra, a frontier or o-series name as sol, and a gpt-6 name as astra. That is what lets an unchanged model line keep working on the first request after the base URL moves, and what it costs is what it is billed as — the class that served the request, not the name that asked for it.

A name that fits nowhere is not guessed at: the request is refused with a message naming the four models, so a misconfiguration is something you see on the first call rather than something you find on a bill. Guessing would be the worse failure of the two, because it would be silent — a name read as the wrong class serves one customer at a loss and charges another for capability they never got, and nothing in either request says so.

Check it works, and read the errors

The first call is the whole verification: if the answer comes back, the base URL and the key are both right, and nothing else in the file needed to change. If it does not, the refusal tells you which of the two it was — an unusable key is answered as an invalid key, and a model this gateway does not serve is answered with the four names it does.

Errors are truthful the rest of the way as well. When the upstream refuses a request, the validation reason it gave passes through to you instead of being flattened into one opaque string, so a context that was too long or a parameter that was wrong says so in the answer. Retry-After is kept on a 429, because that header is what the SDKs pace their own retries by, and a rate limit relayed without it is a rate limit your client has to guess at.

A name that fits nowhere is not guessed at: the request is refused with a message naming the four models, so a misconfiguration is something you see on the first call rather than something you find on a bill.