Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
v0 SDK
https://github.com/vercel/v0-sdk
Admin
A monorepo containing SDKs for interacting with the v0 Platform API to create and manage AI-powered
...
Tokens:
29,513
Snippets:
293
Trust Score:
10
Update:
21 hours ago
Context
Skills
Chat
Benchmark
86.5
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# v0 SDK The v0 SDK is a TypeScript monorepo for interacting with the [v0 Platform API](https://v0.dev/docs/api) — Vercel's AI-powered UI generation service. It provides a fully-typed REST client (`v0-sdk`), headless React rendering components (`@v0-sdk/react`), AI SDK tool integrations (`@v0-sdk/ai-tools`), and a project scaffolding CLI (`create-v0-sdk-app`). The SDK is in Developer Preview (currently v0.16.4) and targets Node.js 22+. The core client wraps the `https://api.v0.dev/v1` REST API, authenticating via a Bearer token from the `V0_API_KEY` environment variable or a passed `apiKey` config option. All resources — chats, messages, versions, projects, deployments, webhooks, MCP servers, users, and rate limits — are accessible as namespaced methods on the default `v0` export or on a custom client created with `createClient()`. Streaming responses (SSE) are supported for chat creation and message sending via `responseMode: 'experimental_stream'`, with a built-in `parseStreamingResponse` async generator for consuming the event stream. --- ## v0-sdk ### Installation and client setup Install the core SDK and configure authentication. The default export `v0` is a pre-configured singleton; `createClient` creates isolated instances. ```typescript // npm install v0-sdk // export V0_API_KEY=your_key_here import { v0, createClient } from 'v0-sdk' // Using default singleton (reads V0_API_KEY from env) const chat = await v0.chats.create({ message: 'Hello' }) // Custom client with explicit key and optional base URL override const client = createClient({ apiKey: process.env.V0_API_KEY, baseUrl: 'https://api.v0.dev/v1', // optional }) ``` --- ### `v0.chats.create` — Create a new chat Starts a new v0 AI conversation. Supports sync, async, or SSE streaming response modes. Returns a `ChatDetail` object, or a `ReadableStream` when `responseMode` is `'experimental_stream'`. ```typescript import { v0, parseStreamingResponse } from 'v0-sdk' // --- Sync (default) --- const chat = await v0.chats.create({ message: 'Build a responsive pricing table with Tailwind CSS', system: 'You are an expert React/Next.js developer', chatPrivacy: 'private', // 'public' | 'private' | 'team' | 'team-edit' | 'unlisted' projectId: 'proj_abc123', // optional modelConfiguration: { modelId: 'v0-pro', // 'v0-auto' | 'v0-mini' | 'v0-pro' | 'v0-max' | 'v0-max-fast' thinking: false, imageGenerations: false, }, responseMode: 'sync', }) console.log(chat.id) // "chat_xyz" console.log(chat.webUrl) // "https://v0.dev/chat/xyz" console.log(chat.latestVersion?.status) // "completed" // --- Streaming --- const stream = await v0.chats.create({ message: 'Create a dark mode dashboard layout', responseMode: 'experimental_stream', }) as ReadableStream<Uint8Array> for await (const event of parseStreamingResponse(stream)) { // event.event: 'message' | custom event name // event.data: raw SSE data string (JSON) process.stdout.write(event.data) } ``` --- ### `v0.chats.sendMessage` — Send a follow-up message Sends an additional message to an existing chat. Supports the same model config and response modes as `create`. ```typescript import { v0 } from 'v0-sdk' const updated = await v0.chats.sendMessage({ chatId: 'chat_xyz', message: 'Make the button use a gradient instead of a solid color', modelConfiguration: { modelId: 'v0-max' }, responseMode: 'sync', }) console.log(updated.latestVersion?.demoUrl) // live preview URL ``` --- ### `v0.chats.init` — Initialize a chat from files, repo, registry, zip, or template Creates a chat pre-seeded with existing code via multiple source types. ```typescript import { v0 } from 'v0-sdk' // From files const chat = await v0.chats.init({ type: 'files', files: [ { name: 'app/page.tsx', content: 'export default function Page() { return <h1>Hello</h1> }' }, { name: 'components/Button.tsx', url: 'https://example.com/Button.tsx' }, ], name: 'My App Refactor', chatPrivacy: 'private', }) // From GitHub repo const chatFromRepo = await v0.chats.init({ type: 'repo', repo: { url: 'https://github.com/org/my-app', branch: 'main' }, lockAllFiles: false, }) // From a template const chatFromTemplate = await v0.chats.init({ type: 'template', templateId: 'nextjs-saas-starter', }) ``` --- ### `v0.chats.find` — List chats with pagination Returns a paginated list of chat summaries. Filter by favorite status or Vercel project. ```typescript import { v0 } from 'v0-sdk' const { data } = await v0.chats.find({ limit: 20, offset: 0, isFavorite: true, vercelProjectId: 'prj_abc', }) for (const chat of data) { console.log(`${chat.id} – ${chat.name ?? 'Untitled'} (${chat.privacy})`) } ``` --- ### `v0.chats.getById` / `update` / `delete` / `favorite` / `fork` — Chat lifecycle Full CRUD and lifecycle operations on chats. ```typescript import { v0 } from 'v0-sdk' // Get full details const detail = await v0.chats.getById({ chatId: 'chat_xyz' }) console.log(detail.messages.length) // total messages // Rename and change privacy const renamed = await v0.chats.update({ chatId: 'chat_xyz', name: 'Pricing Table v2', privacy: 'public', }) // Mark as favorite await v0.chats.favorite({ chatId: 'chat_xyz', isFavorite: true }) // Fork from a specific version const fork = await v0.chats.fork({ chatId: 'chat_xyz', versionId: 'ver_abc', privacy: 'private', }) console.log(fork.id) // new chat ID // Delete await v0.chats.delete({ chatId: 'chat_xyz' }) ``` --- ### `v0.chats.findVersions` / `getVersion` / `updateVersion` / `downloadVersion` / `restore` — Version management Access and manage generated code versions within a chat. ```typescript import { v0 } from 'v0-sdk' // List all versions (paginated) const { data: versions, meta } = await v0.chats.findVersions({ chatId: 'chat_xyz', limit: 10, }) console.log(`Total versions: ${meta.totalCount}`) // Get a specific version with files const version = await v0.chats.getVersion({ chatId: 'chat_xyz', versionId: versions[0].id, includeDefaultFiles: true, }) for (const file of version.files) { console.log(`${file.name}: ${file.content.slice(0, 80)}...`) } // Patch files in a version const patched = await v0.chats.updateVersion({ chatId: 'chat_xyz', versionId: versions[0].id, files: [{ name: 'app/page.tsx', content: '// updated content', locked: false }], }) // Download as zip const buffer = await v0.chats.downloadVersion({ chatId: 'chat_xyz', versionId: versions[0].id, format: 'zip', }) // ArrayBuffer // Restore a previous version await v0.chats.restore({ chatId: 'chat_xyz', versionId: versions[1].id }) ``` --- ### `v0.chats.resolveTask` — Resolve a pending task in a chat Used when v0 requires user confirmation for integration connections, plan approvals, question answers, or tool permissions. ```typescript import { v0 } from 'v0-sdk' // Approve a plan const result = await v0.chats.resolveTask({ chatId: 'chat_xyz', task: { type: 'plan-exit-response', status: 'approved', content: 'Looks good, proceed with the implementation.', }, responseMode: 'sync', }) // Confirm integration connections await v0.chats.resolveTask({ chatId: 'chat_xyz', task: { type: 'confirmed-steps', connectedIntegrationNames: ['Neon', 'Clerk'], addedEnvVars: ['DATABASE_URL', 'CLERK_SECRET_KEY'], }, }) ``` --- ### `v0.chats.stop` / `resume` — Control streaming messages Stop a running generation or resume an interrupted one. ```typescript import { v0 } from 'v0-sdk' // Stop a running message await v0.chats.stop({ chatId: 'chat_xyz', messageId: 'msg_123' }) // Resume an interrupted message const msg = await v0.chats.resume({ chatId: 'chat_xyz', messageId: 'msg_123' }) console.log(msg.content) ``` --- ### `v0.projects.*` — Project management Create and manage projects that group related chats. ```typescript import { v0 } from 'v0-sdk' // Create a project const project = await v0.projects.create({ name: 'E-commerce App', description: 'Main product catalog and checkout flow', instructions: 'Always use TypeScript and Tailwind CSS', privacy: 'private', environmentVariables: [ { key: 'DATABASE_URL', value: 'postgresql://...' }, { key: 'STRIPE_KEY', value: 'sk_test_...' }, ], }) console.log(project.id) // "proj_abc" // List all projects const { data: projects } = await v0.projects.find() // Assign a chat to a project await v0.projects.assign({ projectId: project.id, chatId: 'chat_xyz' }) // Get project by chat const linkedProject = await v0.projects.getByChatId({ chatId: 'chat_xyz' }) // Manage env vars const envVars = await v0.projects.findEnvVars({ projectId: project.id, decrypted: true }) await v0.projects.updateEnvVars({ projectId: project.id, environmentVariables: [{ id: envVars.data[0].id, value: 'new_value' }], }) await v0.projects.deleteEnvVars({ projectId: project.id, environmentVariableIds: [envVars.data[0].id], }) ``` --- ### `v0.deployments.*` — Deployment management Deploy a specific chat version to Vercel and monitor the deployment. ```typescript import { v0 } from 'v0-sdk' // Create a deployment const deployment = await v0.deployments.create({ projectId: 'proj_abc', chatId: 'chat_xyz', versionId: 'ver_abc', }) console.log(deployment.webUrl) // live URL console.log(deployment.inspectorUrl) // Vercel inspector // Poll logs const { logs, nextSince } = await v0.deployments.findLogs({ deploymentId: deployment.id, since: Date.now() - 60_000, }) for (const log of logs) { console.log(`[${log.type}] ${log.text}`) } // Check for build errors const { formattedError } = await v0.deployments.findErrors({ deploymentId: deployment.id, }) if (formattedError) console.error(formattedError) // Delete a deployment await v0.deployments.delete({ deploymentId: deployment.id }) ``` --- ### `v0.hooks.*` — Webhook management Subscribe to v0 platform events via webhooks. ```typescript import { v0 } from 'v0-sdk' // Create a webhook const hook = await v0.hooks.create({ name: 'CI Notifier', url: 'https://myapp.com/webhooks/v0', events: ['chat.created', 'message.finished', 'message.updated'], chatId: 'chat_xyz', // optional: scope to a specific chat }) console.log(hook.id) // "hook_abc" // Update events await v0.hooks.update({ hookId: hook.id, events: ['message.finished'], url: 'https://myapp.com/webhooks/v0-v2', }) // List all hooks const { data: hooks } = await v0.hooks.find() // Delete await v0.hooks.delete({ hookId: hook.id }) ``` --- ### `v0.mcpServers.*` — MCP server management Register and manage Model Context Protocol (MCP) servers for use in v0 chats. ```typescript import { v0 } from 'v0-sdk' // Register an MCP server with bearer auth const server = await v0.mcpServers.create({ name: 'My Data API', url: 'https://mcp.myapp.com', description: 'Provides access to product data', enabled: true, auth: { type: 'bearer', token: process.env.MCP_TOKEN! }, scope: 'user', // 'user' | 'team' }) // Update await v0.mcpServers.update({ mcpServerId: server.id, enabled: false, }) // List all servers const { data: servers } = await v0.mcpServers.find() // Delete await v0.mcpServers.delete({ mcpServerId: server.id }) ``` --- ### `v0.user.*` and `v0.rateLimits.*` — Account and usage Retrieve user profile, plan details, billing info, and rate limits. ```typescript import { v0 } from 'v0-sdk' // Current user const user = await v0.user.get() console.log(user.email, user.name) // Plan and token balance const plan = await v0.user.getPlan() console.log(`Plan: ${plan.plan}, Remaining: ${plan.balance.remaining}/${plan.balance.total}`) // Billing detail (token-based) const billing = await v0.user.getBilling() if (billing.billingType === 'token') { console.log(`On-demand balance: ${billing.data.onDemand.balance}`) } // Rate limits const limits = await v0.rateLimits.find({ scope: 'user' }) console.log(`Remaining requests: ${limits.remaining} (resets at ${limits.reset})`) // Available scopes (team memberships) const { data: scopes } = await v0.user.getScopes() scopes.forEach(s => console.log(s.id, s.name)) ``` --- ### `v0.reports.*` — Usage reporting Query usage events, AI token consumption, and user activity (team plans). ```typescript import { v0 } from 'v0-sdk' // Usage events with pagination const usage = await v0.reports.getUsage({ startDate: '2025-01-01', endDate: '2025-01-31', limit: 50, }) usage.data.forEach(e => console.log(`${e.type}: $${e.totalCost}`)) // AI token usage const aiUsage = await v0.reports.getAIUsage({ start: '2025-01-01', end: '2025-01-31', limit: 100, }) aiUsage.data.forEach(e => { console.log(`${e.modelId}: ${e.totalTokens} tokens (${e.useCase})`) }) // Team user activity const activity = await v0.reports.getUserActivity({ startDate: '2025-01-01', endDate: '2025-01-31', }) activity.data.forEach(a => { console.log(`${a.user.email}: ${a.chatCount} chats, ${a.activeDays} active days`) }) ``` --- ## @v0-sdk/ai-tools ### `v0Tools` — All tools as a flat object Returns all v0 tools (~20+) as a flat object for direct use with the [Vercel AI SDK](https://sdk.vercel.ai). Includes tools for chats, projects, deployments, users, and webhooks. Use `v0ToolsByCategory` to reduce context when not all tools are needed. ```typescript import { generateText, stepCountIs } from 'ai' import { v0Tools } from '@v0-sdk/ai-tools' // npm install @v0-sdk/ai-tools ai const result = await generateText({ model: anthropic('claude-opus-4-5'), prompt: 'Create a new v0 project called "Fitness Tracker" and start a chat for the dashboard', tools: v0Tools({ apiKey: process.env.V0_API_KEY }), stopWhen: stepCountIs(5), }) console.log(result.text) // Shows tool calls made: createProject → createChat → ... result.steps.forEach((step, i) => step.toolCalls.forEach(tc => console.log(`Step ${i + 1}: ${tc.toolName}`)) ) ``` --- ### `v0ToolsByCategory` — Selective tools by category Returns tools grouped into `chat`, `project`, `deployment`, `user`, and `hook` categories. Spread only the categories needed to minimize LLM context size — the recommended approach for production use. ```typescript import { generateText, stepCountIs } from 'ai' import { v0ToolsByCategory } from '@v0-sdk/ai-tools' const tools = v0ToolsByCategory({ apiKey: process.env.V0_API_KEY }) // Only chat + project tools const result = await generateText({ model: openai('gpt-4o'), prompt: 'Create a portfolio project and start building the hero section', tools: { ...tools.chat, ...tools.project, }, stopWhen: stepCountIs(6), system: 'You are a v0 project setup agent. Create the project then start a chat.', }) // Available categories: tools.chat | tools.project | tools.deployment | tools.user | tools.hook console.log(result.text) ``` --- ### Individual tool creators — `createChatTools`, `createProjectTools`, etc. Fine-grained factory functions for each resource domain. Each returns typed AI SDK `tool` objects with Zod input schemas. ```typescript import { generateText, tool, stepCountIs } from 'ai' import { createChatTools, createProjectTools, createDeploymentTools, createUserTools, createHookTools, } from '@v0-sdk/ai-tools' import { z } from 'zod' const config = { apiKey: process.env.V0_API_KEY } const { createChat, sendMessage, forkChat, listChats } = createChatTools(config) const { createProject, listProjects, createEnvironmentVariables } = createProjectTools(config) const { createDeployment, getDeploymentLogs, getDeploymentErrors } = createDeploymentTools(config) const { getCurrentUser, getRateLimits, getUserPlan } = createUserTools(config) const { createHook, listHooks } = createHookTools(config) // Use individual tools in a targeted agent const { text } = await generateText({ model: openai('gpt-4o-mini'), tools: { createChat, sendMessage, // Custom answer tool to terminate the agent done: tool({ description: 'Signal that the task is complete', inputSchema: z.object({ summary: z.string(), chatUrl: z.string() }), }), }, stopWhen: stepCountIs(4), prompt: 'Create a chat for a SaaS landing page and send a follow-up message to add a pricing section', }) console.log(text) ``` --- ## @v0-sdk/react ### `<Message>` component and `useMessage` hook Renders v0 Platform API message content (the `MessageBinaryFormat` binary format returned in the `content` field of API responses). Supports full component customization via the `components` prop (react-markdown style). ```tsx import { v0 } from 'v0-sdk' import { Message, useMessage } from '@v0-sdk/react' import type { MessageBinaryFormat } from '@v0-sdk/react' // --- Component usage --- function ChatMessage({ content }: { content: MessageBinaryFormat }) { return ( <Message content={content} // JSON.parse(apiMessage.content) messageId="msg-001" role="assistant" streaming={false} isLastMessage={true} className="prose dark:prose-invert max-w-none" components={{ // Override code blocks CodeBlock: ({ language, code }) => ( <pre className={`language-${language} bg-zinc-900 rounded p-4`}> <code>{code}</code> </pre> ), // Override headings h2: { className: 'text-2xl font-bold mt-6 mb-3 text-blue-600' }, // Override links a: ({ href, children, ...props }) => ( <a href={href} target="_blank" rel="noopener noreferrer" className="underline text-blue-500" {...props}> {children} </a> ), }} /> ) } // --- Headless hook usage --- function CustomRenderer({ content }: { content: MessageBinaryFormat }) { const { elements } = useMessage({ content, role: 'assistant', streaming: false }) // elements is MessageElement[] — walk and render with your own renderer return <div>{elements.length} elements parsed</div> } ``` --- ### `<StreamingMessage>` component and `useStreamingMessage` hook Consumes a `ReadableStream<Uint8Array>` from `v0.chats.create({ responseMode: 'experimental_stream' })` and progressively renders content as it arrives via SSE delta patches. ```tsx import { useState } from 'react' import { v0 } from 'v0-sdk' import { StreamingMessage, useStreamingMessage } from '@v0-sdk/react' import type { MessageBinaryFormat } from '@v0-sdk/react' // --- Component usage --- function StreamDemo() { const [stream, setStream] = useState<ReadableStream<Uint8Array> | null>(null) const [chatUrl, setChatUrl] = useState<string>('') const handleGenerate = async () => { const response = await v0.chats.create({ message: 'Create a kanban board with drag-and-drop', responseMode: 'experimental_stream', }) as ReadableStream<Uint8Array> setStream(response) } return ( <div> <button onClick={handleGenerate}>Generate</button> {chatUrl && <a href={chatUrl}>Open in v0</a>} {stream && ( <StreamingMessage stream={stream} messageId="kanban-gen" role="assistant" showLoadingIndicator={true} loadingComponent={<div className="animate-pulse">Generating...</div>} errorComponent={(err) => <div className="text-red-500">Error: {err}</div>} onChatData={(chatData) => { // chatData.object === 'chat' — extract the web URL if (chatData.webUrl) setChatUrl(chatData.webUrl) }} onComplete={(finalContent: MessageBinaryFormat) => { console.log('Done! Sections:', finalContent.length) }} /> )} </div> ) } // --- Headless hook usage --- function HeadlessStream({ stream }: { stream: ReadableStream<Uint8Array> | null }) { const { content, isStreaming, isComplete, error } = useStreamingMessage(stream, { onChunk: (chunk) => console.log('Chunk received, elements:', chunk.length), onComplete: (final) => console.log('Streaming complete'), onError: (err) => console.error('Stream error:', err), }) if (error) return <p>Error: {error}</p> if (isStreaming && !content.length) return <p>Waiting for data...</p> return <div>Elements: {content.length}, Done: {String(isComplete)}</div> } ``` --- ## create-v0-sdk-app ### CLI scaffolding — create a new v0 SDK app Bootstraps a ready-to-run Next.js application wired up to the v0 SDK with a single command. Prompts interactively for app name and template selection. ```bash # Using pnpm (recommended) pnpm create v0-sdk-app@latest my-v0-app # Using npm npx create-v0-sdk-app@latest my-v0-app # Using yarn yarn create v0-sdk-app my-v0-app # Then: cd my-v0-app cp .env.example .env.local # Add V0_API_KEY pnpm install pnpm dev ``` --- ## Summary The v0 SDK covers the full lifecycle of AI-generated UI development: creating and iterating on chats with v0's generative models, versioning and downloading generated code, deploying to Vercel, and managing the organizational structure (projects, environment variables, webhooks, MCP servers). The core `v0-sdk` package is suitable for any server-side TypeScript/JavaScript environment including Next.js API routes, tRPC procedures, CLI tools, and standalone Node scripts. The `@v0-sdk/ai-tools` package bridges v0 directly into LLM-driven agentic workflows using the Vercel AI SDK, making it easy to build autonomous agents that programmatically create, update, and deploy v0-generated UIs in response to natural language instructions. For frontend integration, `@v0-sdk/react` provides both a batteries-included `<Message>` renderer and fully headless hooks (`useMessage`, `useStreamingMessage`) that let teams bring their own design system while leveraging v0's binary message format and delta-patch streaming protocol. Together the packages support patterns ranging from a simple prompt-to-preview pipeline (create chat → render stream → link to demo) to sophisticated multi-agent orchestration workflows with routing, parallelism, and evaluation-optimization feedback loops — all without requiring direct REST API knowledge.