Last verified: July 22, 2026
Short path: Start with the OpenAI-compatible API migration guide, compare OpenAI vs OpenRouter cost, and see cheap OpenAI API rates before moving traffic.
If you need to switch from OpenAI API to a compatible gateway, you probably do not want a rewrite. You want to change one configuration value, move the API key, run your existing tests, and know exactly what will break before the next invoice arrives.
That is the right approach. Most OpenAI SDK applications already separate provider configuration from business logic. If yours uses the OpenAI Chat Completions shape, the migration can often be limited to the base_url, credentials, and model identifier. The dangerous part is not the HTTP request. It is assuming that every native OpenAI feature, error behavior, model name, and operational guarantee transfers unchanged — see how to test an OpenAI-compatible endpoint before you cut over.
Quick Answer
To migrate from the direct OpenAI API to an OpenAI-compatible gateway:
- Create a gateway API key and store it separately from
OPENAI_API_KEY. - Change the SDK
base_urltohttps://api.lumeapi.site/v1. - Change authentication to
Authorization: Bearer $LUMEAPI_KEY. - Use an exact model ID from the gateway catalog, such as
gpt-5.6-terra. - Run contract tests for streaming, tool calls, structured output, retries, timeouts, and usage accounting.
- Shift traffic gradually instead of deleting your direct-provider configuration on day one.
- Compare gateway wallet charges with your own token logs before changing the whole production workload — full rate tables on AI API pricing.
For a deeper Python walkthrough, see OpenAI-compatible API in Python. If finance pressure is the trigger, pair this migration with OpenAI API too expensive?.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["LUMEAPI_KEY"],
base_url="https://api.lumeapi.site/v1",
)
response = client.chat.completions.create(
model="gpt-5.6-terra",
messages=[
{"role": "user", "content": "Summarize this incident report in five bullets."}
],
)
print(response.choices[0].message.content)The central rule is simple: treat the gateway as a new provider behind a familiar interface, not as a perfect clone of api.openai.com.
In short
A compatible gateway is usually the lowest-effort way to reduce model API spend because you can preserve most of your OpenAI SDK integration. The savings come from the gateway’s catalog rate, but the migration is only safe if you test the behavior your application actually uses. Change the endpoint and key first, then verify model output, tool calls, retries, usage fields, and failure handling before sending all production traffic through it.
What most guides get wrong
The common myth is that “OpenAI-compatible” means “drop-in identical.”
It usually means the gateway accepts a familiar request shape and returns a familiar response shape. That is valuable, but it does not promise identical support for every provider-native feature. A request that uses basic chat messages may work immediately while a request depending on a newer response API field, a provider-specific tool option, prompt caching, Batch processing, or a particular refusal structure needs separate testing.
The second mistake is changing only the URL and calling the migration complete. Your application may still read OPENAI_API_KEY, point at an old model name, retry a timeout seven times, or assume that every error is an OpenAI error object. Those details matter more than the one-line configuration change.
Use the compatibility layer to reduce code churn. Do not use it as a reason to skip an API contract test.
A realistic production scenario
Priya owns a Python service built with FastAPI and the OpenAI SDK. It classifies support tickets, calls an internal search tool for account context, and streams a final answer to an operator dashboard. The service runs in two Kubernetes deployments: ticket-api and ticket-worker.
The code change looks trivial. A Helm value changes the endpoint, and a new secret supplies the gateway key. During staging, however, Priya notices that the worker’s retry middleware retries a tool-call request after a timeout. The request is not obviously idempotent because the tool writes an audit event before returning account data. A transient timeout now creates duplicate audit records.
She also finds a second issue: the dashboard reports “tokens saved” using a usage field that the application never checked for null. The response shape is close enough for the happy path, but the monitoring code was built around assumptions from the direct provider.
The turning point is not a clever adapter. It is a migration checklist: isolate configuration, pin the model ID, test streaming and tools, make side effects idempotent, cap retries, and compare token counts. The gateway change takes minutes; proving it is safe takes the rest of the deployment.
Expert take
The practical benefit of a compatible gateway is configuration-level portability. Your application can continue using an OpenAI SDK while the transport destination and billing account change. That makes it a good fit for services whose provider-specific logic is thin: message construction, ordinary chat completions, streaming, and straightforward tool calls.
The less obvious mechanism is that migration risk grows with the number of assumptions hidden outside the API call. Search your codebase for:
- Hard-coded
api.openai.comURLs OPENAI_API_KEYreferences- Model names embedded in prompts, tests, and database rows
- Retry middleware that retries all 4xx and 5xx responses
- Usage accounting that assumes fields are always present
- Tool handlers with side effects
- Provider-specific request parameters
- Code that parses raw error text
- Dashboards that identify spend from provider names rather than model IDs
A gateway does not automatically fix a bad retry policy. In fact, cheaper requests can make an overly aggressive retry loop less visible during testing while still multiplying production traffic. One failed agent hop can resend the full conversation, tool results, and previous failure messages. If the seventh attempt is identical to the first, the lower token rate does not make the design sound.
Do not follow this advice blindly when your workload depends on provider-native Batch pricing, prompt caching, a Responses-only feature, or a strict provider-specific latency or data-processing requirement. The catalog rates below are useful for ordinary token-priced requests, but they are not a claim of parity with every native API feature. Keep the direct provider path for those workloads until you have verified an equivalent route.
LumeAPI is an independent third-party gateway, not OpenAI, Anthropic, or Google. It provides an OpenAI-compatible Chat Completions endpoint, but you remain responsible for checking feature support, model behavior, retention requirements, and operational fit for your application.
Before you change production
Start by writing down what “compatible” means for your service. A basic text summarizer and an agent with ten tools do not have the same migration surface.
Create a small inventory with four columns:
| Area | Current assumption | Test | Pass condition |
|---|---|---|---|
| Authentication | SDK reads OPENAI_API_KEY | Load a separate gateway secret | No provider key appears in gateway requests |
| Endpoint | Direct OpenAI URL | Send one staging request | Response arrives from the configured gateway |
| Model | Application uses a specific model string | Request an exact catalog ID | Model is accepted and output is usable |
| Streaming | Server-sent events are consumed incrementally | Stream a long response | Client receives chunks and a final completion |
| Tools | Tool calls are parsed into handlers | Force a known tool call | Arguments validate and side effects occur once |
| Errors | Middleware classifies provider errors | Simulate timeout and rate limit | Retry policy does not duplicate work |
| Usage | Billing dashboard reads token fields | Log prompt and completion usage | Missing or changed fields do not crash reporting |
This inventory catches a common failure: the API call works, but the surrounding code does not.
You should also capture a baseline before migration:
- Requests per minute and peak concurrency
- Average input and output tokens
- P50 and P95 application latency
- Error rate by status class
- Retry count
- Tool-call frequency
- Model IDs used by each route
- Monthly input and output token volume
Do not invent a baseline from provider marketing numbers. Use your own logs. If token usage is not logged today, add it before making a cost claim.
Step-by-step migration
1. Separate provider configuration from application code
Do not scatter the endpoint and key across constructors, test fixtures, and environment-specific branches. Put them behind configuration.
A minimal Python configuration looks like this:
import os
from openai import OpenAI
def build_client() -> OpenAI:
api_key = os.environ["LLM_API_KEY"]
base_url = os.environ.get(
"LLM_BASE_URL",
"https://api.lumeapi.site/v1",
)
return OpenAI(
api_key=api_key,
base_url=base_url,
timeout=30.0,
max_retries=0,
)
client = build_client()Using a generic LLM_API_KEY and LLM_BASE_URL makes the application easier to test against both providers. If you prefer provider-specific names, use OPENAI_API_KEY for direct traffic and LUMEAPI_KEY for gateway traffic, but do not let the name obscure the actual destination.
Setting max_retries=0 in this example is deliberate. It does not mean “never retry.” It means one layer owns retries. If the SDK retries and your HTTP middleware retries and your queue retries, a single timeout can become several paid requests. Implement one bounded policy at the service boundary.
2. Change the base URL and authentication
The gateway endpoint is:
https://api.lumeapi.site/v1The request uses a bearer key:
Authorization: Bearer $LUMEAPI_KEYWith the OpenAI Python SDK, the change is normally:
from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["LUMEAPI_KEY"],
base_url="https://api.lumeapi.site/v1",
)With curl:
curl https://api.lumeapi.site/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $LUMEAPI_KEY" \
-d '{
"model": "gpt-5.6-terra",
"messages": [
{
"role": "user",
"content": "Return the word OK and nothing else."
}
]
}'The direct-provider key should not be sent to the gateway. Rotate or revoke credentials according to your normal secret-management process if a key has been exposed in logs, shell history, CI output, or a client application.
For request-shape reference, compare your integration with the official OpenAI API documentation. The point is not to assume every endpoint is interchangeable; it is to identify which parts of your code rely on the standard Chat Completions shape.
3. Replace model names with exact catalog IDs
A compatible endpoint cannot infer that an internal alias such as production-default means a particular catalog model unless your own application maps it.
Keep an application-level alias, but make the mapping explicit:
MODEL_BY_ROUTE = {
"ticket_summary": "gpt-5.6-terra",
"simple_classification": "gpt-5.4-mini",
}
def summarize_ticket(client: OpenAI, text: str) -> str:
response = client.chat.completions.create(
model=MODEL_BY_ROUTE["ticket_summary"],
messages=[
{
"role": "system",
"content": "Summarize support tickets accurately and briefly.",
},
{"role": "user", "content": text},
],
)
return response.choices[0].message.content or ""The exact model ID matters for both availability and cost accounting. Do not assume that an old direct-provider model string automatically routes to the intended model.
If you want to test a lower-cost route, gpt-5.4-mini is listed at $0.225 per 1 million input tokens and $1.35 per 1 million output tokens through LumeAPI. That makes it a candidate for classification or extraction workloads, but you should decide with task evaluations rather than price alone.
4. Run a contract test, not just a smoke test
A smoke test asks whether one prompt returns text. A migration test asks whether the application’s important behaviors still hold.
At minimum, test:
- Plain text completion
- Long input near your normal context size
- Streaming
- Tool-call selection and argument parsing
- Structured output, if used
- Empty or malformed input
- Timeout handling
- Rate-limit handling
- Usage logging
- Content and refusal handling
- Model-not-found errors
- Cancellation when a user closes a connection
A simple non-streaming assertion:
def test_gateway_contract(client: OpenAI) -> None:
response = client.chat.completions.create(
model="gpt-5.6-terra",
messages=[
{
"role": "user",
"content": "Return valid JSON with the key status set to ok.",
}
],
)
assert response.choices
assert response.choices[0].message.contentFor production, make the test stronger. Validate the JSON with a schema, inspect tool arguments with a typed validator, and compare a fixed evaluation set against the direct-provider baseline. Do not require byte-for-byte output equality from generative models. Compare the properties your product needs: correct fields, valid citations, tool selection, refusal behavior, and acceptable latency.
5. Make retries safe before shifting traffic
Retries are where a low-cost migration can become a high-volume incident.
Use exponential backoff with a cap and a small retry budget. More importantly, retry only operations that are safe to repeat. A completion request that only returns text is easier to retry than a tool call that creates a refund, sends an email, or writes a database record.
import random
import time
from openai import APIConnectionError, APITimeoutError, RateLimitError
RETRYABLE = (APIConnectionError, APITimeoutError, RateLimitError)
def complete_with_bounded_retry(client, **kwargs):
max_attempts = 3
base_delay = 0.5
for attempt in range(max_attempts):
try:
return client.chat.completions.create(**kwargs)
except RETRYABLE:
if attempt == max_attempts - 1:
raise
delay = min(8.0, base_delay * (2 ** attempt))
time.sleep(delay + random.uniform(0, 0.2))This pattern is intentionally incomplete for a full production client. Add request IDs, structured logs, cancellation, and status-aware handling. Do not retry authentication failures, invalid requests, or model-not-found errors as if they were transient.
For agent workflows, put an idempotency boundary around side-effecting tools. Persist a tool-operation ID, check it before applying the side effect, and only then mark the operation complete. A gateway cannot determine whether your tool is safe to repeat.
OpenAI direct rates versus LumeAPI rates
The following catalog rates were updated July 22, 2026. Prices are USD per 1 million tokens, shown as input / output. Monthly examples below use:
- 10 million input tokens
- 2 million output tokens
- No retries, taxes, wallet fees, or other charges
- The listed model for every request
| Model | Official input / output | LumeAPI input / output | Official monthly math | LumeAPI monthly math |
|---|---|---|---|---|
gpt-5.6-sol | $5.00 / $30.00 | $1.50 / $9.00 | $50 + $60 = $110 | $15 + $18 = $33 |
gpt-5.6-terra | $2.50 / $15.00 | $0.75 / $4.50 | $25 + $30 = $55 | $7.50 + $9 = $16.50 |
gpt-5.5 | $5.00 / $30.00 | $1.50 / $9.00 | $50 + $60 = $110 | $15 + $18 = $33 |
gpt-5.4 | $2.50 / $15.00 | $0.75 / $4.50 | $25 + $30 = $55 | $7.50 + $9 = $16.50 |
gpt-5.4-mini | $0.75 / $4.50 | $0.225 / $1.35 | $7.50 + $9 = $16.50 | $2.25 + $2.70 = $4.95 |
The arithmetic is straightforward, but the production conclusion is not “move every request to the most expensive model at a discount.” The better decision is to preserve quality where it affects the user and route simpler work to an appropriate model.
For example, at the stated volume, gpt-5.6-terra through LumeAPI costs $16.50 before other considerations. The same token volume at gpt-5.4-mini costs $4.95. If the mini model passes your extraction and classification evaluations, it can reduce spend further. If it fails on tool selection or nuanced reasoning, the cheaper rate is false economy.
LumeAPI also lists these non-OpenAI model IDs:
| Model | Official input / output | LumeAPI input / output |
|---|---|---|
claude-opus-4-8 | $5.00 / $25.00 | $2.50 / $12.50 |
claude-opus-4-7 | $5.00 / $25.00 | $2.50 / $12.50 |
claude-sonnet-4-6 | $3.00 / $15.00 | $1.50 / $7.50 |
claude-fable-5 | $10.00 / $50.00 | $5.00 / $25.00 |
gemini-3.1-pro-preview | $2.00 / $12.00 | $1.00 / $6.00 |
gemini-3.5-flash | $1.50 / $9.00 | $0.75 / $4.50 |
gemini-3-flash | $0.50 / $3.00 | $0.25 / $1.50 |
Those rates make model substitution possible without rewriting the client abstraction, but model substitution is not automatically behavior-neutral. Keep prompts, evaluation cases, and output schemas under version control when you change models.
OpenAI SDK change base URL in production
The code change is small; the deployment change needs more care.
Use a staged configuration sequence:
Stage 1: Add the alternate configuration
Deploy code that can select either provider without changing the default route:
import os
from openai import OpenAI
def make_client(provider: str) -> OpenAI:
if provider == "lumeapi":
return OpenAI(
api_key=os.environ["LUMEAPI_KEY"],
base_url="https://api.lumeapi.site/v1",
max_retries=0,
)
return OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
max_retries=0,
)The direct client omits base_url, so the SDK uses its normal default. The gateway client uses the explicit LumeAPI endpoint.
Stage 2: Route a small, representative slice
A tiny traffic slice is useful only if it includes the hard cases. Do not send only easy summaries to the gateway while keeping tool-heavy agent requests on the direct path. That produces a comforting but irrelevant comparison.
Select requests by route, tenant, or deterministic hash. Log:
- Provider route
- Exact model ID
- Request and response correlation IDs
- Input and output token counts when available
- Duration
- Retry attempts
- HTTP status class
- Tool-call count
- Validation failures
- User-visible fallback events
Avoid logging prompts or sensitive tool arguments unless your privacy policy permits it. Token counts and metadata are often enough to compare cost and behavior.
Stage 3: Compare outcomes, not just HTTP 200s
A successful HTTP response can still be a failed product request. Compare:
- Schema validation rate
- Correct tool selection
- Tool argument validation
- Completion length
- Empty-content rate
- Refusal handling
- Streaming disconnects
- Timeout rate
- User correction or escalation rate
- Tokens per successful task
The last metric is especially useful. A model that is 40% cheaper per token but needs twice as many retries or produces longer outputs may not reduce cost per completed task.
Stage 4: Change the default and preserve rollback
Once the gateway passes your acceptance thresholds, switch the default through a feature flag or deployment variable. Keep the direct-provider configuration available during the rollback window. Do not remove the old secret and code path in the same release that changes the default.
A rollback should be a configuration change, not an emergency code edit.
When a gateway is the wrong migration target
A gateway is not automatically the best destination for every request.
Stay with a native provider path, or use a split architecture, when you require:
- A provider-native endpoint not exposed through the compatible Chat Completions interface
- Batch processing or prompt-cache economics that the gateway catalog does not promise
- A provider-specific feature your contract tests cannot verify
- Strict contractual, residency, or procurement requirements
- Direct access to provider-native observability or support escalation
- A latency or availability requirement that has not been validated for the gateway route
This is also where leaving OpenAI billing for an API gateway can become operationally awkward. You may save on token rates but add another wallet, invoice workflow, security review, and incident path. The migration should reduce total operating cost, not merely move the line item.
A split is often sensible: route ordinary Chat Completions traffic through the gateway, while keeping a small native integration for features that require it. That gives you savings without pretending the interfaces are identical.
Operational checklist
Before declaring the migration complete, check each item:
Configuration
- [ ] Gateway endpoint is
https://api.lumeapi.site/v1 - [ ] Gateway authentication uses
LUMEAPI_KEY - [ ] Keys are stored in the secret manager, not source code
- [ ] Direct-provider and gateway settings can be selected independently
- [ ] Model IDs are explicit and catalog-backed
Application behavior
- [ ] Plain completions work
- [ ] Streaming works through the full proxy chain
- [ ] Tool calls parse correctly
- [ ] Tool side effects are idempotent
- [ ] Structured outputs pass schema validation
- [ ] Empty content and refusals are handled
- [ ] Cancellation does not leave orphaned work
- [ ] Usage fields can be missing or changed without crashing metrics
Reliability
- [ ] Only one layer owns retries
- [ ] Authentication and invalid-request errors are not retried
- [ ] Backoff has a maximum delay
- [ ] Request timeouts are explicit
- [ ] Queue redelivery cannot duplicate side effects
- [ ] A rollback flag has been tested
Cost control
- [ ] Input and output tokens are logged
- [ ] Model IDs are included in cost reports
- [ ] Retry attempts are counted
- [ ] Long prompts and repeated tool results are visible
- [ ] Monthly spend alerts exist on both the wallet and application side
- [ ] Cost is measured per successful task, not only per request
FAQ
How do I switch from OpenAI API to compatible gateway without rewriting my application?
Change the client’s base_url, supply the gateway key, and use an exact supported model ID. Then test every feature your application uses. Basic Chat Completions integrations may require only a few lines of configuration; tool-heavy or provider-specific applications need a compatibility review.
What does “migrate OpenAI API to gateway” actually change?
It changes the network destination and billing relationship while preserving a familiar request format. Your application still sends messages and receives completions through an OpenAI-compatible interface, but the gateway becomes the service handling that request. Feature support and error behavior must be verified rather than assumed.
How do I change the OpenAI SDK base URL in production?
Pass base_url="https://api.lumeapi.site/v1" when constructing the OpenAI client and use a gateway API key. Put both values behind environment configuration or a feature flag, deploy the alternate path first, and make rollback possible without rebuilding the application.
Can I keep using the OpenAI Python SDK with LumeAPI?
Yes, for the compatible Chat Completions integration described here. The client can be constructed with the LumeAPI base URL and a LumeAPI key. You should still test streaming, tools, structured output, usage reporting, and any provider-native options your code sends.
Should I move every OpenAI request to the gateway?
No. Move the traffic that fits the compatible interface and passes your evaluations. Keep native-provider traffic for features, compliance requirements, Batch or prompt-cache economics, or operational guarantees that the gateway route does not provide.
How much can the migration save?
The answer depends on your model and token mix. At 10 million input and 2 million output tokens per month, gpt-5.6-terra is listed at $55 using the stated official rates and $16.50 through LumeAPI. Your actual result changes with output length, retries, model selection, and traffic volume.
Next steps
- Inventory your current endpoint, key references, model IDs, retries, tools, and usage metrics. Use the OpenAI-compatible API guide as a checklist for the interface boundary.
- Add a provider switch, point staging at
https://api.lumeapi.site/v1, and run contract tests withgpt-5.6-terraplus the model you intend to use for lower-cost routes. - Send a representative production slice through the OpenAI-compatible endpoint, compare cost per successful task, and keep a tested rollback path until the results are stable.
Changing the URL is the easy part. The useful migration is the one that lowers your bill without turning retries, tool calls, or provider-specific assumptions into the next incident.