Home Quizzes Leaderboard Competitions Learn Hire Us
About Contact
Log In Sign Up
Learn Next.js API Routes & Route Handlers

API Routes & Route Handlers

⏱ 15 min read read
Route Handlers (App Router):

Create API endpoints by adding a route.ts file in the app/ directory.
Export named functions for each HTTP method.

// app/api/users/route.ts

import { NextRequest, NextResponse } from 'next/server';

// GET /api/users

export async function GET() {

const users = [{ id: 1, name: 'Alice' }];

return NextResponse.json(users);

}

// POST /api/users

export async function POST(request: NextRequest) {

const body = await request.json();

// validate, save to DB...

return NextResponse.json({ id: 2, ...body }, { status: 201 });

}

Dynamic Route Handlers:

// app/api/users/[id]/route.ts

export async function GET(

request: NextRequest,

{ params }: { params: { id: string } }

) {

const user = await getUserById(params.id);

if (!user) {

return NextResponse.json({ error: 'Not found' }, { status: 404 });

}

return NextResponse.json(user);

}

Request Helpers:

const body = await request.json(); // parse JSON body

const params = request.nextUrl.searchParams; // query string

const name = params.get('name'); // ?name=Alice

const headers = request.headers.get('authorization');

const cookies = request.cookies.get('token');

Response Helpers:

NextResponse.json(data) // 200 JSON

NextResponse.json(data, { status: 201 }) // custom status

NextResponse.json({ error: 'msg' }, { status: 400 })

NextResponse.redirect(new URL('/login', req.url)) // redirect

new NextResponse(null, { status: 204 }) // no content

Supported HTTP methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.

Route Handlers replace the old pages/api/ directory.

They run on the Edge or Node.js runtime --- configurable per route.

export const runtime = 'edge'; --- runs on Vercel Edge Network.
Code Example
// app/api/students/route.ts --- full CRUD API

import { NextRequest, NextResponse } from 'next/server';

// In-memory store (replace with DB in real app)

let students = [

{ id: 1, name: 'Alice', grade: 92 },

{ id: 2, name: 'Bob', grade: 78 },

];

// GET /api/students

export async function GET(request: NextRequest) {

const search = request.nextUrl.searchParams.get('name');

const result = search

? students.filter(s =>
s.name.toLowerCase().includes(search.toLowerCase()))

: students;

return NextResponse.json(result);

}

// POST /api/students

export async function POST(request: NextRequest) {

const body = await request.json();

if (!body.name || typeof body.grade !== 'number') {

return NextResponse.json(

{ error: 'name and grade are required' },

{ status: 400 }

);

}

const newStudent = { id: Date.now(), name: body.name, grade:
body.grade };

students.push(newStudent);

return NextResponse.json(newStudent, { status: 201 });

}

// app/api/students/[id]/route.ts

// GET /api/students/1

export async function GET(

\_req: NextRequest,

{ params }: { params: { id: string } }

) {

const student = students.find(s => s.id === Number(params.id));

if (!student) return NextResponse.json({ error: 'Not found' }, {
status: 404 });

return NextResponse.json(student);

}

// DELETE /api/students/1

export async function DELETE(

\_req: NextRequest,

{ params }: { params: { id: string } }

) {

const idx = students.findIndex(s => s.id === Number(params.id));

if (idx === -1) return NextResponse.json({ error: 'Not found' }, {
status: 404 });

students.splice(idx, 1);

return new NextResponse(null, { status: 204 });

}
← Data Fetching Styling --- CSS Modules, Tailwind & Glob →

Log in to track your progress and earn badges as you complete lessons.

Log In to Track Progress