Migrating from OpenAI
The gateway implements the OpenAI wire format, so migrating an existing integration is a configuration change, not a rewrite. Three things change:
- Base URL →
https://api.smartapihub.com/v1 - API key → your
sk-llm-…key from the dashboard - Model id → prefixed with the vendor:
gpt-4o-minibecomesopenai/gpt-4o-mini
Before / after
typescript
import OpenAI from 'openai';
// before
// const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// after
const client = new OpenAI({
baseURL: 'https://api.smartapihub.com/v1',
apiKey: process.env.LLM_API_KEY,
});
const res = await client.chat.completions.create({
model: 'openai/gpt-4o-mini', // was 'gpt-4o-mini'
messages: [{ role: 'user', content: 'Hello' }],
});python
from openai import OpenAI
# before: client = OpenAI()
client = OpenAI(base_url="https://api.smartapihub.com/v1", api_key=os.environ["LLM_API_KEY"])
res = client.chat.completions.create(
model="openai/gpt-4o-mini", # was "gpt-4o-mini"
messages=[{"role": "user", "content": "Hello"}],
)Most OpenAI SDKs honour OPENAI_BASE_URL and OPENAI_API_KEY, so you can migrate without touching code:
bash
export OPENAI_BASE_URL="https://api.smartapihub.com/v1"
export OPENAI_API_KEY="sk-llm-…"Only the model ids in your code need the vendor/ prefix.
Model id mapping
| OpenAI id | Gateway id |
|---|---|
gpt-4o | openai/gpt-4o |
gpt-4o-mini | openai/gpt-4o-mini |
text-embedding-3-small | openai/text-embedding-3-small |
dall-e-3 | openai/dall-e-3 |
tts-1 | openai/tts-1 |
whisper-1 | openai/whisper-1 |
The exact set of available models depends on what your operator has enabled; always check GET /v1/models. Once migrated, switching to another vendor is one string: anthropic/claude-3-5-haiku, meta/llama-3.1-70b-instruct, and so on — the request shape stays the same.
What is the same
- Request and response bodies for chat completions, completions, embeddings, images, speech and transcriptions.
- SSE streaming format, including
data: [DONE]. - Tool calling (
tools,tool_choice,tool_calls),response_format(json_object,json_schema),seed, penalties,logit_bias,stop. - Error envelope shape:
{ "error": { "type", "code", "message", "param" } }.
What is different
| Area | Difference |
|---|---|
n | Only n: 1 is supported. |
usage | Always present on non-streaming responses and always emitted as a final stream chunk — you no longer need stream_options.include_usage. Contains x_llm_cost_micro and, when estimated, x_llm_usage_estimated: true. |
provider | Extra top-level field on responses naming the provider that served the request. |
routing | Optional request extension to override routing per request. Stripped before forwarding. |
| Headers | X-Request-Id, X-LLM-Provider, X-LLM-Model, X-LLM-Routing-Reason, X-LLM-Cost-Micro on every inference response. |
| Errors | error.code uses the gateway's code enum, and error.request_id is always present. |
| Video / music | Async job endpoints (202 + polling / webhooks) that do not exist in the OpenAI API. Idempotency-Key is required. |
| Responses API | Supported as a documented subset. |
| Fine-tuning, files, assistants, batches, realtime | Not provided by the gateway. |
Checklist
- Replace base URL and key.
- Prefix model ids with the vendor.
- Remove any code that assumes
n > 1. - Read
usage.x_llm_cost_microinstead of computing cost client-side. - Log
X-Request-Idalongside your own request logs. - Handle
402(credits/budget) in addition to429— see API Keys.