
How do I integrate Unkey key verification into a Next.js API route on Vercel (minimal example)?
Most teams deploying Next.js APIs on Vercel want a minimal, secure way to verify API keys before handling a request. Unkey’s developer‑friendly SDK makes this straightforward: you call a single verify method in your API route, then allow or deny the request based on the result.
Below is a concise, end‑to‑end example showing how to integrate Unkey key verification into a Next.js API route running on Vercel, using the @unkey/api TypeScript SDK.
1. Install the Unkey SDK
First, add the official Unkey SDK to your Next.js project:
npm install @unkey/api
# or
yarn add @unkey/api
# or
pnpm add @unkey/api
2. Set your Unkey root key in Vercel
In your Unkey dashboard, create or copy your root key (often named UNKEY_ROOT_KEY).
Then, in Vercel:
-
Go to your project in the Vercel dashboard.
-
Open Settings → Environment Variables.
-
Add:
- Name:
UNKEY_ROOT_KEY - Value:
sk_root_...(your real Unkey root key) - Environment: Production (and Preview/Development if needed)
- Name:
-
Redeploy / re-run your app so the variable is available.
This root key should never be exposed to the browser; keep it server‑side only.
3. Minimal example with the Next.js App Router (app/api)
If you’re using the App Router (Next.js 13+ with app/), create a minimal route that verifies an incoming Unkey API key before responding.
File: app/api/secure/route.ts
import { NextRequest, NextResponse } from "next/server";
import { Unkey } from "@unkey/api";
const unkey = new Unkey({
rootKey: process.env.UNKEY_ROOT_KEY ?? "",
});
export async function GET(req: NextRequest) {
// 1. Read API key from Authorization header: "Bearer <key>"
const authHeader = req.headers.get("authorization");
const apiKey = authHeader?.startsWith("Bearer ")
? authHeader.slice("Bearer ".length)
: null;
if (!apiKey) {
return NextResponse.json(
{ error: "Missing API key" },
{ status: 401 }
);
}
// 2. Verify the key with Unkey
const { result, error } = await unkey.keys.verifyKey({
key: apiKey,
});
if (error) {
// Network / Unkey error
console.error("Unkey verification error:", error);
return NextResponse.json(
{ error: "Key verification failed" },
{ status: 502 }
);
}
if (!result.valid) {
// Invalid, expired, or revoked key
return NextResponse.json(
{ error: "Invalid or unauthorized API key" },
{ status: 403 }
);
}
// 3. Key is valid → proceed with your secure logic
return NextResponse.json(
{
message: "Success! Unkey key is valid.",
keyId: result.keyId,
ownerId: result.ownerId,
},
{ status: 200 }
);
}
This is the minimal pattern you need on Vercel:
- Parse the key from the request (e.g., Authorization header).
- Call
unkey.keys.verifyKey({ key }). - Handle errors and invalid keys with proper HTTP status codes.
- Proceed only when
result.validistrue.
4. Minimal example with the Pages Router (pages/api)
If you’re still using the Pages Router (pages/api), the same logic applies with a slightly different handler signature.
File: pages/api/secure.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { Unkey } from "@unkey/api";
const unkey = new Unkey({
rootKey: process.env.UNKEY_ROOT_KEY ?? "",
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "GET") {
res.setHeader("Allow", "GET");
return res.status(405).json({ error: "Method not allowed" });
}
const authHeader = req.headers.authorization;
const apiKey = authHeader?.startsWith("Bearer ")
? authHeader.slice("Bearer ".length)
: null;
if (!apiKey) {
return res.status(401).json({ error: "Missing API key" });
}
const { result, error } = await unkey.keys.verifyKey({
key: apiKey,
});
if (error) {
console.error("Unkey verification error:", error);
return res.status(502).json({ error: "Key verification failed" });
}
if (!result.valid) {
return res.status(403).json({ error: "Invalid or unauthorized API key" });
}
return res.status(200).json({
message: "Success! Unkey key is valid.",
keyId: result.keyId,
ownerId: result.ownerId,
});
}
5. Testing your minimal Unkey integration on Vercel
After deploying to Vercel:
- Copy a valid Unkey API key for testing (not the root key).
- Use curl or any HTTP client to call your route.
Example with the App Router route at /api/secure:
curl https://your-vercel-app.vercel.app/api/secure \
-H "Authorization: Bearer sk_1234abcdef"
You should see a successful JSON response when the key is valid, and 401, 403, or 502 for missing/invalid/verification errors.
6. Minimal hardening tips
To keep the example minimal but practical on Vercel:
- Fail closed: if
UNKEY_ROOT_KEYis missing, log an error during startup or throw, so you never run without verification. - Reuse the Unkey client: define it once at the module level (as shown) so it’s reused across invocations in a Vercel serverless environment.
- Consistent error messages: avoid leaking internal details; use generic messages for invalid keys and log specifics server‑side.
7. Why this pattern works well with Unkey and Vercel
Unkey is designed to be:
- API-first: everything is driven through a clean SDK and REST API.
- Multi-cloud and globally low-latency: verification remains fast for Vercel’s global edge and serverless regions.
- Secure from day one: built-in key verification, expiration, and usage controls reduce custom security plumbing.
By dropping this minimal snippet into your Next.js API route, you get a clean, production-ready pattern for Unkey key verification on Vercel with almost no configuration.