Next.js API Routes: Building Serverless APIs
Next.js API Routes: Building Serverless APIs
Next.js API routes allow you to build APIs within your Next.js application. Let's explore how to create powerful serverless endpoints.
Basic API Route
// pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default function handler(
req: NextApiRequest,
res: NextApiResponse
) {
res.status(200).json({ message: 'Hello from API!' });
}
HTTP Methods
// pages/api/users/index.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
switch (req.method) {
case 'GET':
const users = await getUsers();
res.status(200).json(users);
break;
case 'POST':
const user = await createUser(req.body);
res.status(201).json(user);
break;
default:
res.setHeader('Allow', ['GET', 'POST']);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
}
Dynamic Routes
// pages/api/users/[id].ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { id } = req.query;
if (req.method === 'GET') {
const user = await getUserById(id as string);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.status(200).json(user);
}
}
Middleware
// middleware.ts
import type { NextApiRequest, NextApiResponse } from 'next';
type Middleware = (
req: NextApiRequest,
res: NextApiResponse,
next: () => void
) => void;
function withMiddleware(middleware: Middleware[]) {
return (handler: Function) => {
return async (req: NextApiRequest, res: NextApiResponse) => {
for (const mw of middleware) {
await new Promise<void>((resolve, reject) => {
mw(req, res, () => resolve());
});
}
return handler(req, res);
};
};
}
// Auth middleware
const authMiddleware = (
req: NextApiRequest,
res: NextApiResponse,
next: () => void
) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized' });
}
next();
};
// Usage
export default withMiddleware([authMiddleware])(handler);
Error Handling
// pages/api/users/index.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const users = await getUsers();
res.status(200).json(users);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
}
App Router API Routes (Next.js 13+)
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
const users = await getUsers();
return NextResponse.json(users);
}
export async function POST(request: Request) {
const body = await request.json();
const user = await createUser(body);
return NextResponse.json(user, { status: 201 });
}
Best Practices
- Validate input with libraries like Zod
- Handle errors gracefully
- Use TypeScript for type safety
- Implement rate limiting
- Keep routes focused - single responsibility
Conclusion
Next.js API routes provide a powerful way to build serverless APIs alongside your frontend. With proper structure and error handling, you can create robust APIs for your applications.