Checked 2026-10-26

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.

bash
1# OpenAI SDK (Python and TypeScript read these)
2export OPENAI_BASE_URL="https://api.relayswitch.io/v1"
3export OPENAI_API_KEY="YOUR_RELAYSWITCH_KEY"
4
5# Anthropic SDK (Python and TypeScript read these)
6export ANTHROPIC_BASE_URL="https://api.relayswitch.io/v1"
7export 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:

ts
1import OpenAI from 'openai';
2
3const client = new OpenAI({
4 baseURL: 'https://api.relayswitch.io/v1',
5 apiKey: process.env.RELAYSWITCH_KEY,
6});
7const completion = await client.chat.completions.create({
8 model: 'gpt-5.5',
9 messages: [{ role: 'user', content: 'Say ok.' }],
10});
11console.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:

ts
1import Anthropic from '@anthropic-ai/sdk';
2
3const client = new Anthropic({
4 baseURL: 'https://api.relayswitch.io/v1',
5 apiKey: process.env.RELAYSWITCH_KEY,
6});
7const message = await client.messages.create({
8 model: 'claude-sonnet-5-5',
9 max_tokens: 256,
10 messages: [{ role: 'user', content: 'Say ok.' }],
11});
12const first = message.content[0];
13console.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:

python
1from openai import OpenAI
2
3client = OpenAI() # reads OPENAI_BASE_URL and OPENAI_API_KEY
4with client.chat.completions.stream(
5 model="gpt-5.5",
6 messages=[{"role": "user", "content": "Count to five."}],
7) as s:
8 for event in s:
9 if event.type == "content.delta":
10 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.

ts
1import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
2import { generateText } from 'ai';
3
4const relayswitch = createOpenAICompatible({
5 name: 'relayswitch',
6 apiKey: process.env.RELAYSWITCH_KEY,
7 baseURL: 'https://api.relayswitch.io/v1',
8});
9const { text } = await generateText({
10 model: relayswitch('claude-sonnet-5-5'),
11 prompt: 'Explain what an API gateway does in one sentence.',
12});

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-5
  • claude-fable-5.1
  • claude-haiku-4-5
  • claude-haiku-4-5-20251001
  • claude-haiku-5-5
  • claude-opus-4-6
  • claude-opus-4-7
  • claude-opus-5
  • claude-opus-5-5
  • claude-sonnet-5
  • claude-sonnet-5-5

06Check it

bash
1curl https://api.relayswitch.io/v1/models -H "Authorization: Bearer YOUR_RELAYSWITCH_KEY"
bash
1curl -i https://api.relayswitch.io/v1/chat/completions \
2 -H "Authorization: Bearer YOUR_RELAYSWITCH_KEY" \
3 -H "content-type: application/json" \
4 -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:

bash
1curl https://api.relayswitch.io/v1/requests/REQUEST_ID/receipt \
2 -H "Authorization: Bearer YOUR_RELAYSWITCH_KEY"

The verify page checks a receipt's signature in the browser.

07What a turn costs

ModelIn / MOut / M2K in + 500 outUnder list
Claude Sonnet 5.5$1.20$3.00$0.003970%
Claude Opus 5.5$2.80$10.00$0.010650%
Claude Haiku 5.5$0.06$0.15$0.000270%
GPT-5.5$1.80$9.00$0.008170%
GPT-6.1 Sol$0.60$3.00$0.002770%
Gemini 4 Argon$0.60$3.00$0.002770%
DeepSeek V4 Pro 0423$0.792$2.376$0.002840%
Kimi K3$0.90$4.50$0.004170%

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.

Two values and your code runs here

Prepaid from $10. Card or crypto, no KYC.