Overview

Node.js and Express are one of the most popular combinations for building REST APIs. Express is a minimal, flexible web framework that gives you the tools to handle HTTP requests without the overhead of a full framework. In this tutorial, you'll build a working API for managing a simple list of tasks.

Prerequisites

  • Node.js installed (v18 or later recommended)
  • Basic JavaScript knowledge
  • A terminal and a code editor (VS Code works great)

Step 1: Set Up Your Project

Create a new directory and initialize a Node.js project:

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

Create a file called index.js — this will be your API's entry point.

Step 2: Create Your Express Server

Open index.js and add the following:

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

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

Run it with node index.js and your server is live.

Step 3: Add In-Memory Data and Routes

For this tutorial, we'll store tasks in a simple array:

let tasks = [
  { id: 1, title: 'Learn Express', done: false },
  { id: 2, title: 'Build an API', done: false }
];

Now add the four core CRUD routes:

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

// GET a single task
app.get('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).json({ error: 'Task not found' });
  res.json(task);
});

// POST a new task
app.post('/tasks', (req, res) => {
  const task = { id: Date.now(), title: req.body.title, done: false };
  tasks.push(task);
  res.status(201).json(task);
});

// DELETE a task
app.delete('/tasks/:id', (req, res) => {
  tasks = tasks.filter(t => t.id !== parseInt(req.params.id));
  res.status(204).send();
});

Step 4: Test Your API

Use curl or Postman to test your endpoints:

  • GET http://localhost:3000/tasks — returns all tasks
  • POST http://localhost:3000/tasks with body {"title": "New task"} — creates a task
  • DELETE http://localhost:3000/tasks/1 — removes task with ID 1

Step 5: Add Basic Error Handling Middleware

Always include a catch-all error handler at the bottom of your file:

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

What's Next?

This is a foundation — a real-world API would also include:

  • A database (like PostgreSQL or MongoDB) instead of in-memory arrays
  • Authentication (API keys or JWT tokens)
  • Input validation using a library like Zod or Joi
  • Rate limiting to prevent abuse

You've just built a fully functional REST API. From here, the sky is the limit.