Route Handlers are the App Router's way of building backend API endpoints, defined in files named route.ts. This lesson covers creating handlers for different HTTP methods and working with the standard Request/Response Web APIs.
route.ts Files Define API Endpoints
A file named exactly route.ts inside any folder in app/ becomes an API endpoint, reachable at that folder's URL path. Unlike page.tsx, which exports one default component, route.ts exports a named function per HTTP method it supports — GET, POST, PUT, DELETE, and so on.
Route Handlers use the standard Web Request and Response objects (the same ones available in browsers and other modern JavaScript runtimes) instead of the Node.js-specific req/res objects used by Pages Router API Routes.
GET /api/posts returns the post list; POST /api/posts creates a new one — both live in the same file, as separate exported functions.
Supported Method Exports
export async function GET(request: Request) { /* ... */ }
export async function POST(request: Request) { /* ... */ }
export async function PUT(request: Request) { /* ... */ }
export async function PATCH(request: Request) { /* ... */ }
export async function DELETE(request: Request) { /* ... */ }
A route.ts file only needs to export the methods it actually supports.
Requesting an unsupported method automatically returns a 405 response from Next.js.
Response.json(data, options) is the standard way to return a JSON response.
A route folder cannot contain both a page.tsx and a route.ts at the same segment — pick one.
Route Handlers Cheat Sheet
Common tasks when building Route Handlers.
Task
Code
Read JSON body
await request.json()
Read query params
new URL(request.url).searchParams
Return JSON
Response.json(data)
Return an error status
Response.json({ error }, { status: 400 })
Read dynamic segment
GET(request, { params })
Dynamic Segments in Route Handlers
Route Handlers support the same [param] dynamic segment syntax as pages. The captured value is delivered as the second argument to your handler function, inside a params object.
By default, GET Route Handlers with no dynamic behavior can be cached similarly to statically rendered pages. Using dynamic APIs like cookies(), reading the request's URL search params, or exporting export const dynamic = "force-dynamic" opts a handler out of caching, just like a page.
Common Mistakes
Naming the file Route.ts or routes.ts instead of the exact required name route.ts.
Trying to have both a page.tsx and a route.ts in the same folder for the same path.
Using Node.js-style req.body instead of the Web-standard await request.json().
Forgetting to return a Response object — returning plain data instead causes a build error.
Key Takeaways
route.ts files define API endpoints in the App Router, one named export per HTTP method.
They use the standard Web Request/Response objects, not Node.js-style req/res.
Dynamic segments work the same as pages, with params passed as the handler's second argument.
A folder can have a page.tsx or a route.ts, but not both, for the same path.
Route Handlers can be cached like static content unless they use dynamic, request-specific APIs.
Pro Tip
Reach for a Route Handler specifically when you need an endpoint consumed by something other than your own Server Components — a public API, a webhook receiver, or a client-side fetch call — since Server Components can usually just call your data layer directly without needing an HTTP round-trip at all.
You now know how to build API endpoints with Route Handlers. Next, learn how Middleware lets you intercept and modify requests before they reach your routes.