Choose Auto, TokenLab Verified, or Official for each request, with prices shown up front.See what's new

Migrate from OpenAI to TokenLab in 5 Minutes

·September 19, 2026·10 min read·Updated October 2, 2026·3128 views
#tutorial#migration#openai#getting-started
Migrate from OpenAI to TokenLab in 5 Minutes

What you’ll learn

  • Do I need to change my model names when I switch from OpenAI?
  • Will streaming and tool calls behave exactly like OpenAI's API?
  • What status code do I get when my balance runs out?
  • Can I call Claude or Gemini models from the same OpenAI client?

The base URL is the easy part of leaving a provider; the failure paths are where migrations go wrong. To migrate from OpenAI to TokenLab, you change two values in your OpenAI SDK client: base_url and api_key. The rest of this guide covers what to confirm around that change. That means the model ID you send, its current price, streaming, tool calls, error handling, timeouts and billing. Facts below come from TokenLab docs and the live model API, each with its observed date.

Key Takeaways

  • The core change is two values: the TokenLab base URL https://api.tokenlab.sh/v1 and a TokenLab API key (they start with sk-).
  • TokenLab documents OpenAI SDK support for Chat Completions and Responses. Optional parameters, tool options and Responses-only fields still depend on the selected model.
  • Read the price of your model from the live API before you decide anything. On 2026-10-03, gpt-5.5 listed $1.50 input and $9.00 output per 1M tokens.
  • Run the checklist at the end before you move production traffic. Most surprises live in error handling, timeouts and billing, not in the happy path.

The Two-Value Change to Migrate from OpenAI to TokenLab

Start with the key. Per the Quickstart (observed 2026-10-03), you create an account, create an API key, and save the full value immediately. It is shown only once, and the prefix in the key list cannot authenticate requests. Check your balance before the first call, because requests bill at the selected model's current price.

Then change the client. The migration guide (observed 2026-10-03) describes the recipe as: set base_url / baseURL to https://api.tokenlab.sh/v1, replace the key, and choose a model ID from GET /v1/models.

For example, imagine a service that has the string gpt-5.5 in its config. After the two-value change, that same string is a valid request, but we would still confirm the ID first. GET /v1/models and GET /v1/models/{model} are public discovery endpoints and work without a key.

Python

import os
from openai import OpenAI

# Before: client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
client = OpenAI(
    api_key=os.environ["TOKENLAB_API_KEY"],
    base_url="https://api.tokenlab.sh/v1",
    timeout=30.0,
    max_retries=0,
)

response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Hello, world!"}],
)
print(response.choices[0].message.content)

Node.js

import OpenAI from 'openai';

// Before: new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
const client = new OpenAI({
  apiKey: process.env.TOKENLAB_API_KEY,
  baseURL: 'https://api.tokenlab.sh/v1',
  timeout: 30_000,
  maxRetries: 0,
});

const completion = await client.chat.completions.create({
  model: 'gpt-5.5',
  messages: [{ role: 'user', content: 'Hello' }],
});
console.log(completion.choices[0].message.content);

cURL

curl https://api.tokenlab.sh/v1/chat/completions \
  -H "Authorization: Bearer $TOKENLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-5.5","messages":[{"role":"user","content":"Say hello"}]}'

The timeout and retry settings in the first two samples mirror the Quickstart examples (observed 2026-10-03), which use a 30-second timeout and zero SDK retries. We keep retries at zero during testing so that a failing request is visible instead of being retried silently.

Pass the base URL explicitly in client configuration. The SDK guide (observed 2026-10-03) recommends this over relying on older environment-variable aliases. Keep the key on the server and in a secret manager, never in client-side code.

Pick the Model ID and Read Its Price

A migration should not assume a model ID or a price. Both live in the model API. We read https://api.tokenlab.sh/v1/models/gpt-5.5 and https://api.tokenlab.sh/v1/models/laguna-s-2.1 on 2026-10-03. Pricing for both was last updated 2026-10-02T16:53:30.068Z.

