Dynamic API Routes

What are Dynamic API Routes

Just like dynamic routes in pages, you can also create dynamic API routes.

The API route pages/api/post/[pid].js will have the following code:

export default function handler(req, res) {
  const { pid } = req.queryres.end(`Post: ${pid}`)
}

A request to /api/post/abc will respond with the text Post: abc.

Index Routes and Dynamic API Routes

Common pattern for setting up routes

  • GET api/posts

    • Gets a list of posts and is probably paginated.

  • GET api/posts/12345.

    • Gets post id 12345

Two Ways to model this

Option One
  • /api/posts.js

  • /api/posts/[postId].js

Option Two
  • /api/posts/index.js

  • /api/posts/[postId].js

Both options are allowed. You can not only use /api/posts/[postId].js because Dynamic Routes do not have an undefined state so GET api/posts will not match the above under any circumstance.

Catch all API Routes

Just as with 'regular' dynamic routes, you can also extend API Routes in to catching all the paths by adding three dots in the brackets.

  • pages/api/post/[...slug].js

    • Will match /api/post/a.

    • But will also match /api/post/a/b.

When you use a matched parameter, it will be sent as a query parameter to the page and will turn it in to an array. The path /api/post/a will have the following query: { "slug": ["a"] }.

An API route could look like this if it was made for pages/api/post/[...slug].js:

export default function handler(req, res) {
  const { slug } = req.query
  res.end(`Post: ${slug.join(', ')}`)
}

If you request /api/post/a/b/c, it will respond with the following text: Post: a, b, c.

Optional Catch All API Routes

Again, the same as with 'regular' dynamic routes.

All routes can be made optional if you include the parameter in double brackets like [[...slug]].

  • pages/api/post/[[...slug]].js

    • will match /api/post

    • will match /api/post/

    • will match /api/post/a/b

    • etc.

The biggest difference is that because it is optional. the route without the parameter is also matched.

Caveats

  • Predefined API routes take precedence over dynamic API routes.

  • Dynamic API routes take precendence over catch all API routes.

    • This will lead to the following:

    • pages/api/post/create.js will match /api/post/create

    • pages/api/post/[pid].js will match /api/post/1, api/post/abc, etc.

      • but not /api/post/create.

    • pages/api/post/[...slug].js will match /api/post/1/2 and /api/post/a/b/c

      • but not /api/post/create and /api/post/abc.