Build a REST API with Node.js and Express in 30 Minutes

Building APIs doesn’t have to be complicated. In this tutorial, we’ll build a fully functional REST API from scratch using Node.js and Express. By the end, you’ll have a working API with CRUD operations, proper error handling, and middleware.

Prerequisites

Make sure you have Node.js installed (version 18 or higher). You can check by running:

node --version
npm --version

Step 1: Project Setup

Create a new directory and initialize the project:

mkdir my-api && cd my-api
npm init -y
npm install express cors dotenv
npm install -D nodemon

Step 2: Create the Server

Create server.js in your project root:

const express = require('express');
const cors = require('cors');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(cors());
app.use(express.json());

// In-memory data store
let books = [
  { id: 1, title: 'Clean Code', author: 'Robert Martin', year: 2008 },
  { id: 2, title: 'The Pragmatic Programmer', author: 'Hunt & Thomas', year: 1999 }
];

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

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

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

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

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

app.listen(PORT, () => console.log('Server running on port ' + PORT));

Step 3: Add Error Handling Middleware

Add this before app.listen():

// 404 handler
app.use((req, res) => {
  res.status(404).json({ error: 'Route not found' });
});

// Global error handler
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

Step 4: Test Your API

Start the server with node server.js and test using curl:

# Get all books
curl http://localhost:3000/api/books

# Create a new book
curl -X POST http://localhost:3000/api/books \
  -H "Content-Type: application/json" \
  -d '{"title":"Refactoring","author":"Martin Fowler","year":1999}'

# Update a book
curl -X PUT http://localhost:3000/api/books/1 \
  -H "Content-Type: application/json" \
  -d '{"year":2009}'

What’s Next?

This is a solid foundation, but for production you’d want to add a database (MongoDB or PostgreSQL), input validation (Joi or Zod), authentication (JWT), rate limiting, and proper logging. We’ll cover those in future tutorials.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top