While static API routes are useful for fixed endpoints, real-world applications often require dynamic endpoints that can adapt based on the input provided by the client. Think about fetching a specific user's profile, retrieving details for a particular product, or updating a record identified by a unique ID. This is where dynamic API routes in Next.js shine.
Dynamic API routes are created by using square brackets [] around a part of the file name within the pages/api directory. This bracketed segment represents a dynamic parameter that can be captured and used within your API route handler.
For instance, if you have a file named pages/api/users/[id].js, the [id] part signifies a dynamic parameter. When a request comes in for a URL like /api/users/123, the value 123 will be available as the id parameter.
export default function handler(req, res) {
const { id } = req.query;
res.status(200).json({ userId: id });
}In the code above, req.query is an object containing all the query parameters and dynamic route parameters. For a dynamic route like [id].js, the value of the id parameter will be accessible within req.query.id.
You can also have multiple dynamic parameters within a single route. For example, a route like pages/api/posts/[postId]/comments/[commentId].js would allow you to access both postId and commentId from req.query.
export default function handler(req, res) {
const { postId, commentId } = req.query;
res.status(200).json({
message: `Fetching comment ${commentId} for post ${postId}`,
});
}A powerful feature for handling more complex dynamic routing is the 'catch-all' route. This is denoted by using three dots ... followed by a parameter name inside the square brackets, such as [...slug].js. This route will match any URL that falls under its parent directory.
When a catch-all route is matched, the parameter will be an array of all the URL segments. For example, if you have pages/api/files/[...path].js and a request comes in for /api/files/documents/reports/2023.pdf, req.query.path will be an array: ['documents', 'reports', '2023.pdf'].
export default function handler(req, res) {
const { path } = req.query;
res.status(200).json({ filePathParts: path });
}You can also create optional catch-all routes by wrapping the entire dynamic segment in double square brackets, like [[...slug]].js. This allows the route to also match the base path without any additional segments. For instance, pages/api/users/[[...userId]].js would match both /api/users and /api/users/123.
graph TD;
A[Request to /api/users/123]
B[Pages directory structure]
C[pages/api/users/[id].js]
D[req.query.id = '123']
E[API Handler Logic]
F[Response with user data]
A --> B;
B --> C;
C --> D;
D --> E;
E --> F;
Understanding and utilizing dynamic API routes allows you to build highly flexible and powerful backend services directly within your Next.js application, streamlining your development process.