Next.js API Routes: Creating Backend Endpoints
Learn how to create API routes in Next.js to build backend functionality. Master route handlers, request methods, and building RESTful APIs.
Next.js API Routes: Creating Backend Endpoints
Next.js makes it easy to build full-stack applications by allowing you to create API endpoints right alongside your frontend code. In this guide, we'll explore how to create and use API routes in Next.js.
If you're new to Next.js, start with our Getting Started with Next.js guide. For routing basics, check out our Routing guide.
What are API Routes?
API routes in Next.js are server-side functions that handle HTTP requests. They're perfect for:
- Creating RESTful APIs
- Handling form submissions
- Building webhook endpoints
- Integrating with databases
- Creating authentication endpoints
Creating Your First API Route
In the App Router, API routes are created using route.js or route.ts files in the app directory.
app/
api/
hello/
route.js
This creates an endpoint at /api/hello.
Basic GET Handler
// app/api/hello/route.js
export async function GET() {
return Response.json({ message: 'Hello from Next.js!' });
}
Handling Different HTTP Methods
You can export functions for different HTTP methods:
// app/api/users/route.js
export async function GET(request) {
// Handle GET request
const users = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
];
return Response.json({ users });
}
export async function POST(request) {
// Handle POST request
const body = await request.json();
// Process the data
const newUser = {
id: Date.now(),
...body,
};
return Response.json({ user: newUser }, { status: 201 });
}
Working with Request Data
Reading Request Body
export async function POST(request) {
const body = await request.json();
// Use body data
return Response.json({ received: body });
}
Reading Query Parameters
export async function GET(request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
return Response.json({ id });
}
Reading Headers
export async function GET(request) {
const authorization = request.headers.get('authorization');
if (!authorization) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
return Response.json({ message: 'Authorized' });
}
Dynamic API Routes
Just like pages, API routes can be dynamic:
app/
api/
users/
[id]/
route.js
// app/api/users/[id]/route.js
export async function GET(request, { params }) {
const { id } = await params;
// Fetch user by ID
const user = { id, name: 'John Doe' };
return Response.json({ user });
}
export async function PUT(request, { params }) {
const { id } = await params;
const body = await request.json();
// Update user
return Response.json({ user: { id, ...body } });
}
export async function DELETE(request, { params }) {
const { id } = await params;
// Delete user
return Response.json({ message: 'User deleted' }, { status: 200 });
}
Error Handling
Always handle errors properly in your API routes:
export async function GET(request) {
try {
// Your logic here
const data = await fetchData();
return Response.json({ data });
} catch (error) {
return Response.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}
Working with Databases
Here's an example of integrating with a database:
// app/api/posts/route.js
import { db } from '@/lib/database';
export async function GET() {
try {
const posts = await db.post.findMany();
return Response.json({ posts });
} catch (error) {
return Response.json(
{ error: 'Failed to fetch posts' },
{ status: 500 }
);
}
}
export async function POST(request) {
try {
const body = await request.json();
const post = await db.post.create({
data: body,
});
return Response.json({ post }, { status: 201 });
} catch (error) {
return Response.json(
{ error: 'Failed to create post' },
{ status: 500 }
);
}
}
Authentication in API Routes
Here's a simple example of handling authentication:
// app/api/protected/route.js
export async function GET(request) {
const token = request.headers.get('authorization');
if (!token || !isValidToken(token)) {
return Response.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
return Response.json({ message: 'Protected data' });
}
CORS Configuration
If you need to handle CORS:
export async function GET(request) {
return Response.json(
{ data: 'Hello' },
{
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type',
},
}
);
}
Best Practices
- Validate input: Always validate and sanitize user input
- Handle errors: Use try-catch blocks and return appropriate status codes
- Use TypeScript: Add type safety to your API routes
- Rate limiting: Implement rate limiting for public APIs
- Environment variables: Use environment variables for sensitive data
- Response format: Keep your response format consistent
Real-World Example: Blog API
Here's a complete example of a blog API:
// app/api/blog/route.js
let posts = [
{ id: 1, title: 'First Post', content: 'Content here' },
];
export async function GET() {
return Response.json({ posts });
}
export async function POST(request) {
const { title, content } = await request.json();
if (!title || !content) {
return Response.json(
{ error: 'Title and content are required' },
{ status: 400 }
);
}
const newPost = {
id: posts.length + 1,
title,
content,
createdAt: new Date().toISOString(),
};
posts.push(newPost);
return Response.json({ post: newPost }, { status: 201 });
}
Testing API Routes
You can test your API routes using tools like:
- curl: Command-line tool
- Postman: GUI tool for API testing
- Thunder Client: VS Code extension
- Next.js built-in testing: Use fetch in your tests
Conclusion
API routes in Next.js provide a powerful way to build backend functionality without a separate server. They're perfect for building full-stack applications with a single framework.
Next Steps:
- Learn about Next.js Routing for dynamic pages
- Discover Image Optimization techniques
- Explore Metadata API for SEO improvements
- Check out Middleware for authentication
Happy coding! 🚀
Related Articles
Next.js Image Optimization: Using the Image Component
Master Next.js image optimization with the Image component. Learn lazy loading, responsive images, and performance best practices.
Next.js Metadata API: Improving SEO
Learn how to use Next.js Metadata API to improve SEO, add Open Graph tags, Twitter cards, and structured data to your pages.
Next.js Middleware: Adding Authentication and More
Master Next.js middleware to add authentication, handle redirects, modify requests, and implement advanced routing logic.