Next.js enables you to create API routes inside the app/api/
directory. These endpoints run on the server, allowing you to implement backend logic within your Next.js app. API routes serve as backend interfaces defined in app/api/.../route.ts
and are ideal for implementing RESTful APIs, handling webhooks, or serving cross-platform clients (e.g., mobile).
Pros: Accessible by various frontends and adhere to traditional API design.
Cons: The API path (e.g., /api/...
) is exposed to the client, which may require extra authentication or CORS handling.
Sometimes you need a public endpoint for external services or multiple frontends; API routes in Next.js (App Router) address this need.
Each API route is placed in its own folder under app/api/
, with the endpoint code defined in a route.ts
file.
// app/api/hello/route.ts
export async function GET() {
const data = { message: "Hello World" };
return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" },
});
}
export async function POST(req: Request) {
const body = await req.json();
// Process 'body' here
return new Response(JSON.stringify({ received: body }), {
headers: { "Content-Type": "application/json" },
});
}
Call these endpoints from client components using the native fetch
API. For example:
"use client";
export default function TestApi() {
async function getData() {
const response = await fetch("/api/hello");
const data = await response.json();
console.log(data);
}
return (
<button onClick={getData}>
Call API
</button>
);
}
Use fetch
within any client (or even server) component to interact with your API routes.
const fetchData = async () => {
const res = await fetch("/api/hello");
const data = await res.json();
console.log(data);
};
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);
};
You can protect API routes by checking headers, cookies, or tokens before returning a response.
// app/api/protected/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function GET(req: NextRequest) {
const authHeader = req.headers.get("Authorization");
if (!authHeader || authHeader !== "Bearer mysecrettoken") {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
return NextResponse.json({ message: "Authenticated" });
}