API Routes and Server ActionsLesson 3.5
How to structure Next.js API routes for REST endpoints
REST conventions in App Router, dynamic route handlers, CORS headers, error handling patterns, HTTP status codes, route handler middleware patterns
RESTful Route Handler Structure
For a full CRUD REST API, use two route files:
app/api/posts/
route.ts ← GET (list) + POST (create)
[id]/
route.ts ← GET (single) + PATCH + DELETE// app/api/posts/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server'
export async function GET(
_req: NextRequest,
{ params }: { params: { id: string } }
) {
const post = await db.post.findUnique({ where: { id: params.id } })
if (!post) return NextResponse.json({ error: 'Not found' }, { status: 404 })
return NextResponse.json(post)
}
export async function DELETE(
_req: NextRequest,
{ params }: { params: { id: string } }
) {
await db.post.delete({ where: { id: params.id } })
return new NextResponse(null, { status: 204 })
}Adding CORS Headers
export async function OPTIONS() {
return new NextResponse(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
})
}The second argument to route handler functions provides params for dynamic segments. This is different from page components where params comes via the first argument props. Return 204 No Content for successful deletes with no body.
