Route handlers are how Next.js exposes plain HTTP endpoints in the App Router. A route.ts file inside the app directory exports functions named after HTTP methods, and the framework turns that file into a URL that any client can call.
Where a page renders UI, a route handler returns a raw response such as JSON, text, or a redirect. Here is the smallest handler, which answers GET requests on /api/health and returns JSON.
// app/api/health/route.ts
export async function GET() {
return Response.json({ status: 'ok' })
}Visiting /api/health returns a JSON object with status ok. The function name GET is the HTTP method, and the folder path app/api/health becomes the URL.
Where the file must live
The route file has to sit inside the app directory, and its folder path is the endpoint path. A file at app/api/posts/route.ts answers requests on /api/posts, while app/dashboard/settings/route.ts answers /dashboard/settings.
The file name is always route.js or route.ts. Next.js treats the file as a route convention, not as UI, so it never renders. If a route.ts and a page.tsx exist in the same folder, Next.js reports a route conflict, so keep one endpoint type per folder.
HTTP methods are exported functions
Each HTTP method you want to support is a named export. Add one function per method, and each function receives the incoming request as its first argument.
// app/api/posts/route.ts
export async function GET(request: Request) {
return Response.json({ posts: [] })
}
export async function POST(request: Request) {
const body = await request.json()
return Response.json({ created: true, ...body })
}A GET request to /api/posts runs the GET export, and a POST request runs the POST export. A method without a matching export returns 405 Method Not Allowed.
Next.js supports GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. When you do not define OPTIONS, Next.js generates it and sets the Allow header from the methods you exported.
| Method | Typical use in a handler |
|---|---|
| GET | Read a resource or list |
| POST | Create a resource or accept a webhook |
| PUT and PATCH | Update a resource |
| DELETE | Remove a resource |
PUT and PATCH are both update methods, but the difference is your API contract, not Next.js. The router only sends the method to its matching function.
Reading the request and route params
The first argument is a Request, or a NextRequest when you import the type from next/server. NextRequest adds cookie helpers and a parsed nextUrl object with searchParams. See NextRequest and NextResponse for those helpers.
Dynamic route segments arrive through a context object whose params field is a Promise, so it must be awaited.
// app/posts/[id]/route.ts
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params
return Response.json({ id })
}A request to /posts/42 returns a JSON object with id 42. Route params became asynchronous in Next.js 15, and Next.js 16 fully removed synchronous access, so await the Promise before reading id. See handling GET, POST, PUT, PATCH, and DELETE for the full method map.
When to use a route handler
Use a route handler when a client outside your app needs a stable URL, such as a webhook receiver or a public API. For example, a payment provider calls back at /api/webhooks/payments, which you implement as a route handler because the provider needs a URL outside your app.
If the caller is your own form or button, a Server Action is usually simpler because it has no URL to manage. See Server Actions vs API Routes vs Route Handlers to choose between them.
Common mistakes
The first mistake is exporting a lowercase function name such as get. Method names are case sensitive, and Next.js only recognizes the uppercase names, so a lowercase export is ignored.
The second is assuming the file name shows up in the URL. A file at app/api/route.ts serves /api, not /api/route, because the folder path is the endpoint and the file name is just the convention.
Also note that layouts and pages in the same folder do not wrap a route handler, because the handler returns a raw response instead of rendering.
Rune AI
Key Insights
- A route.js file exports functions named after HTTP methods like GET and POST.
- The file path under app becomes the endpoint URL.
- Each handler receives a Request and an optional context with awaited params.
- Next.js auto-generates OPTIONS when you do not define it.
- Route Handlers use the Web Request and Response APIs, not the Pages Router pair.
Frequently Asked Questions
Do Route Handlers replace pages?
Which HTTP methods can a route handler export?
Are route handlers the same as API Routes?
Conclusion
A route.js file is how the App Router exposes an API endpoint. Place it inside app, export functions named after HTTP methods, and return a Web Response. The folder path becomes the URL, while the request and route context provide the incoming data.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.