We use cookies. Cookies and browser storage keep you signed in and remember your preferences. With your permission we also measure how the site is used. You can any time. See our cookie policy.

Vercel AI SDK

SDK guides

Vercel AI SDK

Use api14 as an OpenAI-compatible provider in the Vercel AI SDK for text generation, streaming, tool calls and structured output in your app.

The Vercel AI SDK talks to api14 through its OpenAI-compatible provider. Every model id becomes a model you can pass to generateText, streamText, generateObject or embed.

Install

npm install ai @ai-sdk/openai-compatible zod
export API14_API_KEY="sk-api14-..."

Configure

import { createOpenAICompatible } from "@ai-sdk/openai-compatible";

export const api14 = createOpenAICompatible({
  name: "api14",
  baseURL: "https://api14.com/api/v1",
  apiKey: process.env.API14_API_KEY,
  includeUsage: true,
});

@ai-sdk/openai works too: createOpenAI({ baseURL: "https://api14.com/api/v1", apiKey }), then use openai.chat("anthropic/claude-sonnet-4.5") so requests go to /chat/completions.

Generate text

import { generateText } from "ai";

const { text, usage } = await generateText({
  model: api14("anthropic/claude-sonnet-4.5"),
  prompt: "Explain vector databases in two sentences.",
});
console.log(text, usage);

Streaming

import { streamText } from "ai";

const result = streamText({
  model: api14("openai/gpt-5-mini"),
  prompt: "Write a haiku about APIs.",
});

for await (const delta of result.textStream) process.stdout.write(delta);

In a Next.js route handler, return the stream directly:

// app/api/chat/route.ts
import { convertToModelMessages, streamText, type UIMessage } from "ai";

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();
  const result = streamText({ model: api14("openai/gpt-5-mini"), messages: convertToModelMessages(messages) });
  return result.toUIMessageStreamResponse();
}

Tools and structured output

import { generateObject, generateText, tool } from "ai";
import { z } from "zod";

const { text } = await generateText({
  model: api14("openai/gpt-5-mini"),
  prompt: "What is the weather in Istanbul?",
  tools: {
    getWeather: tool({
      description: "Get the current weather",
      inputSchema: z.object({ city: z.string() }),
      execute: async ({ city }) => ({ city, tempC: 21 }),
    }),
  },
});

const { object } = await generateObject({
  model: api14("openai/gpt-5-mini"),
  schema: z.object({ city: z.string(), country: z.string() }),
  prompt: 'Extract the place from: "I live in Lisbon, Portugal."',
});

Embeddings

import { embedMany } from "ai";

const { embeddings } = await embedMany({
  model: api14.textEmbeddingModel("openai/text-embedding-3-small"),
  values: ["The quick brown fox", "Lorem ipsum"],
});

Errors

import { APICallError } from "ai";

try {
  await generateText({ model: api14("openai/gpt-5-mini"), prompt: "Hi" });
} catch (e) {
  if (APICallError.isInstance(e) && e.statusCode === 402) console.error("Balance too low, add funds");
  else if (APICallError.isInstance(e) && e.statusCode === 429) console.error("Retry after", e.responseHeaders?.["retry-after"]);
  else throw e;
}

The SDK retries 429 and 5xx twice by default (maxRetries on each call). See Errors.