VOOZH about

URL: https://dev.to/onlyeugene/how-to-build-a-rest-api-with-nodejs-and-express-from-scratch-3hfa

⇱ How to Build a REST API with Node.js and Express from Scratch - DEV Community


Have you ever wondered how mobile apps and websites get their data? The answer is usually an API. In this tutorial, you will build a working REST API from scratch using Node.js and Express. By the end, you will have an API that can create, read, update, and delete data — the four core operations of any real-world application.

No prior API experience needed. If you know basic JavaScript, you are ready.


What You Will Build

A simple Books API that lets you:

  • Get a list of all books
  • Get a single book by ID
  • Add a new book
  • Update a book
  • Delete a book

Prerequisites

Before starting, make sure you have:

  • Node.js installed (version 14 or higher)
  • A code editor (VS Code recommended)
  • A terminal / command prompt
  • Postman or Thunder Client to test your API

Step 1: Set Up Your Project

Open your terminal and run these commands one by one:


# Create a new folder for your project
mkdir books-api

# Move into the folder
cd books-api

# Create a package.json file (just press Enter for all questions)
npm init -y

# Install Express
npm install express

Now create a file called index.js inside your books-api folder. This is where all your code will live.

Your folder structure should look like this:

books-api/
 index.js
 package.json
 node_modules/

Step 2: Create Your First Server

Open index.js and add this code:

// Import Express
const express = require('express');

// Create an Express app
const app = express();

// This line lets our API understand JSON data
app.use(express.json());

// Choose a port number for our server
const PORT = 3000;

// Start the server
app.listen(PORT, () => {
 console.log(`Server is running on http://localhost:${PORT}`);
});

What each line does:

  • require('express') — loads the Express library we installed
  • app.use(express.json()) — tells Express to read JSON from incoming requests
  • app.listen(PORT) — starts the server and listens for requests on port 3000

Run your server:

node index.js

You should see:

Server is running on http://localhost:3000

Your server is live. Now let's add data and routes.


Step 3: Add Some Sample Data

Since we are not using a database in this tutorial, we will store our books in an array. Add this to your index.js file, just below app.use(express.json()):

// Our "database" — a simple array of books
let books = [
 { id: 1, title: 'The Pragmatic Programmer', author: 'Andrew Hunt' },
 { id: 2, title: 'Clean Code', author: 'Robert C. Martin' },
 { id: 3, title: 'You Don\'t Know JS', author: 'Kyle Simpson' },
];

Think of this array as a temporary database. Every time the server restarts, data resets — but it is perfect for learning.


Step 4: GET All Books

This route returns every book in our list. Add this below your books array:

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

What is happening here:

  • app.get — we are setting up a GET route
  • '/books' — the URL path someone visits
  • req — the incoming request (what the user sends)
  • res — the response (what we send back)
  • res.json(books) — sends our books array as JSON

Test it: Open Postman, set the method to GET, and visit http://localhost:3000/books. You will see all three books.


Step 5: GET a Single Book

What if someone wants just one book? We use a URL parameter:

// GET /books/:id — returns one book by ID
app.get('/books/:id', (req, res) => {
 // Convert the id from text to a number
 const id = parseInt(req.params.id);

 // Find the book with that ID
 const book = books.find((b) => b.id === id);

 // If no book found, send a 404 error
 if (!book) {
 return res.status(404).json({ message: 'Book not found' });
 }

 // Send the book back
 res.json(book);
});

What is happening here:

  • :id in the URL is a placeholder — it captures whatever number the user types
  • req.params.id reads that number from the URL
  • parseInt converts it from a string to a number
  • .find() searches the array for a matching book
  • If nothing is found, we return a 404 status with a helpful message

Test it: GET http://localhost:3000/books/1 returns the first book. GET http://localhost:3000/books/99 returns "Book not found".


Step 6: POST — Add a New Book

Now let's allow adding a new book:

// POST /books — adds a new book
app.post('/books', (req, res) => {
 // Get the title and author from the request body
 const { title, author } = req.body;

 // Simple validation — make sure both fields exist
 if (!title || !author) {
 return res.status(400).json({ message: 'Title and author are required' });
 }

 // Create the new book with a unique ID
 const newBook = {
 id: books.length + 1,
 title: title,
 author: author,
 };

 // Add it to our array
 books.push(newBook);

 // Send back the new book with a 201 status (means "created")
 res.status(201).json(newBook);
});

