stackademic

The leading education platform for anyone with an interest in software development.

Next.js API Routes

Build HTTP endpoints with Route Handlers in the App Router

Overview

Route Handlers define API endpoints in route.ts files. They export functions named after HTTP methods (GET, POST, etc.) and return Response objects or NextResponse.

Syntax / Usage

// app/api/users/route.ts
import { NextResponse } from 'next/server'

export async function GET() {
  const users = await db.users.findMany()
  return NextResponse.json(users)
}

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

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

Examples

Validate input with Zod:

import { z } from 'zod'

const schema = z.object({ email: z.string().email() })

export async function POST(request: Request) {
  const parsed = schema.safeParse(await request.json())
  if (!parsed.success) {
    return NextResponse.json(parsed.error.flatten(), { status: 400 })
  }
  // create user...
}

Set caching headers:

export async function GET() {
  return NextResponse.json(data, {
    headers: { 'Cache-Control': 'public, s-maxage=60' },
  })
}

Common Mistakes

  • Using Pages Router pages/api patterns in App Router projects
  • Returning plain objects instead of Response/NextResponse
  • Heavy work in Route Handlers without considering serverless timeouts
  • Exposing admin endpoints without auth checks

See Also

middleware server-components routing fetch-api