Next.js Route Handlers

Build custom HTTP endpoints in the App Router using Web Request and Response APIs

Overview

Route Handlers define API endpoints inside the App Router using a route.ts file. They export functions named after HTTP methods (GET, POST, etc.) and use the standard Web Request and Response objects. Use them for webhooks, third-party integrations, or JSON APIs consumed by clients.

Syntax / Usage

Create app/api/<name>/route.ts and export one function per HTTP method. Handlers receive a Request and can read params from the second argument.

// app/api/posts/route.ts
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
  const query = request.nextUrl.searchParams.get('q')
  const posts = await db.post.findMany({ where: { title: { contains: query } } })
  return NextResponse.json(posts)
}

export async function POST(request: NextRequest) {
  const body = await request.json()
  const post = await db.post.create({ data: body })
  return NextResponse.json(post, { status: 201 })
}

Examples

Read a dynamic segment via the typed params promise:

// app/api/posts/[id]/route.ts
export async function GET(
  _request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params
  const post = await db.post.findUnique({ where: { id } })
  if (!post) return new Response('Not found', { status: 404 })
  return Response.json(post)
}

Control caching — handlers are dynamic by default; opt into static caching:

// app/api/config/route.ts
export const dynamic = 'force-static'

export async function GET() {
  return Response.json({ theme: 'dark' })
}

Common Mistakes

  • Defining a Route Handler and a page.tsx in the same segment folder (conflict)
  • Forgetting to await request.json() before reading the body
  • Assuming GET handlers are always cached — they are dynamic when reading request data
  • Returning a plain object instead of a Response/NextResponse
  • Not awaiting the params promise in newer App Router versions

See Also

nextjs-server-actions api-routes nextjs-caching