Next.js lets you build server-side endpoints without spinning up a separate backend service. With the App Router introduced in Next.js 13, frontend and backend code live together, and `app/api` provides a convenient place to define your APIs. You can define RESTful endpoints inside this directory and consume them from your pages or components just like any other fetchable resource.

These handler functions are known as API Routes and are a core part of full stack development in Next.js.

What you can do with API Routes

  • Define GET, POST, PUT, DELETE (and custom) endpoints using file-based routing.
  • Run server-side code, query databases or third-party services from the same repo.
  • Build full-stack features such as authentication, form handling, and webhooks.
  • Deploy to serverless platforms with zero configuration—the routes scale automatically.
  • Keep frontend and backend logic together for easier maintenance and faster iteration.

Next.js makes full-stack development simple.


What are API Routes in Next.js?

API Routes in Next.js are server-side handler functions that let you define RESTful endpoints directly within your project. Routes live in the app/api directory (or pages/api in older versions) and run as serverless or edge functions depending on your configuration. The handlers receive standard web Request objects and can return Response objects, or use utility helpers such as NextResponse from next/server.

Endpoints are generated automatically based on the file structure. For instance, app/api/users/route.js becomes an API endpoint at /api/users, and nesting or dynamic segments create corresponding URL patterns.

HTTP methods supported in API Routes

You implement a handler for each method by exporting a function named after the verb (e.g. export async function GET(req){}).

  • GET: Retrieve data from the server.
  • POST: Send new data to the server.
  • PUT/PATCH: Update existing data.
  • DELETE: Remove data.

Create API Routes

API Routes should be created in the app/api directory of your Next.js project. Each file in this directory corresponds to an API endpoint.

For example, if you want to create an API endpoint for users, you can create a file at app/api/users/route.js. This file will define the logic for handling requests to the /api/users endpoint.

You can organize your API routes in subdirectories within the app/api directory to create a structured API. For example, you could have app/api/products/route.js for product-related endpoints and app/api/orders/route.js for order-related endpoints.

API Structure


app/
 ├ api/
 │   ├ users/
 │   │   ├ route.ts

API Endpoints

app/api/users

Basic API Route example

Here's a simple example of an API Route that handles GET and POST requests for a users endpoint.

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

export async function GET(request) {
    const cars = [
        { id: 1, name: "Swift" },
        { id: 2, name: "Baleno" },
        { id: 3, name: "Alto" }
    ];
    return NextResponse.json(cars);
}

Call API

Now let's call the API from a page or component. Use the standard fetch API — the endpoint lives under /api/*. If you're calling it from a client component add the "use client" directive at the top; in server components you can call it directly since everything runs on the server.

// app/page.js (client component)
'use client';

import { useEffect } from 'react';
import { useState } from 'react';

export default function Page() {
  const [cars,setCars]=useState([]);

  useEffect(() => {
    async function fetchCars() {
      const res = await fetch('/api/cars');
      const data = await res.json();
      setCars(data);
    }
    fetchCars();
  }, []);

  return <div>Open the browser console to see the car list</div>;
}


POST API

Here's an example of a POST API Route that allows you to add a new user to the list of users. The post API route is defined in app/api/users/route.js.

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

export async function POST(request) {
    try {
        const body = await request.json();
        console.log(body);
        return NextResponse.json({ message: "User added successfully" });
    } catch (err) {
        return NextResponse.json({ error: "Invalid request" }, { status: 400 });
    }
}

To call this POST API, you can use the fetch API in a client component. Here's an example of how to call the POST API from a client component:

 // app/page.js
'use client'; 
async function addUser() {
    const res = await fetch('/api/users', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ name: 'New User' })
    });
    const data = await res.json();
    console.log(data);
}

Dynamic API Routes

Next.js allows you to create dynamic API routes using file naming conventions. For example, if you want to create an API route for a specific user ID, you can create a file like app/api/users/[id]/route.js.

// app/api/users/[id]/route.js
import { NextResponse } from 'next/server';

export async function GET(request, { params }) {
    const { id } = await params;
    console.log(id);
    return NextResponse.json({ message: `User with ID ${id} retrieved successfully` });
}

In this example, the API route will match any request to /api/users/{id}, where {id} is a dynamic segment. Inside your handler you receive a second argument containing the route params object (e.g. export async function GET(req, { params })) or you can parse it from new URL(req.url). Then read params.id to get the value.


API Route Query Parameters

You can send query string parameters like ?name=John. In a route handler you can read them from the URL: const { searchParams } = new URL(request.url); const name = searchParams.get('name');.

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

export async function GET(request) {
    const { searchParams } = new URL(request.url);
    const name = searchParams.get('name');
    console.log(name);
    return NextResponse.json({ message: `User with name ${name} retrieved successfully` });
}

API Routes Error Handling

When working with API routes, it's important to handle errors gracefully. You can use try-catch blocks to handle errors in your API route handlers.

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

export async function GET(request) {
    try {
        const { searchParams } = new URL(request.url);
        const name = searchParams.get('name');
        console.log(name);
        return NextResponse.json({ message: `User with name ${name} retrieved successfully` });
    } catch (error) {
        console.error(error);
        return NextResponse.json({ message: "Error retrieving user" }, { status: 500 });
    }
}

FAQs

Here are some frequently asked questions about API routes in Next.js.

Can I use API routes for server-side rendering?

A: API routes are designed for request/response logic and do not generate HTML. In the App Router you leverage server components or plain fetch calls in pages to handle SSR. In the older Pages Router, data‑fetching helpers such as getServerSideProps and getStaticProps run on the server but are completely separate from API routes.