Skip to main content

How to Build Your First REST API, Step by Step

A step-by-step guide to building a small REST API with Node.js and Express, from one route to adding, reading, changing and deleting records, with the status codes and tests that go with it.

Niraj KafleSaarathi Academy
8 min read
Building a first REST API step by step with Node.js, Express and Postman

To build your first REST API, install Node.js, create a project with Express and write one route for each thing a user can do with a single resource, such as books: list them, get one, add one, change one and delete one. Each route takes and returns JSON and answers with the right status code. Test every route with curl or Postman as you write it. With the code below you can have a working API running on your laptop in one sitting, and the rest of this guide shows what to learn after that.

An API (application programming interface) is how one program asks another for data. When a mobile app shows your bank balance, it asks the bank's API, and the API answers in JSON. If you are not sure what backend work involves, read what a backend developer does first. We use Node.js here, but the same steps work in Django or Laravel. Our post on Node.js, Django or Laravel helps you pick one.

What makes an API a REST API?

REST is a set of habits for designing web APIs. Three of them matter on day one:

  • Each thing your API manages is a resource with its own URL. All books live at /books, and the book with ID 2 lives at /books/2.
  • The HTTP method says what to do with it. GET reads, POST creates, PUT replaces, PATCH changes part of a record and DELETE removes it.
  • Each request carries everything the server needs. The server doesn't remember your earlier requests, which is what people mean when they call REST stateless.

Put together, five routes cover a whole resource:

  • GET /books lists all books.
  • GET /books/2 gets one book.
  • POST /books adds a book.
  • PUT /books/2 replaces book 2.
  • DELETE /books/2 deletes book 2.

Step 1: Install Node.js and set up the project

Download the LTS version of Node.js from nodejs.org. LTS stands for long-term support, and it is the version most companies run. Then open a terminal and check that it installed:

node -v
npm -v

Both should print a version number. Next, make a folder for the project and install Express, a small and popular web framework for Node.js:

mkdir books-api
cd books-api
npm init -y
npm install express

npm init -y creates a package.json file that keeps track of your project's packages. npm install express downloads Express into a node_modules folder. If you use Git, add node_modules to your .gitignore file.

Step 2: Start a server that answers one request

Create a file called server.js in the project folder:

const express = require('express');

const app = express();
app.use(express.json());

app.get('/', (req, res) => {
  res.json({ message: 'Hello from my first API' });
});

app.listen(3000, () => {
  console.log('API running on http://localhost:3000');
});

Start it with:

node --watch server.js

Open http://localhost:3000 in your browser and you will see the message as JSON. The --watch flag restarts the server each time you save the file, so leave it running while you work. The line app.use(express.json()) tells Express to read JSON that a client sends in the request body. The POST and PUT routes later need it.

Step 3: Add some data to work with

A real API reads from a database. To keep the first version simple, keep the books in an array in memory. Add this below app.use(express.json());:

const books = [
  { id: 1, title: 'Muna Madan', author: 'Laxmi Prasad Devkota' },
  { id: 2, title: 'Palpasa Cafe', author: 'Narayan Wagle' },
];
let nextId = 3;

Each time the server restarts, the array goes back to these two books. That is fine while you learn, and a database fixes it later.

Step 4: Write the routes that read books

Put every route from here on above the app.listen line.

app.get('/books', (req, res) => {
  res.json(books);
});

app.get('/books/:id', (req, res) => {
  const book = books.find((b) => b.id === Number(req.params.id));
  if (!book) {
    return res.status(404).json({ error: 'Book not found' });
  }
  res.json(book);
});

The :id in the path is a route parameter. For /books/2, Express puts '2' in req.params.id. It arrives as text, so Number() turns it into a number before the comparison. If no book matches, the API says so with a 404 status instead of sending back an empty answer.

Step 5: Add, change and delete books

app.post('/books', (req, res) => {
  const { title, author } = req.body ?? {};
  if (!title || !author) {
    return res.status(400).json({ error: 'title and author are required' });
  }
  const book = { id: nextId++, title, author };
  books.push(book);
  res.status(201).json(book);
});

app.put('/books/:id', (req, res) => {
  const book = books.find((b) => b.id === Number(req.params.id));
  if (!book) {
    return res.status(404).json({ error: 'Book not found' });
  }
  const { title, author } = req.body ?? {};
  if (!title || !author) {
    return res.status(400).json({ error: 'title and author are required' });
  }
  book.title = title;
  book.author = author;
  res.json(book);
});

app.delete('/books/:id', (req, res) => {
  const index = books.findIndex((b) => b.id === Number(req.params.id));
  if (index === -1) {
    return res.status(404).json({ error: 'Book not found' });
  }
  books.splice(index, 1);
  res.status(204).end();
});

The POST and PUT routes check the input before they save anything, and answer 400 if a field is missing. A client can send anything, including nothing at all. In Express 5, req.body is empty when a request has no JSON body, and ?? {} stops that from crashing the route.

A successful POST answers 201, which means a record was created, and sends back the new book with its ID. A successful DELETE answers 204, which means it worked and there is nothing to send back.

