Vercel AI SDK
Send Vercel AI SDK calls through the CoreValue gateway, attribute their cost to customers and features, and route through Vercel AI Gateway.
Introduction
The Vercel AI SDK (ai) works with CoreValue through its OpenAI provider: point
the provider at the CoreValue gateway and every call is metered, budgeted and attributed. Headers you
add tell CoreValue which customer, feature or end user a call was for, which is what cost per customer
and the other unit-economics reports are built from.
Set up
Sign in at app.corevalue.dev. Create a key under Governance › Keys, and add the key for each provider you call under Gateway › Provider keys.
COVA_API_KEY=sk-cova-XXXXXXXXXXXXXXXXnpm install ai @ai-sdk/openaipnpm add ai @ai-sdk/openaiimport { createOpenAI } from "@ai-sdk/openai";
import { generateText } from "ai";
const cova = createOpenAI({
apiKey: process.env.COVA_API_KEY,
baseURL: "https://gateway.corevalue.dev/gateway/v1",
});
const { text } = await generateText({
model: cova.chat("gpt-4o-mini"),
prompt: "Write a haiku about cost per customer.",
});Use cova.chat(...). Since AI SDK 5, calling the provider directly, as cova("gpt-4o-mini"),
uses OpenAI's Responses API (AI SDK OpenAI provider).
cova.chat(...) uses Chat Completions, which every provider and model prefix supports. For the
Responses API itself, see Responses API.
Which base URL
| Base URL | Use it for |
|---|---|
https://gateway.corevalue.dev/gateway/v1 | Any model, with or without a provider prefix: gpt-4o-mini, groq/llama-3.3-70b-versatile, vercel/openai/gpt-4o-mini. Use this one. |
https://gateway.corevalue.dev/v1 | OpenAI models only. A prefixed model here is not routed by its prefix; the request goes to OpenAI. |
The prefixes are listed in Call other providers.
Attribute cost to customers and features
Add CoreValue headers to the provider, where they go on every request, or to a single call. A call's headers are sent together with the provider's.
import { createOpenAI } from "@ai-sdk/openai";
import { generateText } from "ai";
const cova = createOpenAI({
apiKey: process.env.COVA_API_KEY,
baseURL: "https://gateway.corevalue.dev/gateway/v1",
headers: {
"Cova-Feature-Id": "support-assistant", // the same for every call from this client
},
});
const { text } = await generateText({
model: cova.chat("gpt-4o-mini"),
prompt: question,
headers: {
"Cova-Customer-Id": account.id, // who this call was for
"Cova-User-Id": user.id, // the person using your product
},
});| Header | What CoreValue does with it |
|---|---|
Cova-Customer-Id | Cost per customer: unit economics, customer budgets and the margin floor, chargeback |
Cova-Feature-Id | Cost per feature, on the Spend page |
Cova-User-Id | Requests and spend per end user. Attribution only: no budget is set on it |
Cova-Property-<Name> | Any label you choose, for filtering requests, e.g. Cova-Property-Env: production |
The team is not a header: it comes from the CoreValue API key that made the call. Every header is described in the Headers reference.
Route through Vercel AI Gateway
If you buy models through Vercel AI Gateway and have no account with each provider, keep doing so and put CoreValue in front of it:
- Add your Vercel AI Gateway API key under Gateway › Provider keys as Vercel AI Gateway.
- Prefix Vercel's model id with
vercel/, on the/gateway/v1base URL.
const { text } = await generateText({
model: cova.chat("vercel/openai/gpt-4o-mini"), // Vercel's id is openai/gpt-4o-mini
prompt: question,
headers: { "Cova-Customer-Id": account.id },
});Vercel still bills you. CoreValue records each request at the model's list price on its author's own API, which is what Vercel charges, and applies your budgets, key caps and attribution as for any provider. More in Call other providers.
Do not use the AI SDK's own Vercel AI Gateway provider (@ai-sdk/gateway, the gateway(...)
model helper) for these calls. It sends requests straight to Vercel, so CoreValue never sees them:
no cost, no budgets, no attribution. Use the OpenAI provider pointed at CoreValue, as above.
Examples
Streaming
Streamed calls are metered and attributed the same way.
import { streamText } from "ai";
const result = streamText({
model: cova.chat("gpt-4o-mini"),
prompt: "Write a short story about a robot learning to paint.",
maxOutputTokens: 300,
headers: { "Cova-Customer-Id": account.id },
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}In a Next.js route handler, return result.toUIMessageStreamResponse() as usual.
Another provider
const { text } = await generateText({
model: cova.chat("anthropic/claude-sonnet-4-5-20250929"),
prompt: "Explain quantum computing in two sentences.",
});The provider's key must be saved under Gateway › Provider keys.
Tool calling
import { generateText, tool } from "ai";
import { z } from "zod";
const result = await generateText({
model: cova.chat("gpt-4o"),
prompt: "What is the weather like in San Francisco?",
tools: {
getWeather: tool({
description: "Get the weather for a location",
inputSchema: z.object({ location: z.string().describe("The city name") }),
execute: async ({ location }) => `It's sunny in ${location}`,
}),
},
});Request a CoreValue Integration
Looking for a framework or tool not listed here? Request it here!