Migrate from Portkey
Switch from Portkey to LLM Gateway. Same OpenAI-compatible API, no virtual keys or special headers, fully open-source self-hosting.
Published
Portkey wraps your provider calls in virtual keys, config IDs, and x-portkey-* headers. LLM Gateway keeps the OpenAI-compatible interface but drops the extra ceremony: standard Bearer auth, provider keys managed in a dashboard, and the option to self-host the entire platform under AGPLv3. Migration is mostly a base URL change.
Quick Migration
Both services are OpenAI-compatible, so the core change is the base URL and dropping Portkey's custom headers:
1- const baseURL = "https://api.portkey.ai/v1";2- // plus x-portkey-api-key and x-portkey-virtual-key headers3+ const baseURL = "https://api.llmgateway.io/v1";4
5- const apiKey = process.env.PORTKEY_API_KEY;6+ const apiKey = process.env.LLM_GATEWAY_API_KEY; // standard Bearer auth1- const baseURL = "https://api.portkey.ai/v1";2- // plus x-portkey-api-key and x-portkey-virtual-key headers3+ const baseURL = "https://api.llmgateway.io/v1";4
5- const apiKey = process.env.PORTKEY_API_KEY;6+ const apiKey = process.env.LLM_GATEWAY_API_KEY; // standard Bearer authWhy Teams Switch to LLM Gateway
| What You Get | Portkey | LLM Gateway |
|---|---|---|
| OpenAI-compatible API | Yes | Yes |
| Custom headers / virtual keys | Required for provider routing | Not needed |
| Open-source self-hosting | Gateway/router only (MIT) | Full platform (AGPLv3) |
| Automatic provider routing | Manual config | Live scoring, automatic |
| Response caching | Simple + semantic | Built-in, one toggle |
| Image & video generation | Limited | Same API as chat |
| Pricing | Usage/seat-based tiers | 5% platform fee, or 0% with your keys |
Want a feature-by-feature breakdown? See LLM Gateway vs Portkey.
Migration Steps
1. Get Your LLM Gateway API Key
Sign up at llmgateway.io/signup and create an API key from your dashboard.
2. Map Your Models
LLM Gateway supports two model ID formats:
Root Model IDs (without provider prefix) — uses smart routing to automatically select the best provider based on uptime, throughput, price, and latency:
1gpt-5.22claude-opus-4-5-202511013gemini-3-flash-preview1gpt-5.22claude-opus-4-5-202511013gemini-3-flash-previewProvider-Prefixed Model IDs — routes to a specific provider with automatic failover if uptime drops:
1openai/gpt-5.22anthropic/claude-opus-4-5-202511013google-ai-studio/gemini-3-flash-preview1openai/gpt-5.22anthropic/claude-opus-4-5-202511013google-ai-studio/gemini-3-flash-previewIn Portkey, the provider is usually selected by the virtual key or config attached to the request. With LLM Gateway, you select the provider in the model ID itself (or let smart routing choose) — there's no separate virtual key to manage.
For more on routing behavior, see the routing documentation.
3. Update Your Code
Python with OpenAI SDK
1from openai import OpenAI2
3# Before (Portkey via OpenAI SDK)4from portkey_ai import createHeaders5
6client = OpenAI(7 base_url="https://api.portkey.ai/v1",8 api_key="dummy",9 default_headers=createHeaders(10 api_key=os.environ["PORTKEY_API_KEY"],11 virtual_key=os.environ["PORTKEY_VIRTUAL_KEY"],12 ),13)14
15# After (LLM Gateway) - no custom headers, no virtual key16client = OpenAI(17 base_url="https://api.llmgateway.io/v1",18 api_key=os.environ["LLM_GATEWAY_API_KEY"],19)20
21response = client.chat.completions.create(22 model="gpt-5.2", # or "openai/gpt-5.2" to target a specific provider23 messages=[{"role": "user", "content": "Hello!"}],24)1from openai import OpenAI2
3# Before (Portkey via OpenAI SDK)4from portkey_ai import createHeaders5
6client = OpenAI(7 base_url="https://api.portkey.ai/v1",8 api_key="dummy",9 default_headers=createHeaders(10 api_key=os.environ["PORTKEY_API_KEY"],11 virtual_key=os.environ["PORTKEY_VIRTUAL_KEY"],12 ),13)14
15# After (LLM Gateway) - no custom headers, no virtual key16client = OpenAI(17 base_url="https://api.llmgateway.io/v1",18 api_key=os.environ["LLM_GATEWAY_API_KEY"],19)20
21response = client.chat.completions.create(22 model="gpt-5.2", # or "openai/gpt-5.2" to target a specific provider23 messages=[{"role": "user", "content": "Hello!"}],24)Python with the Portkey SDK
If you use the native portkey-ai client, swap to the OpenAI SDK pointed at LLM Gateway:
1# Before (native Portkey SDK)2from portkey_ai import Portkey3
4portkey = Portkey(5 api_key=os.environ["PORTKEY_API_KEY"],6 virtual_key=os.environ["PORTKEY_VIRTUAL_KEY"],7)8
9response = portkey.chat.completions.create(10 model="gpt-5.2",11 messages=[{"role": "user", "content": "Hello!"}],12)13
14# After (LLM Gateway via the standard OpenAI SDK)15from openai import OpenAI16
17client = OpenAI(18 base_url="https://api.llmgateway.io/v1",19 api_key=os.environ["LLM_GATEWAY_API_KEY"],20)21
22response = client.chat.completions.create(23 model="gpt-5.2",24 messages=[{"role": "user", "content": "Hello!"}],25)1# Before (native Portkey SDK)2from portkey_ai import Portkey3
4portkey = Portkey(5 api_key=os.environ["PORTKEY_API_KEY"],6 virtual_key=os.environ["PORTKEY_VIRTUAL_KEY"],7)8
9response = portkey.chat.completions.create(10 model="gpt-5.2",11 messages=[{"role": "user", "content": "Hello!"}],12)13
14# After (LLM Gateway via the standard OpenAI SDK)15from openai import OpenAI16
17client = OpenAI(18 base_url="https://api.llmgateway.io/v1",19 api_key=os.environ["LLM_GATEWAY_API_KEY"],20)21
22response = client.chat.completions.create(23 model="gpt-5.2",24 messages=[{"role": "user", "content": "Hello!"}],25)TypeScript/JavaScript
1import OpenAI from "openai";2
3// Before (Portkey via OpenAI SDK)4import { createHeaders } from "portkey-ai";5
6const client = new OpenAI({7 baseURL: "https://api.portkey.ai/v1",8 apiKey: "dummy",9 defaultHeaders: createHeaders({10 apiKey: process.env.PORTKEY_API_KEY,11 virtualKey: process.env.PORTKEY_VIRTUAL_KEY,12 }),13});14
15// After (LLM Gateway) - standard Bearer auth, no extra headers16const llmgateway = new OpenAI({17 baseURL: "https://api.llmgateway.io/v1",18 apiKey: process.env.LLM_GATEWAY_API_KEY,19});20
21const completion = await llmgateway.chat.completions.create({22 model: "gpt-5.2", // or "openai/gpt-5.2" to target a specific provider23 messages: [{ role: "user", content: "Hello!" }],24});1import OpenAI from "openai";2
3// Before (Portkey via OpenAI SDK)4import { createHeaders } from "portkey-ai";5
6const client = new OpenAI({7 baseURL: "https://api.portkey.ai/v1",8 apiKey: "dummy",9 defaultHeaders: createHeaders({10 apiKey: process.env.PORTKEY_API_KEY,11 virtualKey: process.env.PORTKEY_VIRTUAL_KEY,12 }),13});14
15// After (LLM Gateway) - standard Bearer auth, no extra headers16const llmgateway = new OpenAI({17 baseURL: "https://api.llmgateway.io/v1",18 apiKey: process.env.LLM_GATEWAY_API_KEY,19});20
21const completion = await llmgateway.chat.completions.create({22 model: "gpt-5.2", // or "openai/gpt-5.2" to target a specific provider23 messages: [{ role: "user", content: "Hello!" }],24});cURL
1# Before (Portkey)2curl https://api.portkey.ai/v1/chat/completions \3 -H "x-portkey-api-key: $PORTKEY_API_KEY" \4 -H "x-portkey-virtual-key: $PORTKEY_VIRTUAL_KEY" \5 -H "Content-Type: application/json" \6 -d '{7 "model": "gpt-5.2",8 "messages": [{"role": "user", "content": "Hello!"}]9 }'10
11# After (LLM Gateway) - single Authorization header12curl https://api.llmgateway.io/v1/chat/completions \13 -H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \14 -H "Content-Type: application/json" \15 -d '{16 "model": "gpt-5.2",17 "messages": [{"role": "user", "content": "Hello!"}]18 }'19# Use "openai/gpt-5.2" to target a specific provider1# Before (Portkey)2curl https://api.portkey.ai/v1/chat/completions \3 -H "x-portkey-api-key: $PORTKEY_API_KEY" \4 -H "x-portkey-virtual-key: $PORTKEY_VIRTUAL_KEY" \5 -H "Content-Type: application/json" \6 -d '{7 "model": "gpt-5.2",8 "messages": [{"role": "user", "content": "Hello!"}]9 }'10
11# After (LLM Gateway) - single Authorization header12curl https://api.llmgateway.io/v1/chat/completions \13 -H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \14 -H "Content-Type: application/json" \15 -d '{16 "model": "gpt-5.2",17 "messages": [{"role": "user", "content": "Hello!"}]18 }'19# Use "openai/gpt-5.2" to target a specific provider4. Replace Virtual Keys and Configs
Portkey routes through virtual keys (one per provider credential) and config objects. LLM Gateway replaces both:
- Virtual keys → Provider Keys. Add your provider API keys once in the dashboard under Settings > Provider Keys. Bring your own keys and pay a 0% gateway markup, or use LLM Gateway's default keys.
- Configs → model IDs + routing. Provider selection, fallbacks, and load balancing are handled by the model ID and built-in smart routing — there's no separate config object to maintain.
Streaming Support
Streaming works identically:
1from openai import OpenAI2
3client = OpenAI(4 base_url="https://api.llmgateway.io/v1",5 api_key=os.environ["LLM_GATEWAY_API_KEY"],6)7
8stream = client.chat.completions.create(9 model="openai/gpt-5.2",10 messages=[{"role": "user", "content": "Write a story"}],11 stream=True,12)13
14for chunk in stream:15 if chunk.choices[0].delta.content:16 print(chunk.choices[0].delta.content, end="")1from openai import OpenAI2
3client = OpenAI(4 base_url="https://api.llmgateway.io/v1",5 api_key=os.environ["LLM_GATEWAY_API_KEY"],6)7
8stream = client.chat.completions.create(9 model="openai/gpt-5.2",10 messages=[{"role": "user", "content": "Write a story"}],11 stream=True,12)13
14for chunk in stream:15 if chunk.choices[0].delta.content:16 print(chunk.choices[0].delta.content, end="")Function/Tool Calling
Tool calling carries over unchanged — it's standard OpenAI-format tools:
1tools = [{2 "type": "function",3 "function": {4 "name": "get_weather",5 "description": "Get the weather for a location",6 "parameters": {7 "type": "object",8 "properties": {"location": {"type": "string"}},9 "required": ["location"],10 },11 },12}]13
14response = client.chat.completions.create(15 model="openai/gpt-5.2",16 messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],17 tools=tools,18)1tools = [{2 "type": "function",3 "function": {4 "name": "get_weather",5 "description": "Get the weather for a location",6 "parameters": {7 "type": "object",8 "properties": {"location": {"type": "string"}},9 "required": ["location"],10 },11 },12}]13
14response = client.chat.completions.create(15 model="openai/gpt-5.2",16 messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],17 tools=tools,18)What Changes After Migration
- No more virtual keys or
x-portkey-*headers — standard Bearer auth and provider keys in a dashboard - Automatic routing — providers scored on live uptime, throughput, price, and latency instead of static configs
- Caching is one toggle — no semantic-cache setup required to get repeat-request savings
- Generative media included — image and video models through the same API and billing
- Fully open source — self-host the entire platform, not just the router
Self-Hosting LLM Gateway
Prefer to run it yourself? Unlike Portkey, where only the gateway is open source, the entire LLM Gateway platform is available under AGPLv3:
1git clone https://github.com/theopenco/llmgateway2cd llmgateway3pnpm install4pnpm setup5pnpm dev1git clone https://github.com/theopenco/llmgateway2cd llmgateway3pnpm install4pnpm setup5pnpm devSee the self-hosting guide for production deployment with a single Docker image.
Full Comparison
Want a detailed breakdown of all features? Check out our LLM Gateway vs Portkey comparison page.
Need Help?
- Browse available models at llmgateway.io/models
- Read the API documentation
- Contact support at contact@llmgateway.io