How to Deploy Claude API on Vercel: Full Guide
Deploying "Claude API on Vercel" doesn't mean hosting a model — Claude runs on Anthropic's infrastructure, not yours. What you're actually deploying is a serverless backend route (usually a Next.js API route or Vercel Function) that holds your API key securely and forwards requests from your frontend to Claude, then streams the response back. This guide walks through exactly how to build and ship that.
If you've tried calling the Claude API directly from a browser, you've already hit the wall: CORS blocks it, and even if it didn't, you'd be exposing your API key to anyone who opens devtools. Vercel fixes this by letting you run a thin server-side function next to your frontend, in the same deploy, with zero separate infrastructure to manage.
Why you need a backend layer at all
Claude's API expects requests with an x-api-key header and a JSON body describing the conversation. That key must never reach client-side JavaScript. So the deployment pattern on Vercel is always:
- Frontend (React/Next.js/static site) calls your own
/api/chatroute - That route runs server-side on Vercel, holds the real API key in an environment variable
- It calls Claude (or a gateway like SubToAPI), gets the response, and returns it to the browser
This is true whether you're hitting Anthropic's endpoint directly or routing through a service that manages keys and usage for you.
Step 1: Set up the project
Start with a standard Next.js app (App Router works fine with Vercel's edge/serverless runtimes):
npx create-next-app@latest claude-vercel-app
cd claude-vercel-app
Create an API route at app/api/chat/route.js:
export async function POST(req) {
const { messages } = await req.json();
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages,
}),
});
const data = await response.json();
return Response.json(data);
}
This is the core pattern: a server-side route that holds the secret and proxies the request.
Step 2: Add environment variables
Never commit API keys. Add them locally in .env.local:
ANTHROPIC_API_KEY=sk-ant-...
Then in the Vercel dashboard, go to Settings → Environment Variables and add the same key for Production, Preview, and Development environments separately. Vercel injects these at build and runtime — your code just reads process.env.ANTHROPIC_API_KEY without any extra config.
Step 3: Deploy
Push to GitHub and import the repo in Vercel, or deploy directly from the CLI:
npm i -g vercel
vercel
Vercel auto-detects Next.js, builds it, and gives you a production URL. Every push to your main branch triggers a new deployment; every pull request gets its own preview URL with its own environment variables, which is useful for testing prompt changes without touching production traffic.
Step 4: Handle streaming correctly
Chat UIs feel broken without streaming. Vercel Functions support streaming responses, but you need to use the Edge runtime (not the default Node.js serverless runtime) for the lowest latency, and pipe the response body through instead of buffering it:
export const runtime = "edge";
export async function POST(req) {
const { messages } = await req.json();
const upstream = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
stream: true,
messages,
}),
});
return new Response(upstream.body, {
headers: { "content-type": "text/event-stream" },
});
}
This forwards the server-sent events straight to the browser without Vercel buffering the whole response first.
Simplifying key and team management with SubToAPI
The pattern above works, but it has rough edges once you're past a side project: you're managing one raw API key, there's no built-in way to issue separate keys per environment or teammate, and usage metadata isn't broken down anywhere.
SubToAPI sits in the same backend-route position but gives you sub_live_... application keys instead of a single shared secret, so you can issue a distinct key per app, per environment, or per teammate and revoke any of them individually from a dashboard. The Vercel route itself barely changes — you just point the fetch call at SubToAPI's endpoint and swap the header:
export const runtime = "edge";
export async function POST(req) {
const { messages } = await req.json();
const upstream = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.SUBTOAPI_KEY}`,
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
stream: true,
messages,
}),
});
return new Response(upstream.body, {
headers: { "content-type": "text/event-stream" },
});
}
Streaming, tool use, and the same message format are all supported — see the streaming docs and tools docs for the request shapes. Plans start at €9/month for solo projects, with team seats on the Team (€19/seat) and Scale (€49/seat) plans if you need shared usage dashboards across a company. There's a free trial at /signup, and the quickstart covers getting a key in under five minutes.
Deployment checklist
Before calling it done:
- API key is only referenced server-side, never in client bundles
- Environment variables are set for Production, Preview, and Development on Vercel
- Streaming routes use
runtime = "edge"and forward the response body directly - Rate limiting or basic abuse protection exists on your
/api/chatroute if it's publicly reachable - Error responses from Claude (4xx/5xx) are caught and surfaced as readable errors, not raw JSON dumps
Questions
Do I need a dedicated server to run Claude on Vercel? No. Vercel Functions (serverless or edge) are enough — you're just proxying requests to Claude's API, not hosting a model.
Can I call the Claude API directly from client-side JavaScript on Vercel? No. CORS and security both prevent this. You need a server-side route (API route, edge function) that holds the key and forwards the request.
Why would I use SubToAPI instead of Anthropic's API directly on Vercel? SubToAPI adds per-app API keys, team seats, and usage metadata on top of the same request format, which matters once more than one person or project shares access. See /pricing for plan details.