Field gpt-5.5 laguna-s-2.1
Lifecycle stage active active
Max input / output tokens 1,000,000 / 128,000 1,048,576 / 131,072
Accepted request formats openai_chat_completions, openai_responses openai_chat_completions
Capabilities listed coding, json-mode, prompt-cache, reasoning, tool-use, vision tool-use
Input, USD per 1M tokens 1.5 0.1
Output, USD per 1M tokens 9 0.2
Cache read, USD per 1M tokens 0.15 0.01

Sources: gpt-5.5 and laguna-s-2.1, both observed 2026-10-03.

To turn those rates into a number, here is an estimate with the working shown. Take a job with 1M input tokens and 100k output tokens, with no cache hits.

  • gpt-5.5: 1 × $1.50 + 0.1 × $9.00 = $1.50 + $0.90 = $2.40.
  • laguna-s-2.1: 1 × $0.10 + 0.1 × $0.20 = $0.10 + $0.02 = $0.12.

These are estimates from listed per-token rates. Your final charge is the Usage record. Tokenization differs by model, so the same text produces different token counts on different models.

We do not claim a saving here. To compare against what you pay today, put the TokenLab rates next to your own OpenAI invoice, or the OpenAI pricing page, on the day you switch. Prices change, and the billing guide (observed 2026-10-03) says not to hard-code a copied price table. It points to GET /v1/models/:model/pricing for current values.

Other model IDs follow the same pattern. The docs examples use gpt-5.6-terra and gpt-5.6-luna for Chat Completions, and claude-sonnet-5 and gemini-3.5-flash on their own routes. Read each model's accepted formats before you point traffic at it. For wider comparisons, see the model directory, the OpenRouter vs TokenLab comparison and the model rankings. Image and video teams can start with the best AI image models API 2026 and best AI video models API 2026. For code tasks, see best AI models for coding.

What to Check Next When You Migrate from OpenAI to TokenLab

TokenLab documents the OpenAI SDK as working with Chat Completions and Responses. That is compatibility with the request and response format, not a promise that every model behaves the same. The API formats guide (observed 2026-10-03) says optional parameters depend on the model. It also says a model does not necessarily accept all four API formats, and tokenlab.accepted_request_formats shows which it accepts. Treat each area below as something to test with your real traffic.

Streaming

stream: true sends partial message deltas as server-sent events. Set stream_options with include_usage: true to receive token usage in stream chunks, as the Create Chat Completion reference (observed 2026-10-03) documents.

stream = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Count to five."}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="")

Two behaviors to plan for. If a stream is interrupted after output arrived, do not treat it as a complete response. The error handling guide (observed 2026-10-03) warns that repeating it may produce different output or a second charge. And streaming can finish before billing does, so the billing ID may be absent.

Tool calls

The Chat Completions reference lists tools, tool_choice and parallel_tool_calls. It says parallel calls work "when supported by the selected model." Function calling is documented as "supported by the selected model," so check the capabilities list. In the table above, both gpt-5.5 and laguna-s-2.1 list tool-use, but only gpt-5.5 lists json-mode and vision. Send your real tool schemas, not a toy example, and check that the returned arguments parse.

If you plan to call Claude models, note the migration guide's rule. Claude tool calls, thinking blocks and Anthropic message fields belong on /v1/messages, and Chat Completions does not guarantee them.

Error shapes

Chat Completions and Responses return an OpenAI-style error object. Per the error handling guide, only message and type are always present. Fields such as code, param, retryable and retry_after appear when relevant. Branch on HTTP status and code, not on the message text, and make your parser tolerate missing fields. Anthropic Messages and Gemini keep their own error formats, so one parser will not cover every route.

Status Code What it means
401 invalid_api_key Key is missing, invalid, inactive or revoked
401 expired_api_key Key has expired
402 insufficient_balance Account balance cannot cover the request
402 quota_exceeded The key's own usage limit was reached
403 model_not_allowed This key cannot use the requested model
429 rate_limit_exceeded Too many requests; wait for Retry-After

Sources: Authentication and error handling, observed 2026-10-03.

This table corrects a common assumption. An empty balance is a 402, not a 401. If your current code treats every 4xx as a bad key, update it.

