A route file allows you to create custom request handlers for a given route. The following HTTP methods are supported: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS.
TypeScript
route.ts
export async function GET(request: Request) {}export async function HEAD(request: Request) {}export async function POST(request: Request) {}export async function PUT(request: Request) {}export async function DELETE(request: Request) {}export async function PATCH(request: Request) {}// 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: Request) {}
The request object is a NextRequest object, which is an extension of the Web Request API. NextRequest gives you further control over the incoming request, including easily accessing cookies and an extended, parsed, URL object nextUrl.
TypeScript
route.ts
import type { NextRequest } from 'next/server'export async function GET(request: NextRequest) { const url = request.nextUrl}
You can type the Route Handler context using RouteContext to get strongly typed params from a route literal. RouteContext is a globally available helper.
app/users/[id]/route.ts
import type { NextRequest } from 'next/server'export async function GET(_req: NextRequest, ctx: RouteContext<'/users/[id]'>) { const { id } = await ctx.params return Response.json({ id })}
Good to know
Types are generated during next dev, next build or next typegen.
After type generation, the RouteContext helper is globally available. It doesn't need to be imported.
You can read or set cookies with cookies from next/headers.
TypeScript
route.ts
import { cookies } from 'next/headers'export async function GET(request: NextRequest) { const cookieStore = await cookies() const a = cookieStore.get('a') const b = cookieStore.set('b', '1') const c = cookieStore.delete('c')}
Alternatively, you can return a new Response using the Set-Cookie header.
TypeScript
app/api/route.ts
import { cookies } from 'next/headers'export async function GET(request: Request) { const cookieStore = await cookies() const token = cookieStore.get('token') return new Response('Hello, Next.js!', { status: 200, headers: { 'Set-Cookie': `token=${token.value}` }, })}
You can also use the underlying Web APIs to read cookies from the request (NextRequest):
TypeScript
app/api/route.ts
import { type NextRequest } from 'next/server'export async function GET(request: NextRequest) { const token = request.cookies.get('token')}
You can use generateStaticParams with dynamic Route Handlers to statically generate responses at build time for specified params, while handling other params dynamically at request time.
When using Cache Components, you can combine generateStaticParams with use cache to enable data caching for both prerendered and runtime params.
The request object passed to the Route Handler is a NextRequest instance, which includes some additional convenience methods, such as those for more easily handling query parameters.
TypeScript
app/api/search/route.ts
import { type NextRequest } from 'next/server'export function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams const query = searchParams.get('query') // query is "hello" for /api/search?query=hello}
Since formData data are all strings, you may want to use zod-form-data to validate the request and retrieve data in the format you prefer (e.g. number).