Next.js: Dynamic API Segments for Flexible Endpoints
Think of dynamic API segments as URL templates. A single file like `app/api/users/[id]/route.ts` can handle requests for any user ID, from `/api/users/1` to `/api/users/99`. The footgun is forgetting to parse the ID, which is always a string.
WHY IT EXISTS Hardcoding every possible API endpoint is impossible and unscalable. If your application has thousands of users, you cannot create thousands of route files like api/users/1, api/users/2, and so on. Dynamic segments solve this by allowing a single route handler to match a URL pattern, making your API manageable.
THE MENTAL MODEL Think of a dynamic API route as a function that accepts a URL parameter. The file app/api/posts/[slug]/route.ts acts like a function definition that receives slug as an argument. The value of this argument is determined by the specific URL segment provided in an incoming request, like /api/posts/hello-world.
HOW IT WORKS In the Next.js App Router, you create a folder with a name enclosed in brackets, like [id]. Inside this folder, you place your route.ts file which defines your API handlers (GET, POST, etc.). When a request comes in, for example to /api/users/123, Next.js maps the URL segment to a params object. The handler function in app/api/users/[id]/route.ts will receive an object like { params: { id: '123' } }. You can then access the ID within your code. This also supports catch-all segments ([...slug]) to match multiple path parts.
WHEN TO USE IT Use dynamic segments whenever you need an API endpoint to operate on a specific, but variable, resource identifier in the URL. This is the standard pattern for building RESTful APIs for CRUD (Create, Read, Update, Delete) operations, such as fetching a specific user by ID, updating a product by its SKU, or deleting a comment by its unique key.
WHEN NOT TO USE IT Avoid dynamic segments for static, known routes like /api/health or /api/auth/login. For these, a standard, non-dynamic route.ts file in a folder with that name is clearer and more direct. Overusing catch-all segments can also make routing logic complex and hard to debug; prefer specific dynamic segments when possible.
ONE CANONICAL EXAMPLE A blog's API needs to fetch individual posts. You would create a file at app/api/posts/[slug]/route.ts. Inside this file, a GET function would receive the request and a context object containing params. You'd extract the slug via params.slug, query your database for the post with that slug, and return it as a JSON response. A request to /api/posts/my-first-post would result in params.slug being the string "my-first-post".
Read the original → nextjs.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.