Step 6: Test every route

The browser's address bar can only send GET requests, so use curl, which comes with macOS, Linux and recent versions of Windows. Run these in a second terminal while the server is running:

curl http://localhost:3000/books

curl -X POST http://localhost:3000/books \
  -H "Content-Type: application/json" \
  -d '{"title": "Seto Dharti", "author": "Amar Neupane"}'

curl -X PUT http://localhost:3000/books/1 \
  -H "Content-Type: application/json" \
  -d '{"title": "Muna Madan", "author": "L. P. Devkota"}'

curl -i -X DELETE http://localhost:3000/books/2

curl -i http://localhost:3000/books/99

The -i flag prints the status code, so you can see the 204 and the 404 for yourself. Try a POST with the author left out and check that you get a 400. On Windows, run these commands in Git Bash, which installs with Git, because PowerShell treats the quotes and line breaks differently. If you would rather click than type, Postman sends the same requests from a window and saves them in a collection you can run again.

Which status codes should a beginner know?

  • 200 OK: the request worked and the answer is in the body.
  • 201 Created: a new record was made.
  • 204 No Content: it worked and there is nothing to send back.
  • 400 Bad Request: the client sent something wrong, like a missing field.
  • 401 Unauthorized: the client hasn't logged in.
  • 403 Forbidden: the client is logged in but isn't allowed to do this.
  • 404 Not Found: there is no such record or route.
  • 500 Internal Server Error: something broke on the server, which means a bug in your code.

The app on the other end decides what to do from the status code. A mobile app that gets a 401 can send the user to the login screen. One that gets a 200 with an error message tucked inside the body will carry on as if everything worked.

Mistakes to avoid in your first API

  • Verbs in URLs, like /getBooks or /deleteBook/2. The HTTP method already says the action, so use GET /books and DELETE /books/2.
  • Answering 200 to everything, errors included.
  • Skipping input checks. A missing field should get a clear 400, not a crash or a half-saved record.
  • A different error shape on every route. Pick one, such as { "error": "..." }, and use it everywhere.
  • Passwords or API keys written into the code. Read them from environment variables kept in a .env file, and keep that file out of GitHub.

What to learn after your first API

  1. A real database. Swap the array for PostgreSQL so your data survives a restart. Learn basic SQL first, then a tool like Prisma.
  2. Proper validation. A library like Zod checks types and formats, not only whether a field exists. Right now this API would accept a number as a title.
  3. Login and permissions. Store passwords hashed with bcrypt, give users a token when they log in, and check that a user can only change their own records.
  4. Structure. Split routes, business logic and database code into separate files before the project grows.
  5. Documentation. An OpenAPI file, often shown with Swagger, describes every route so a frontend developer knows what to send.
  6. Deployment. Package the API with Docker and put it on a server so other people can use it.

AI coding tools can write routes like these in seconds. They also skip input checks, forget to check who owns a record and sometimes suggest packages that don't exist. Read every line they give you, and test each route yourself before you trust it.

How our Backend Engineering course builds on this

Our Backend Engineering course runs 10 weeks, 2 hours a day, 5 days a week, in our Old Baneshwor classroom and online. It starts where this post starts and goes much further:

  • Week 1 covers how the web works: DNS, HTTPS, HTTP methods, status codes and headers checked with curl, and REST compared with GraphQL and gRPC. It also covers the Linux terminal and Git.
  • Weeks 2 and 3 cover JavaScript, async code and TypeScript. Week 3 ends with your first HTTP server, built on Node's own http module before any framework.
  • Week 4 is Express in TypeScript: routers, middleware, validation with Zod, one consistent error format, pagination, logging and a Postman collection. It ends with a checklist for reviewing routes written with AI.
  • Weeks 5 to 7 move to NestJS and databases.

Later weeks add security, queues, a system design week, then Docker and CI/CD, and the course ends with a capstone project. The full week-by-week plan and the syllabus PDF are on the course page.

Frequently asked questions

What is a REST API in simple words?

It is a way for one program to ask another for data over the web. Each kind of data has its own URL, like /books, and the HTTP method says what to do: GET to read, POST to add, PUT or PATCH to change and DELETE to remove. The answer usually comes back as JSON.

Which language is best for a first REST API?

Any mainstream backend language works. Node.js with Express, Python with Django and PHP with Laravel all show up in Nepali job ads. Pick one and finish a small project in it. Our post on Node.js, Django or Laravel compares them.

Do I need a database to build a REST API?

Not for your first one. An array in memory is enough to learn routes, JSON and status codes. Any real API needs a database such as PostgreSQL, because data in memory is lost every time the server restarts.

How do I test a REST API without a frontend?

Use curl in the terminal or Postman. Both let you send GET, POST, PUT and DELETE requests with a JSON body and see the status code and the reply. Week 4 of our Backend Engineering course includes building a Postman collection.

See what the syllabus actually covers.

Every week is published up front. Ten students a batch. Mentors who still do the job.

Course for this topic: Full Stack Development with Vibe Coding

Also see: Software Quality Assurance and Backend Engineering