---
title: "Vercel AI SDK setup with one API key"
canonical: https://uplinkswitch.ai/guides/vercel-ai-sdk
generated: 2026-11-04T07:24:51.214Z
source: https://uplinkswitch.ai/guides/vercel-ai-sdk
base_url: https://api.uplinkswitch.com/v1
---

[›uplinkswitch](https://uplinkswitch.ai/)

[api.uplinkswitch.com/v1](https://uplinkswitch.ai/models)[Console](https://uplinkswitch.ai/console)

[›uplinkswitch](https://uplinkswitch.ai/)

# 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.

Checked 2026-10-28

·[All guides](https://uplinkswitch.ai/guides)·[Models](https://uplinkswitch.ai/models)

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](https://uplinkswitch.ai/models) 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](https://uplinkswitch.ai/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`:

.env.local

```
UPLINKSWITCH_API_KEY=sk-uplink-live-...
```

Then install the two packages:

shell

```
pnpm add ai @ai-sdk/openai-compatible
```

## The provider

`createOpenAICompatible` takes the base URL, the key and optional headers ([AI SDK docs](https://ai-sdk.dev/providers/openai-compatible-providers), 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

```
// 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.

generate.ts

```
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);
```

stream.ts

```
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.

lib/uplinkswitch.ts (typed ids)

```
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](https://uplinkswitch.ai/models), 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](https://uplinkswitch.ai/models/claude-sonnet-5-5) | `claude-sonnet-5-5` | $1.20 | $3.00 | $2.00 / $10.00 | $0.0063 |
| [Claude Opus 5.5](https://uplinkswitch.ai/models/claude-opus-5-5) | `claude-opus-5-5` | $2.80 | $10.00 | $4.00 / $20.00 | $0.0162 |
| [GPT-6.1 Sol](https://uplinkswitch.ai/models/gpt-6.1-sol) | `gpt-6.1-sol` | $0.60 | $3.00 | $2.00 / $10.00 | $0.0039 |
| [Gemini 3.1 Pro Preview](https://uplinkswitch.ai/models/gemini-3.1-pro-preview) | `gemini-3.1-pro-preview` | $1.20 | $7.20 | $2.00 / $12.00 | $0.0084 |
| [DeepSeek V4 Pro 0813](https://uplinkswitch.ai/models/deepseek-v4-pro-0813) | `deepseek-v4-pro-0813` | $0.792 | $1.188 | $1.32 / $3.96 | $0.0038 |
| [Kimi K3](https://uplinkswitch.ai/models/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:

shell

```
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](https://uplinkswitch.ai/console) Usage page within seconds, with its tokens and its charge.

## Errors you will see

-   `401 invalid_api_key`: the key is wrong, revoked, or `UPLINKSWITCH_API_KEY` is 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`: `baseURL` lost its `/v1`. Enter it exactly as shown above.
-   `429 rate_limited`: the key hit its requests-per-minute or concurrency limit. The response carries `retry-after` in seconds. Wait that long and resend.

## Good to know

-   `@ai-sdk/openai-compatible` calls `/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](https://uplinkswitch.ai/guides/opencode), which uses this same package under its provider block, and in [LangChain](https://uplinkswitch.ai/guides/langchain). The [SDKs guide](https://uplinkswitch.ai/guides/sdks) has the OpenAI, Anthropic and Gemini clients. One balance serves all of them.

## Questions

### 

Yes. The @ai-sdk/openai-compatible package takes a baseURL and an apiKey, and the provider it returns plugs into generateText, streamText, embed and every other AI SDK call. Set baseURL to https://api.uplinkswitch.com/v1 and every chat model on the Models page answers through it.

### 

Yes. Pass claude-sonnet-5-5 or claude-opus-5-5 as the model id. The Claude ids answer the OpenAI chat completions format here, tool calls and streaming included, so @ai-sdk/anthropic is not needed.

### 

https://api.uplinkswitch.com/v1, ending at /v1. The package adds /chat/completions itself. Without /v1 the API answers 404 with "No such route."

### 

The gateway records X-Title as the client app against each request in its log. The headers are optional and change nothing about the response.

### 

Each result carries usage with input and output token counts; multiply by the per-million prices in the table above. The console Usage page lists every request within seconds with its charge in dollars, filterable by key and model.

### 

No. Credit is prepaid from $10 and each request bills per token to the key that made it. The price on each model page is locked for 30 days from each top-up.

Get a key in the [console](https://uplinkswitch.ai/console): prepaid credit, no subscription, 30-day price lock.

## Related

-   [SDK setup](https://uplinkswitch.ai/guides/sdks)
-   [LangChain setup](https://uplinkswitch.ai/guides/langchain)
-   [Strands Agents setup](https://uplinkswitch.ai/guides/strands-agents)
-   [LiteLLM setup](https://uplinkswitch.ai/guides/litellm)
-   [Claude Sonnet 5.5](https://uplinkswitch.ai/models/claude-sonnet-5-5)
-   [GPT-6.1 Sol](https://uplinkswitch.ai/models/gpt-6.1-sol)
-   [DeepSeek V4 Pro](https://uplinkswitch.ai/models/deepseek-v4-pro-0813)
-   [Model catalog](https://uplinkswitch.ai/models)
-   [LLM API price index](https://uplinkswitch.ai/pricing-index)
