Portkey’s REST API provides direct HTTP access to 250+ LLMs with production-grade routing, fallbacks, and observability. Use it from any programming language or tool that can make HTTP requests.
Overview
The REST API offers:
Universal Access : Use from any language (Python, Go, Ruby, PHP, etc.)
OpenAI-Compatible : Same endpoints and request/response format
250+ LLMs : Access any provider through unified API
Simple Integration : Just HTTP headers and JSON payloads
Production Features : Fallbacks, caching, retries, and guardrails
Base URL
https://api.portkey.ai/v1
For self-hosted gateway:
Authentication
Portkey uses HTTP headers for authentication and configuration:
x-portkey-api-key: your-portkey-api-key
Provider Authentication
Choose one method:
Virtual Key (Recommended)
Provider + Authorization
x-portkey-virtual-key: your-virtual-key
Quick Start
Get Your API Keys
Sign up at Portkey and get your API key. Add provider keys as Virtual Keys.
Make Your First Request
curl https://api.portkey.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-d '{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hello!"}]
}'
Chat Completions
Basic Request
curl https://api.portkey.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-provider: openai" \
-H "Authorization: Bearer YOUR_OPENAI_API_KEY" \
-d '{
"model": "gpt-4",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain quantum computing."}
],
"temperature": 0.7,
"max_tokens": 500
}'
Response
{
"id" : "chatcmpl-123" ,
"object" : "chat.completion" ,
"created" : 1677652288 ,
"model" : "gpt-4" ,
"choices" : [
{
"index" : 0 ,
"message" : {
"role" : "assistant" ,
"content" : "Quantum computing is..."
},
"finish_reason" : "stop"
}
],
"usage" : {
"prompt_tokens" : 20 ,
"completion_tokens" : 100 ,
"total_tokens" : 120
}
}
Streaming
Enable streaming with "stream": true:
curl https://api.portkey.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-d '{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Write a story"}],
"stream": true
}'
Response (Server-Sent Events):
data: {"id":"1","choices":[{"delta":{"content":"Once"}}]}
data: {"id":"1","choices":[{"delta":{"content":" upon"}}]}
data: {"id":"1","choices":[{"delta":{"content":" a"}}]}
data: [DONE]
Switching Providers
Change providers by updating the header:
OpenAI
Anthropic
Google Gemini
Azure OpenAI
curl https://api.portkey.ai/v1/chat/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-provider: openai" \
-H "Authorization: Bearer YOUR_OPENAI_KEY" \
-d '{"model": "gpt-4", "messages": [...]}'
Advanced Routing
Using Configs
Pass a config object via header:
curl https://api.portkey.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-config: '{"strategy":{"mode":"fallback"},"targets":[{"virtual_key":"openai-key"},{"virtual_key":"anthropic-key"}]}' " \
-d '{"model": "gpt-4", "messages": [...]}'
Or use a saved config ID:
curl https://api.portkey.ai/v1/chat/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-config: pc-config-abc123" \
-d '{"model": "gpt-4", "messages": [...]}'
Fallback Example
curl https://api.portkey.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H 'x-portkey-config: {
"strategy": {"mode": "fallback"},
"targets": [
{"virtual_key": "openai-virtual-key"},
{"virtual_key": "anthropic-virtual-key"}
]
}' \
-d '{"model": "gpt-4", "messages": [...]}'
Load Balancing
curl https://api.portkey.ai/v1/chat/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H 'x-portkey-config: {
"strategy": {"mode": "loadbalance"},
"targets": [
{"virtual_key": "openai-key-1", "weight": 0.7},
{"virtual_key": "openai-key-2", "weight": 0.3}
]
}' \
-d '{"model": "gpt-4", "messages": [...]}'
Retries
curl https://api.portkey.ai/v1/chat/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-H 'x-portkey-config: {
"retry": {
"attempts": 5,
"on_status_codes": [429, 500, 502, 503]
}
}' \
-d '{"model": "gpt-4", "messages": [...]}'
Caching
Simple Caching
curl https://api.portkey.ai/v1/chat/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-H "x-portkey-cache: simple" \
-H "x-portkey-cache-force-refresh: false" \
-d '{"model": "gpt-4", "messages": [...]}'
Semantic Caching
curl https://api.portkey.ai/v1/chat/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-H 'x-portkey-config: {
"cache": {
"mode": "semantic",
"max_age": 3600
}
}' \
-d '{"model": "gpt-4", "messages": [...]}'
Add custom metadata:
curl https://api.portkey.ai/v1/chat/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-H 'x-portkey-metadata: {"user_id":"user_123","environment":"production"}' \
-H "x-portkey-trace-id: request-001" \
-d '{"model": "gpt-4", "messages": [...]}'
Other Endpoints
Completions (Legacy)
curl https://api.portkey.ai/v1/completions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-d '{
"model": "gpt-3.5-turbo-instruct",
"prompt": "Once upon a time",
"max_tokens": 100
}'
Embeddings
curl https://api.portkey.ai/v1/embeddings \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-d '{
"model": "text-embedding-3-small",
"input": "The quick brown fox jumps over the lazy dog"
}'
Image Generation
curl https://api.portkey.ai/v1/images/generations \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-d '{
"model": "dall-e-3",
"prompt": "A serene landscape with mountains",
"n": 1,
"size": "1024x1024"
}'
Audio Transcription
curl https://api.portkey.ai/v1/audio/transcriptions \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-F model="whisper-1" \
-F file="@speech.mp3"
Text to Speech
curl https://api.portkey.ai/v1/audio/speech \
-H "x-portkey-api-key: YOUR_PORTKEY_API_KEY" \
-H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY" \
-d '{
"model": "tts-1",
"voice": "alloy",
"input": "Hello, this is a test."
}' \
--output speech.mp3
Language Examples
Python (requests)
import requests
url = "https://api.portkey.ai/v1/chat/completions"
headers = {
"Content-Type" : "application/json" ,
"x-portkey-api-key" : "YOUR_PORTKEY_API_KEY" ,
"x-portkey-virtual-key" : "YOUR_VIRTUAL_KEY"
}
data = {
"model" : "gpt-4" ,
"messages" : [{ "role" : "user" , "content" : "Hello!" }]
}
response = requests.post(url, json = data, headers = headers)
print (response.json())
Node.js (fetch)
const response = await fetch ( 'https://api.portkey.ai/v1/chat/completions' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-portkey-api-key' : 'YOUR_PORTKEY_API_KEY' ,
'x-portkey-virtual-key' : 'YOUR_VIRTUAL_KEY'
},
body: JSON . stringify ({
model: 'gpt-4' ,
messages: [{ role: 'user' , content: 'Hello!' }]
})
});
const data = await response . json ();
console . log ( data );
package main
import (
" bytes "
" encoding/json "
" fmt "
" net/http "
)
func main () {
url := "https://api.portkey.ai/v1/chat/completions"
payload := map [ string ] interface {}{
"model" : "gpt-4" ,
"messages" : [] map [ string ] string {
{ "role" : "user" , "content" : "Hello!" },
},
}
jsonData , _ := json . Marshal ( payload )
req , _ := http . NewRequest ( "POST" , url , bytes . NewBuffer ( jsonData ))
req . Header . Set ( "Content-Type" , "application/json" )
req . Header . Set ( "x-portkey-api-key" , "YOUR_PORTKEY_API_KEY" )
req . Header . Set ( "x-portkey-virtual-key" , "YOUR_VIRTUAL_KEY" )
client := & http . Client {}
resp , _ := client . Do ( req )
defer resp . Body . Close ()
var result map [ string ] interface {}
json . NewDecoder ( resp . Body ). Decode ( & result )
fmt . Println ( result )
}
Ruby
require 'net/http'
require 'json'
uri = URI ( 'https://api.portkey.ai/v1/chat/completions' )
request = Net :: HTTP :: Post . new (uri)
request[ 'Content-Type' ] = 'application/json'
request[ 'x-portkey-api-key' ] = 'YOUR_PORTKEY_API_KEY'
request[ 'x-portkey-virtual-key' ] = 'YOUR_VIRTUAL_KEY'
request. body = {
model: 'gpt-4' ,
messages: [{ role: 'user' , content: 'Hello!' }]
}. to_json
response = Net :: HTTP . start (uri. hostname , uri. port , use_ssl: true ) do | http |
http. request (request)
end
puts JSON . parse (response. body )
PHP
<? php
$url = 'https://api.portkey.ai/v1/chat/completions' ;
$headers = [
'Content-Type: application/json' ,
'x-portkey-api-key: YOUR_PORTKEY_API_KEY' ,
'x-portkey-virtual-key: YOUR_VIRTUAL_KEY'
];
$data = [
'model' => 'gpt-4' ,
'messages' => [[ 'role' => 'user' , 'content' => 'Hello!' ]]
];
$ch = curl_init ( $url );
curl_setopt ( $ch , CURLOPT_POST , 1 );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , $headers );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$response = curl_exec ( $ch );
curl_close ( $ch );
echo $response ;
?>
Error Responses
Portkey returns standard HTTP status codes:
{
"error" : {
"message" : "Invalid API key" ,
"type" : "invalid_request_error" ,
"code" : "invalid_api_key"
}
}
Common status codes:
400 - Bad request
401 - Unauthorized (invalid API key)
429 - Rate limit exceeded
500 - Server error
502 - Bad gateway
503 - Service unavailable
Header Required Description x-portkey-api-keyYes Your Portkey API key x-portkey-virtual-keyNo* Virtual key for provider x-portkey-providerNo* Provider name (openai, anthropic, etc) AuthorizationNo* Provider API key (with provider header) x-portkey-configNo Config object or ID x-portkey-metadataNo Custom metadata JSON x-portkey-trace-idNo Custom trace ID x-portkey-cacheNo Cache mode (simple/semantic)
*Either virtual-key OR (provider + Authorization) required
Best Practices
Always use virtual keys instead of raw provider keys for better security: -H "x-portkey-virtual-key: YOUR_VIRTUAL_KEY"
Use caching to reduce costs and improve latency: { "cache" : { "mode" : "semantic" , "max_age" : 3600 }}
Implement proper error handling for all status codes.
Complete Production Example
curl https://api.portkey.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-portkey-api-key: $PORTKEY_API_KEY " \
-H 'x-portkey-config: {
"strategy": {"mode": "fallback"},
"targets": [
{"virtual_key": "openai-key"},
{"virtual_key": "anthropic-key"}
],
"retry": {"attempts": 3},
"cache": {"mode": "semantic", "max_age": 3600}
}' \
-H 'x-portkey-metadata: {
"user_id": "user_123",
"environment": "production",
"service": "chat-api"
}' \
-H "x-portkey-trace-id: req-$( date +%s)" \
-d '{
"model": "gpt-4",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "How can I help you today?"}
],
"temperature": 0.7,
"max_tokens": 500
}'
Resources
The REST API is perfect for integrating Portkey into any application, regardless of programming language.