Timeouts and retries

The migration guide says existing retry, timeout and streaming code can usually stay. Review it against the documented retry rules.

  • Do not repeat 400, 401, 402, 403, 404 or 413 responses unchanged.
  • Retry 429 after the server-provided delay.
  • Retry 500–504 only when retryable is true, and respect retry_after.
  • A 503 all_channels_failed can come back with retryable: false. In that case the operation has no supply in the selected delivery tier, so repeating it will not help.

Save the Request ID from the response headers with the model and your own job ID. It is what you need for an investigation.

Billing

One balance works across models, with no subscription or minimum spend, per the billing guide. Each completed request is charged once, for the delivery option that produced it. The options are TokenLab Verified, Official and Auto, and Auto tries Verified first, then Official. Set a spending limit on each API key if you want a hard stop. When the limit is reached, requests with that key return 402.

Non-streaming OpenAI-compatible responses include billing_transaction_id when billing finishes before the response is sent. It may also appear in the X-Billing-Transaction-ID header. Store it, and reconcile against the Usage page rather than your own token math.

Verification Checklist After You Migrate from OpenAI to TokenLab

Run these in order against a staging key before production traffic moves. Each row traces to a documented behavior above.

Step What to run What you should see
1. Model discovery GET /v1/models/gpt-5.5 (no key needed) Lifecycle active and the accepted formats you plan to use
2. Authenticated request The Python or cURL sample above A non-empty answer; the request appears in the Requests view with model, status and usage
3. Usage fields Read usage on a non-streaming response prompt_tokens, completion_tokens, total_tokens
4. Streaming stream: true with include_usage: true SSE chunks, then usage; an interrupted stream is handled as incomplete
5. Tool calls Your real tools and tool_choice Arguments parse and match your schema
6. Vision or JSON mode Only if the model lists vision or json-mode Expected output; skip the test if the capability is not listed
7. Bad key Request with a deleted or wrong key 401 invalid_api_key
8. No balance or key limit Use a key with a low limit or an empty workspace 402 insufficient_balance or quota_exceeded
9. Model restriction Restrict a key's model list, then request another model 403 model_not_allowed
10. Timeout and retry Force a timeout in staging Your code retries only per retryable and retry_after
11. Billing Compare billing_transaction_id and Usage with your estimate Charge matches the model's current price and the recorded tokens

After the table passes, change your production configuration and deploy. Keep the old OpenAI key active until Usage confirms the new path is stable.

Frequently Asked Questions

Do I need to change my model names when I switch from OpenAI?

Not necessarily, but confirm each one. TokenLab model IDs are exact strings, so check them with GET /v1/models or GET /v1/models/{model}. On 2026-10-03 the live API listed gpt-5.5 as active. If a request returns model_not_found, the ID is unknown or unavailable. Read the model list and use a current ID.

Will streaming and tool calls behave exactly like OpenAI's API?

TokenLab documents streaming through SSE and function calling through the OpenAI-compatible request format. The docs also say supported options depend on the selected model. We therefore treat the result as compatible, not identical. Test streaming, tools, tool_choice and any response_format you use with the specific model you plan to run.

What status code do I get when my balance runs out?

You get HTTP 402 with the code insufficient_balance. A key that reached its own spending limit also returns 402, with quota_exceeded. A missing, invalid or revoked key returns 401. Do not retry any of these unchanged. Top up the balance, raise the key limit, or replace the key.

Can I call Claude or Gemini models from the same OpenAI client?

The model catalog lists claude-sonnet-5 and gemini-3.5-flash with openai_chat_completions among their request formats. Basic chat can therefore go through the same client. Claude-specific fields such as thinking blocks and Claude tool use belong on /v1/messages. Gemini-native fields stay on the /v1beta route. Keep one API format per conversation.

Start Building on TokenLab

Create a key at TokenLab, set the base URL to https://api.tokenlab.sh/v1, and run the Quickstart request before touching production.

Sources

Prices checked 2026-10-03

Related models

Recent model releases

Try the models from this article

Chat, create images, or make video with the same TokenLab balance.