SDK setup: OpenAI, Anthropic, Vercel AI SDK
Your existing OpenAI SDK or Anthropic SDK code runs unchanged with its base URL set to https://api.relayswitch.io/v1 and one key in place of several.
The OpenAI SDK reads OPENAI_BASE_URL, the Anthropic SDK reads ANTHROPIC_BASE_URL, and the Vercel AI SDK takes the base URL in a provider option. Every model on the Models page is callable from the same key, and each request's charge lands on your prepaid balance with a signed receipt. The same two values are what the Claude Code and Cursor guides set.
01Environment variables
Both SDKs read these, so no code changes.
# OpenAI SDK (Python and TypeScript read these)export OPENAI_BASE_URL="https://api.relayswitch.io/v1"export OPENAI_API_KEY="YOUR_RELAYSWITCH_KEY" # Anthropic SDK (Python and TypeScript read these)export ANTHROPIC_BASE_URL="https://api.relayswitch.io/v1"export ANTHROPIC_API_KEY="YOUR_RELAYSWITCH_KEY"The Python and TypeScript clients of each SDK read the same two names, so a service that already runs on OPENAI_API_KEY switches with one line in its environment. The key page in the console shows the full key once at creation.
02TypeScript
The constructor takes the same two values when you would rather not use environment variables. openai on npm, any version that has chat.completions.create:
import OpenAI from 'openai'; const client = new OpenAI({ baseURL: 'https://api.relayswitch.io/v1', apiKey: process.env.RELAYSWITCH_KEY,});const completion = await client.chat.completions.create({ model: 'gpt-5.5', messages: [{ role: 'user', content: 'Say ok.' }],});console.log(completion.choices[0].message.content);The Anthropic SDK, @anthropic-ai/sdk on npm, sends to /v1/messages and needs max_tokens on every call:
import Anthropic from '@anthropic-ai/sdk'; const client = new Anthropic({ baseURL: 'https://api.relayswitch.io/v1', apiKey: process.env.RELAYSWITCH_KEY,});const message = await client.messages.create({ model: 'claude-sonnet-5-5', max_tokens: 256, messages: [{ role: 'user', content: 'Say ok.' }],});const first = message.content[0];console.log(first.type === 'text' ? first.text : first.type);The Messages format answers only Claude ids; see the formats section.
03Python, streaming
With the shell block above in place, OpenAI() with no arguments reads the base URL and the key:
from openai import OpenAI client = OpenAI() # reads OPENAI_BASE_URL and OPENAI_API_KEYwith client.chat.completions.stream( model="gpt-5.5", messages=[{"role": "user", "content": "Count to five."}],) as s: for event in s: if event.type == "content.delta": print(event.delta, end="")04Vercel AI SDK
@ai-sdk/openai-compatible with the base URL set by hand. Any model id from the Models page works, with generateText and streamText alike, Claude ids included.
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';import { generateText } from 'ai'; const relayswitch = createOpenAICompatible({ name: 'relayswitch', apiKey: process.env.RELAYSWITCH_KEY, baseURL: 'https://api.relayswitch.io/v1',});const { text } = await generateText({ model: relayswitch('claude-sonnet-5-5'), prompt: 'Explain what an API gateway does in one sentence.',});05Formats
Every chat model answers the OpenAI chat completions format at /v1/chat/completions. The Claude ids also answer the Anthropic Messages format at /v1/messages. Those ids today:
claude-fable-5claude-fable-5.1claude-haiku-4-5claude-haiku-4-5-20251001claude-haiku-5-5claude-opus-4-6claude-opus-4-7claude-opus-5claude-opus-5-5claude-sonnet-5claude-sonnet-5-5
06Check it
curl https://api.relayswitch.io/v1/models -H "Authorization: Bearer YOUR_RELAYSWITCH_KEY"curl -i https://api.relayswitch.io/v1/chat/completions \ -H "Authorization: Bearer YOUR_RELAYSWITCH_KEY" \ -H "content-type: application/json" \ -d '{"model": "claude-haiku-5-5", "messages": [{"role": "user", "content": "Say ok."}]}'The answer carries a request id header. Look the request up by it to read tokens and charge, or fetch its signed receipt:
curl https://api.relayswitch.io/v1/requests/REQUEST_ID/receipt \ -H "Authorization: Bearer YOUR_RELAYSWITCH_KEY"The verify page checks a receipt's signature in the browser.
07What a turn costs
| Model | In / M | Out / M | 2K in + 500 out | Under list |
|---|---|---|---|---|
| Claude Sonnet 5.5 | $1.20 | $3.00 | $0.0039 | 70% |
| Claude Opus 5.5 | $2.80 | $10.00 | $0.0106 | 50% |
| Claude Haiku 5.5 | $0.06 | $0.15 | $0.0002 | 70% |
| GPT-5.5 | $1.80 | $9.00 | $0.0081 | 70% |
| GPT-6.1 Sol | $0.60 | $3.00 | $0.0027 | 70% |
| Gemini 4 Argon | $0.60 | $3.00 | $0.0027 | 70% |
| DeepSeek V4 Pro 0423 | $0.792 | $2.376 | $0.0028 | 40% |
| Kimi K3 | $0.90 | $4.50 | $0.0041 | 70% |
Live from the catalog. Cached input, where the model supports it, bills lower than the input rate.
Questions
- How do I find my API key?
- Create it in the console under Keys. The full key is shown once at creation, so copy it then; afterwards the console shows only the prefix and the spend on it. Send it as Authorization: Bearer or as an x-api-key header; the SDKs do that for you once the environment variable is set.
- Is the Claude API key free here?
- No. Every request bills per token from prepaid credit, and the table on this page is the rate per million tokens; a 2,000-in, 500-out turn on Claude Sonnet 5.5 is $0.0039. What needs no key: GET /v1/catalog for prices and POST /v1/estimate for a cost before you send.
- Do I need a subscription to use the OpenAI SDK here?
- No. Credit is prepaid, there is no monthly fee, and a key can carry a monthly spend limit you set, so a loop that runs away stops at 402 monthly_limit_reached rather than at your card limit.
- Can I use the Anthropic SDK with a non-Claude model?
- No. A non-Claude id sent to /v1/messages returns a 400 saying the model is served in the openai format. Point the OpenAI SDK at the same base URL for GPT, Gemini, DeepSeek, Kimi and the rest; the Claude ids answer both formats, so one OpenAI client can cover the whole list. Today 11 ids answer the Anthropic format.
- Does the Vercel AI SDK work with Claude here?
- @ai-sdk/openai-compatible speaks the OpenAI chat completions format, and every Claude id answers it, so relayswitch("claude-sonnet-5-5") works with generateText, streamText and tool calls the same as a GPT id.
- Do I need to change my code to switch?
- No. Two values change: the base URL becomes https://api.relayswitch.io/v1 and the key becomes your RelaySwitch key. Model ids are the developer ids, and requests and responses keep each SDK's own shape, including streaming and tool calls.