Test it in Postman:

  • Method: POST
  • URL: http://localhost:3000/books
  • Body: raw → JSON
{"title":"Eloquent JavaScript","author":"Marijn Haverbeke"}

You will get back the new book with an ID of 4.


Step 7: PUT — Update a Book

What if someone made a typo in a book title? This route fixes it:

// PUT /books/:id — updates an existing book
app.put('/books/:id', (req, res) => {
 const id = parseInt(req.params.id);
 const { title, author } = req.body;

 // Find the position of the book in the array
 const index = books.findIndex((b) => b.id === id);

 // If book doesn't exist, return 404
 if (index === -1) {
 return res.status(404).json({ message: 'Book not found' });
 }

 // Update the book — keep the same ID, change title and author
 books[index] = { id, title, author };

 // Send back the updated book
 res.json(books[index]);
});

Test it in Postman:

  • Method: PUT
  • URL: http://localhost:3000/books/1
  • Body:
{"title":"The Pragmatic Programmer (20th Anniversary Edition)","author":"Andrew Hunt"}

Step 8: DELETE — Remove a Book

Finally, let's allow deleting a book:

// DELETE /books/:id — removes a book
app.delete('/books/:id', (req, res) => {
 const id = parseInt(req.params.id);

 // Find the book's position in the array
 const index = books.findIndex((b) => b.id === id);

 // If not found, return 404
 if (index === -1) {
 return res.status(404).json({ message: 'Book not found' });
 }

 // Remove the book from the array
 books.splice(index, 1);

 // Confirm deletion
 res.json({ message: 'Book deleted successfully' });
});

Test it: DELETE http://localhost:3000/books/2 removes Clean Code from the list. Do a GET on /books and confirm it is gone.


Your Complete index.js File

Here is the full code in one place:

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

const PORT = 3000;

let books = [
 { id: 1, title: 'The Pragmatic Programmer', author: 'Andrew Hunt' },
 { id: 2, title: 'Clean Code', author: 'Robert C. Martin' },
 { id: 3, title: "You Don't Know JS", author: 'Kyle Simpson' },
];

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

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

// POST a new book
app.post('/books', (req, res) => {
 const { title, author } = req.body;
 if (!title || !author) return res.status(400).json({ message: 'Title and author are required' });
 const newBook = { id: books.length + 1, title, author };
 books.push(newBook);
 res.status(201).json(newBook);
});

// PUT update a book
app.put('/books/:id', (req, res) => {
 const id = parseInt(req.params.id);
 const { title, author } = req.body;
 const index = books.findIndex((b) => b.id === id);
 if (index === -1) return res.status(404).json({ message: 'Book not found' });
 books[index] = { id, title, author };
 res.json(books[index]);
});

// DELETE a book
app.delete('/books/:id', (req, res) => {
 const id = parseInt(req.params.id);
 const index = books.findIndex((b) => b.id === id);
 if (index === -1) return res.status(404).json({ message: 'Book not found' });
 books.splice(index, 1);
 res.json({ message: 'Book deleted successfully' });
});

app.listen(PORT, () => {
 console.log(`Server is running on http://localhost:${PORT}`);
});

What You Just Built

You now have a fully working REST API with five routes:

Method Route What it does
GET /books Returns all books
GET /books/:id Returns one book
POST /books Adds a new book
PUT /books/:id Updates a book
DELETE /books/:id Deletes a book

What to Learn Next

Now that your API works, here are natural next steps:

  • Add a real database — connect MongoDB or PostgreSQL instead of an array
  • Add authentication — protect your routes with JWT tokens
  • Deploy your API — put it online using Railway or Render (both free)
  • Add input validation — use a library like express-validator for stricter checks

Conclusion

Building a REST API with Node.js and Express is simpler than most people think. You started from an empty folder and ended up with a working API that handles all four CRUD operations. Every API you use daily — Twitter, Instagram, your banking app — works on these same principles at its core.

The code in this tutorial is intentionally simple so you can focus on understanding the concepts. Once these feel comfortable, adding a database and authentication becomes a natural next step.

Happy building.