Introduction

Next.js enables you to define Route Handlers in the app/api/ directory. These handlers run on the server and allow you to implement backend logic such as RESTful APIs, database access, webhooks, and cross-platform communication (e.g. mobile apps).

In the App Router, prefer using Server Components for server-side logic. Use Route Handlers only when a public HTTP endpoint is required.

Pros: Accessible from any frontend; aligns with traditional API design

Cons: API paths (/api/...) are exposed to the client, requiring authentication and CORS handling

Creating Route Handlers

Each Route Handler lives in its own folder under app/api/, with logic placed in a route.ts file. Supports all HTTP methods: GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD

Basic Example

// app/api/hello/route.ts
export async function GET() {
  return new Response(JSON.stringify({ message: "Hello World" }), {
    headers: { "Content-Type": "application/json" },
  });
}

export async function POST(req: Request) {
  const body = await req.json();
  return new Response(JSON.stringify({ received: body }), {
    headers: { "Content-Type": "application/json" },
  });
}

Calling Route Handlers from the Frontend

Use fetch inside client or server components

GET request

const fetchData = async () => {
  const res = await fetch("/api/hello");
  const data = await res.json();
  console.log(data);
};

POST request

const sendData = async () => {
  const res = await fetch("/api/user", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name: "Alice" }),
  });
  const data = await res.json();
  console.log(data);
};

Middleware and Authentication

Protect handlers using headers, cookies, or tokens

// app/api/protected/route.ts
import { NextRequest, NextResponse } from "next/server";

export async function GET(req: NextRequest) {
  const token = req.headers.get("Authorization");
  if (token !== "Bearer mysecrettoken") {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  return NextResponse.json({ message: "Authenticated" });
}

Using with Databases

Connect to any database (PostgreSQL, MySQL, MongoDB, etc.)