Checked 2026-10-28

Vercel AI SDK on one API key

One RelaySwitch key in the AI SDK's OpenAI-compatible provider reaches every chat model on the Models page, billed per token from a prepaid balance you top up by card or crypto.

A Vercel AI SDK API key setup here is one provider block: createOpenAICompatible with the base URL https://api.relayswitch.io/v1 and a RelaySwitch key. After that, generateText, streamText and tool calls take any model id from the Models page, Claude ids included, with no second provider package and no second key.

There is no subscription. You pay as you go: each request bills its tokens at the live catalog price against a balance you prepaid by card (Card) or crypto (USDT, USDC, BTC, ETH, SOL). This guide writes the provider, shows the three calls, prices a chat turn on each model and lists the errors you can hit.

01What you need

  • A Node.js or Next.js project on the AI SDK (ai on npm).
  • A RelaySwitch key. Sign in with an email code at the console and create one under Keys. Keys start with sk-relay-; the full key shows once at creation, so copy it then.
  • A balance. Top-ups start at $10, by card or crypto, with no subscription and no KYC. Before the first top-up the console chat gives you 12 free turns a day to try models; SDK requests bill the balance.

02Vercel AI SDK API key and provider setup

  1. Install the SDK core and the OpenAI-compatible provider package.
    bash
    1pnpm add ai @ai-sdk/openai-compatible
  2. Put the key in the environment, never in source. One key per app keeps the console Usage page readable.
    bash
    1# .env.local (Next.js reads it; other runtimes use dotenv or the shell)
    2RELAYSWITCH_KEY=sk-relay-...
  3. Build the provider once in a shared module and import it wherever you call a model.
    ts
    1// lib/relayswitch.ts
    2// Options per the AI SDK OpenAI-compatible providers docs, read 2026-10-28:
    3// https://ai-sdk.dev/providers/openai-compatible-providers
    4import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
    5
    6export const relayswitch = createOpenAICompatible({
    7 name: 'relayswitch',
    8 baseURL: 'https://api.relayswitch.io/v1',
    9 apiKey: process.env.RELAYSWITCH_KEY,
    10 // Adds token counts to streamed answers (stream_options.include_usage).
    11 includeUsage: true,
    12});

name labels the provider inside the SDK; it is also the key under providerOptions if you ever pass provider-specific options. baseURL keeps the /v1; the SDK appends /chat/completions. apiKey goes out as a Bearer token. Option names follow the OpenAI-compatible providers docs (read 2026-10-28).

03generateText, streamText and tools

relayswitch(id) returns a chat model, the same as relayswitch.chatModel(id). The id is the one the Models page shows, with no vendor prefix.

ts
1import { generateText } from 'ai';
2import { relayswitch } from '@/lib/relayswitch';
3
4const { text, usage } = await generateText({
5 model: relayswitch('claude-sonnet-5-5'),
6 prompt: 'Explain what an API gateway does in one sentence.',
7});
8console.log(text, usage);

Streaming uses the same model object. With includeUsage on, the final chunk carries the token counts, so the result.usage promise resolves after the stream ends (streamText reference, read 2026-10-28).

ts
1import { streamText } from 'ai';
2import { relayswitch } from '@/lib/relayswitch';
3
4const result = streamText({
5 model: relayswitch('claude-sonnet-5-5'),
6 system: 'Answer in plain English.',
7 messages: [{ role: 'user', content: 'Count to five.' }],
8});
9for await (const part of result.textStream) {
10 process.stdout.write(part);
11}
12console.log(await result.usage); // present because includeUsage is on

Tool calling works the SDK way: each entry in tools is a tool() with a description, an inputSchema and an execute function, and stopWhen: stepCountIs(n) bounds a multi-step run (tool calling docs, read 2026-10-28). Every chat model answers the OpenAI chat completions format, and the Claude ids answer it as well as the Anthropic one, so the same provider covers Claude, GPT, Gemini, DeepSeek and GLM.

If @ai-sdk/openai is already in the project, it works here with the base URL set. Pick the Chat Completions factory:

ts
1// If @ai-sdk/openai is already in the project. Its default factory uses the
2// Responses API; openai.chat() selects Chat Completions (docs read 2026-10-28:
3// https://ai-sdk.dev/providers/ai-sdk-providers/openai).
4import { createOpenAI } from '@ai-sdk/openai';
5
6const openai = createOpenAI({
7 baseURL: 'https://api.relayswitch.io/v1',
8 apiKey: process.env.RELAYSWITCH_KEY,
9});
10const model = openai.chat('claude-sonnet-5-5');

04Which model to pick

A chat app resends the whole conversation every turn, so the input rate is most of the bill once a thread is long. The output rate matters for long answers and code generation. Of the models here, Claude Haiku 5.5 has the lowest input rate today at $0.0582 per million tokens.

