← All lessons
Lesson 14 · Advanced

Route Handlers (API Routes)

Build real HTTP endpoints inside the app folder. Useful for webhooks, third-party clients and anything that isn't a UI.

Server actions cover most internal mutations, but sometimes you genuinely need an HTTP endpoint — for webhooks, third-party callers, or non-React clients. Route handlers are that.

Where they live

Create a route.js file in any folder under app/ (instead of page.js). The folder's path becomes the URL.

app/api/hello/route.js   → GET/POST/etc to /api/hello
app/webhooks/stripe/route.js → /webhooks/stripe

Exporting HTTP methods

Export a function for each HTTP method you want to handle. They receive a Web Request and return a Web Response:

// app/api/hello/route.js
export async function GET() {
  return Response.json({ message: "Hello" });
}

export async function POST(request) {
  const body = await request.json();
  return Response.json({ echoed: body }, { status: 201 });
}

Reading query params and dynamic segments

// app/api/items/[id]/route.js
export async function GET(request, { params }) {
  const { id } = await params;
  const url = new URL(request.url);
  const fields = url.searchParams.get("fields");
  return Response.json({ id, fields });
}

Caching behavior

By default, GET route handlers are not cached in Next.js 16 — you opt in. The same dynamic/revalidate exports from lesson 12 work here too:

// app/api/posts/route.js
export const revalidate = 60;

export async function GET() {
  const posts = await db.post.findMany();
  return Response.json(posts);
}

POST, PUT, PATCH, DELETE are always dynamic — they perform side effects, so caching wouldn't make sense.

Route handler vs. server action

  • Use a **server action** for internal form submissions and mutations from your own UI.
  • Use a **route handler** for everything that needs a stable, public HTTP contract.
  • Both run on the server. Both can hit your database. Pick the one that fits the caller.
Note: Route handlers return standard Web Response objects. That means streaming, redirects, cookies and binary responses all work using the standard Web API.

Try it

Turn this Express-style handler into a Next.js route handler at `app/api/echo/route.js`.

Need a hint?

Export a function named after the HTTP method. Read the body with `await request.json()`.

Quiz

Pick the best answer. You only get one shot per question.

1. Which file makes a folder under `app/` an HTTP endpoint instead of a UI page?

2. Are GET route handlers cached by default in Next.js 16?

3. You need to expose a webhook to a third-party service. Which is the right tool?