Vercel AI SDK
One key, every model, pay as you go, no subscription: createOpenAICompatible with our base URL, then generateText or streamText on any id.
At the end you have one createOpenAICompatible provider at https://api.uplinkswitch.com/v1 with one API key from the console, and any model id on the list in generateText or streamText, Claude included. Each request bills per token to the prepaid balance behind that key, and the live table below is what a chat turn costs on each model today.
What you need
An account on the console with credit on it, and one key created there. Create the key for this app alone, so its requests sit apart from any other tool on the Usage page. Put the key in .env.local:
UPLINKSWITCH_API_KEY=sk-uplink-live-...Then install the two packages:
pnpm add ai @ai-sdk/openai-compatibleThe provider
createOpenAICompatible takes the base URL, the key and optional headers (AI SDK docs, read 2026-10-28). apiKey becomes the Authorization: Bearer header. The two custom headers name the app in our request log. includeUsage adds token counts to streamed responses.
// lib/uplinkswitch.ts
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
export const uplinkswitch = createOpenAICompatible({
name: 'uplinkswitch',
baseURL: 'https://api.uplinkswitch.com/v1',
apiKey: process.env.UPLINKSWITCH_API_KEY,
headers: {
'HTTP-Referer': 'https://uplinkswitch.ai',
'X-Title': 'Vercel AI SDK',
},
includeUsage: true,
});Call the provider with a model id to get a chat model. uplinkswitch('id'), uplinkswitch.chatModel('id') and uplinkswitch.languageModel('id') are the same thing.
import { generateText } from 'ai';
import { uplinkswitch } from './lib/uplinkswitch';
const { text, usage } = await generateText({
model: uplinkswitch('claude-sonnet-5-5'),
prompt: 'Explain what an API gateway does in one sentence.',
});
console.log(text, usage);import { streamText } from 'ai';
import { uplinkswitch } from './lib/uplinkswitch';
const { textStream } = streamText({
model: uplinkswitch('gpt-6.1-sol'),
prompt: 'Count from 1 to 5.',
});
for await (const textPart of textStream) {
process.stdout.write(textPart);
}For editor completion on the ids, pass them as the first type parameter; the (string & {}) branch keeps any other id from the Models page valid.
type UplinkSwitchChatIds =
| 'claude-sonnet-5-5'
| 'claude-opus-5-5'
| 'gpt-6.1-sol'
| 'gemini-3.1-pro-preview'
| 'deepseek-v4-pro-0813'
| 'kimi-k3'
| (string & {});
export const uplinkswitch = createOpenAICompatible<
UplinkSwitchChatIds,
string,
string,
string
>({
name: 'uplinkswitch',
baseURL: 'https://api.uplinkswitch.com/v1',
apiKey: process.env.UPLINKSWITCH_API_KEY,
});Which model id to use
Any chat id on the Models page, with no vendor prefix. Tool calling, streaming and system prompts work on every chat model here, so an id in the table below is a safe pick for a chat route or an agent loop.
The Claude ids answer the OpenAI format as well as the Anthropic one, so claude-sonnet-5-5 goes in the same call as gpt-6.1-sol or deepseek-v4-pro-0813, with no second provider. Input price decides the cost of a long conversation, because the history goes back up on every turn; pick by the input column.
What a chat turn costs
One turn at 4,000 input tokens (system prompt, history and tool results) and 500 output tokens. Nothing is counted at the cached rate.
| Model | Model id | Input / 1M | Output / 1M | Developer list, in / out | One turn, 4,000 in + 500 out |
|---|---|---|---|---|---|
| Claude Sonnet 5.5 | claude-sonnet-5-5 | $1.20 | $3.00 | $2.00 / $10.00 | $0.0063 |
| Claude Opus 5.5 | claude-opus-5-5 | $2.80 | $10.00 | $4.00 / $20.00 | $0.0162 |
| GPT-6.1 Sol | gpt-6.1-sol | $0.60 | $3.00 | $2.00 / $10.00 | $0.0039 |
| Gemini 3.1 Pro Preview | gemini-3.1-pro-preview | $1.20 | $7.20 | $2.00 / $12.00 | $0.0084 |
| DeepSeek V4 Pro 0813 | deepseek-v4-pro-0813 | $0.792 | $1.188 | $1.32 / $3.96 | $0.0038 |
| Kimi K3 | kimi-k3 | $0.90 | $4.50 | $3.00 / $15.00 | $0.0059 |
USD per million tokens, live from GET /v1/catalog. List: the developer’s own published price. The last column is the turn above at this base URL.
That turn on Claude Sonnet 5.5 is $0.0063 here, against $0.013 at the developer's list price. A thousand of them a day is $6.30. Cached input bills at the cache-read price on the model page by itself; there is no switch to set.
Check it
Confirm the key before you run the app:
curl https://api.uplinkswitch.com/v1/models -H "Authorization: Bearer $UPLINKSWITCH_API_KEY"A list of model ids means the key works. Then run generate.ts. The request shows on the console Usage page within seconds, with its tokens and its charge.
Errors you will see
401 invalid_api_key: the key is wrong, revoked, orUPLINKSWITCH_API_KEYis unset where the provider is built. Copy it again from the console and check the variable is loaded on the server side, not only in the browser bundle.402 insufficient_balance: the prepaid balance does not cover the request. Top up in the console; requests work again at once.404 model_not_found: the id is not on the Models page at this base URL. Copy it from there rather than typing it: a dot, a dash or a date suffix out of place is enough.404 No such route:baseURLlost its/v1. Enter it exactly as shown above.429 rate_limited: the key hit its requests-per-minute or concurrency limit. The response carriesretry-afterin seconds. Wait that long and resend.
Good to know
@ai-sdk/openai-compatiblecalls/v1/chat/completions, which every chat model here answers, Claude included.- Build the provider once in a module and import it, so the headers and key are set in one place.
- The same base URL and key work in OpenCode, which uses this same package under its provider block, and in LangChain. The SDKs guide has the OpenAI, Anthropic and Gemini clients. One balance serves all of them.
Questions
Get a key in the console: prepaid credit, no subscription, 30-day price lock.