ModelInputCachedOutputDeveloper list in / outContext
Claude Sonnet 5.5$1.20 (40% under)$0.075$3.00 (70% under)$2.00 / $10.001M tokens
Claude Opus 5.5$2.716 (32% under)$0.1455$9.70 (51% under)$4.00 / $20.001M tokens
Claude Haiku 5.5$0.0582 (41% under)$0.01$0.1455 (70% under)$0.10 / $0.501M tokens
GPT-5.5$1.80 (64% under)$0.16$9.00 (70% under)$5.00 / $30.001.1M tokens
GPT-6.1 Sol$0.582 (70% under)$0.0582$2.91 (70% under)$2.00 / $10.001.1M tokens
Gemini 4 Argon$0.60 (70% under)$0.06$3.00 (70% under)$2.00 / $10.001M tokens
DeepSeek V4 Pro 0423$0.792 (40% under)$0.0264$2.376 (40% under)$1.32 / $3.961M tokens
GLM 5.3$0.3178 (70% under)$0.066$0.9987 (70% under)$1.092 / $3.4321M tokens

USD per million tokens, read from the RelaySwitch catalog when this page was built. Developer list: the catalog's record of the developer's own price.

Swapping models is one string: change the id in relayswitch(id). The full list, with every price and context size, is on the Models page. How the balance and the cached rate work is on Pricing.

05What a chat turn costs

The turn: 2,000 input tokens (a system prompt plus a short history) and 500 output tokens back. Those sizes are an assumption; the usage object on each result and the console Usage page show the real ones.

ModelInput / MOutput / MOne turn
Claude Haiku 5.5$0.0582$0.1455$0.00019
GLM 5.3$0.3178$0.9987$0.0011
GPT-6.1 Sol$0.582$2.91$0.0026
Gemini 4 Argon$0.60$3.00$0.0027
DeepSeek V4 Pro 0423$0.792$2.376$0.0028
Claude Sonnet 5.5$1.20$3.00$0.0039
GPT-5.5$1.80$9.00$0.0081
Claude Opus 5.5$2.716$9.70$0.0103

2,000 in and 500 out at the live per-token prices when this page was built. Cached input, where the model has a cached rate, bills lower.

The same turn runs $0.00019 on Claude Haiku 5.5 and $0.0103 on Claude Opus 5.5. A cheap model for routine turns and a dear one for the hard question is a reasonable split; the provider block does not change.

06Check the key before the SDK

Two curl calls rule out the key and the base URL before you debug the SDK. The first lists every model id your key can call:

bash
1curl https://api.relayswitch.io/v1/models -H "Authorization: Bearer sk-relay-..."

The second sends one small request the way the SDK does. -i prints the headers, including the request id and, on a non-streamed answer, the charge in USD.

bash
1curl -i https://api.relayswitch.io/v1/chat/completions \
2 -H "Authorization: Bearer sk-relay-..." \
3 -H "Content-Type: application/json" \
4 -d '{"model": "claude-sonnet-5-5", "messages": [{"role": "user", "content": "Say ok."}]}'

If both work, any failure left is in the provider block. Each SDK call then shows on the console's Usage page within seconds, with its tokens and its charge.

07Errors and fixes

  • 401: the key is wrong, revoked or unset. process.env.RELAYSWITCH_KEY is undefined when .env.local is missing or the variable name differs. Paste the key again from the console and run the curl check.
  • 402: the balance is too low for the request. Top up in the console; the key works again at once.
  • 404 on the model: the id is not in the catalog. Check for a typo or a display name in place of the id.
  • 404 on the route: the base URL is missing /v1 or carries a trailing path. Use https://api.relayswitch.io/v1 exactly.
  • 429: the key hit its rate limit. Back off and retry, or create a key with a higher Requests / min in the console.
  • result.usage is empty on a stream: includeUsage is off. Set it to true in the provider block.
  • 400 from @ai-sdk/anthropic on a non-Claude id: that package sends the Anthropic format to /v1/messages, which only the Claude ids answer. The OpenAI-compatible provider covers Claude and the rest with no second package.

Questions

Which base URL does the Vercel AI SDK need?
https://api.relayswitch.io/v1, with the /v1 at the end. The OpenAI-compatible provider appends /chat/completions to it.
Does the Vercel AI SDK work with Claude on one key?
Yes. The Claude ids on RelaySwitch answer the OpenAI chat completions format, so relayswitch('claude-sonnet-5-5') works with generateText, streamText and tool calls, with no @ai-sdk/anthropic package and no second key.
Is there a free Vercel AI SDK API key?
Keys are free to create, and the console chat runs 12 free turns a day before your first top-up. SDK requests bill a prepaid balance, from $10, by card or crypto.
Do I need a subscription?
No. You pay as you go: each request bills its tokens at the live catalog price against credit you prepaid with Card or USDT, USDC, BTC, ETH, SOL. There is no monthly fee and no KYC.
How do I see what each request cost?
Every result carries a usage object with the token counts, and the console Usage page lists each request with its tokens and its charge in USD. On a non-streamed curl call the charge is in the response headers.
Can I use @ai-sdk/openai instead of @ai-sdk/openai-compatible?
Yes. createOpenAI with baseURL set to https://api.relayswitch.io/v1 and your RelaySwitch key works; use openai.chat(id) for the Chat Completions API. The OpenAI-compatible provider is the shorter path for a mixed model list.

Every chat model in the AI SDK

One key, prepaid from $10 by card or crypto. No KYC, no subscription.

Join on Telegram