How To Use API Route Handlers in Next.js 13+ (App Router)

The latest Next.js update introduces an innovative directory structure called the app router. This not only brings a fresh organizational approach but also introduces a revamped method for handling API routes. Termed “Route Handlers,” (previously “API Routes” as used in the pages directory) within the app router, these handlers offer a new way to expose endpoints to your API. Let’s delve into the nuances and explore the changes.

Directory Structure

Just like the previous “pages” directory structure, the new Route Handlers reside in a directory named “API” under the higher-level “app” directory. However, there’s a notable difference. Each Route Handler file is now named route.ts, and the URL slug for accessing a specific handler is determined by the containing directory. For instance:

|  |--layout.tsx
|  |--page.tsx
|  |--api/
|  |  |--route.ts
|  |  |  |users/
|  |  |  |--route.ts

In this example, the “users” route handler can be accessed at /api/users, while the upper-level route can be reached at /api. Also, dynamic routing should involve naming the directory with the dynamic slug, not the file itself. Read more on that here.

Ensure each route handler is located within the “API” directory. Placing page.tsx and route.ts files in the same directory will result in an error.

Route Handler Syntax

Inside each route.ts file is where you handle incoming requests. In the app directory, Next.js exposes each HTTP request type (e.g., “GET”, “POST”) as separate handler functions. This is a departure from the pages directory, where each API Route had only one handler function that managed all types of requests. An example of a route handler in the app directory looks like this:


import { NextRequest, NextResponse } from "next/server";

export async function GET(request: NextRequest) {
  const requestUrl = request.url;

  return NextResponse.json({
    message: "Hello from the API",
    request: requestUrl,

export async function HEAD(request: NextRequest) {}

export async function POST(request: NextRequest) {}

export async function PUT(request: NextRequest) {}

export async function DELETE(request: NextRequest) {}

export async function PATCH(request: NextRequest) {}

// If `OPTIONS` is not defined, Next.js will automatically implement `OPTIONS` and  set the appropriate Response `Allow` header depending on the other methods defined in the route handler.
export async function OPTIONS(request: NextRequest) {}

This new syntax empowers you to manage different HTTP requests separately, eliminating the need for intricate if/switch statements within a single handler function.

Embracing API Route Handlers

Embracing API Route Handlers in your Next.js app using the app router is a significant step forward. To ensure the effectiveness of your route handlers, consider using a robust API testing engine. If you’re a VSCode user, the Postman extension is a great choice, allowing you to select the exact HTTP request type for testing. Happy coding!


Join the conversation

Your email address will not be published. Required fields are marked *