# Vercel AI SDK

> Use Inferit from the Vercel AI SDK as an OpenAI-compatible provider: an API key, the base URL, model auto or a named model, and pay per request with x402 through a custom fetch. Testnet: test ITC, no monetary value.

The AI SDK's OpenAI-compatible provider takes a base URL, a key and, optionally, a fetch of your own. With Inferit's base URL, generateText, streamText and the rest work as with any provider.

## 1. Get an API key

Create a key in the [Buy workspace](https://inferit.app/buy) ([Quickstart](https://inferit.cc/docs/quickstart.md), steps 1 to 6) and export it. The key spends your prepaid balance: test ITC on the testnet, a test token with no monetary value.

```bash
export INFERIT_API_KEY='ik_...'
```

The base URL is `https://api-production-c74b9.up.railway.app/v1`. Any OpenAI-compatible client works with it (chat completions, streaming included).

## 2. Add Inferit as a provider

`createOpenAICompatible` from `@ai-sdk/openai-compatible`, with Inferit's base URL and your key. `response.modelId` is the model that answered.

_chat.mjs_

```javascript
// npm i ai @ai-sdk/openai-compatible
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
import { generateText } from 'ai';

const inferit = createOpenAICompatible({
  name: 'inferit',
  baseURL: 'https://api-production-c74b9.up.railway.app/v1',
  apiKey: process.env.INFERIT_API_KEY,
});

const { text, response } = await generateText({
  model: inferit('qwen/qwen-2.5-14b-instruct'), // "auto": Inferit picks the model
  prompt: 'Say hello in five words.',
});
console.log(text);
console.log(response.modelId); // the model that answered
```

## Model auto, or a named model

With `"auto"` as the model, Inferit picks the model: the best value on a published quality ranking for this request, at that model's cheapest healthy seller ([Automatic routing](https://inferit.cc/docs/routing.md)). The response names the model that answered, in its `model` field and the `x-inferit-model` header.

Auto needs a ranked model with a live seller. `GET /v1/routing` lists the models it can choose from now in `candidates_now`; while that list is empty, a request with auto answers `503 no_eligible_model`. Then name a catalog model with a live seller instead, such as `qwen/qwen-2.5-14b-instruct`, and Inferit picks the seller. The samples on this page send auto while it has a candidate, and that model otherwise.

## Pay per request with x402

With no API key, the provider can pay for each request with x402. Leave out `apiKey`, so no `Authorization` header is sent and the API answers with a `402` quote, and pass the standard x402 v2 client's fetch as the provider's `fetch`: it signs the quote and resends the same body. Each payment is at least 0.01 ITC, is credited to the paying address's balance, and each request is charged its exact cost ([agents.md](https://inferit.cc/agents.md), [API reference](https://inferit.cc/docs/api-reference.md#x402)). The client caps one payment at 1 ITC; that is a setting in your client, not a rule of the contract.

_chat-x402.mts_

```typescript
// npm i ai @ai-sdk/openai-compatible @x402/fetch @x402/evm viem
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
import { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { ExactEvmScheme } from '@x402/evm/exact/client';
import { generateText } from 'ai';
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';

const account = privateKeyToAccount((process.env.AGENT_KEY ?? generatePrivateKey()) as `0x${string}`);

// Testnet only: Inferit's faucet gives this address 1,000 free test ITC (the claim costs nothing).
await fetch('https://api-production-c74b9.up.railway.app/v1/faucet', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ address: account.address }),
});

// The standard x402 v2 client pays only in tokens it was told about: allow ITC,
// and cap one payment at 1 ITC (1000000 base units, 6 decimals).
const ITC = { network: 'eip155:1874', asset: '0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB' } as const;
const client = new x402Client()
  .register('eip155:*', new ExactEvmScheme(account))
  .setSpendControls({ allowedAssets: [{ ...ITC, maxAmountPerPayment: '1000000' }] });
const paidFetch = wrapFetchWithPayment(fetch, client);

// No apiKey: the provider sends no Authorization header, so the API answers with
// a 402 quote, which paidFetch pays and retries with PAYMENT-SIGNATURE.
const inferit = createOpenAICompatible({ name: 'inferit', baseURL: 'https://api-production-c74b9.up.railway.app/v1', fetch: paidFetch });

const { text } = await generateText({
  model: inferit('qwen/qwen-2.5-14b-instruct'),
  prompt: 'Say hello in five words.',
  maxOutputTokens: 64, // the quote is the worst case for this body: a small limit keeps it small
});
console.log(text);
```

`streamText` works the same way: the payment is settled before the stream starts.

## Checked

The API-key sample ran against the hosted testnet API on 2026-10-13, with a named model (auto had no candidate that day).

The x402 variant was run up to the API's `402` quote: the request reached the API with no `Authorization` header and the x402 client read the quote. The paid retry is the same exchange as on [Agents](https://inferit.cc/agents).

---

Canonical page: https://inferit.cc/docs/guides/vercel-ai-sdk
All pages as markdown: https://inferit.cc/llms.txt
Testnet demo: test tokens, no monetary value.
