Work in progress: under construction · noindex

Tutorial · Beginner

REST API Tutorial: from zero to your first own API

Node.js Express 5 Reading time ~12 min Updated: July 2026

REST is the de facto standard for how programs talk to each other over HTTP. In this tutorial you'll learn the fundamentals – HTTP methods, status codes, CRUD – and at the end you'll build a working API with Node.js and Express.

What is a REST API?

REST (Representational State Transfer) is an architectural style for web interfaces. Instead of its own commands, a REST API uses the web's existing mechanisms: URLs address resources (e.g. books, users, orders), and the HTTP method defines what should happen to the resource.

Two properties are central:

HTTP basics: methods, headers, body

An HTTP request consists of a method (the verb), a URL, optional headers (metadata such as Content-Type or Authorization) and – for write operations – a body (usually JSON).

MethodPurposeBody?Idempotent?
GETRead resource(s)noyes
POSTCreate a new resourceyesno
PUTFully replace a resourceyesyes
PATCHPartially update a resourceyesno
DELETEDelete a resourcenoyes

Idempotent means: sending the same request multiple times has the same effect as sending it once. Sending a PUT with the same content twice changes nothing after the first time – whereas POST would create two objects.

Understanding status codes

The server always responds with a three-digit status code. The first digit reveals the category:

RangeMeaningCommon codes
2xxSuccess200 OK · 201 Created · 204 No Content
3xxRedirection301 Moved Permanently · 304 Not Modified
4xxClient error400 Bad Request · 401 Unauthorized · 403 Forbidden · 404 Not Found · 429 Too Many Requests
5xxServer error500 Internal Server Error · 503 Service Unavailable
Memory aid

4xx = "you made a mistake" (bad input, missing authentication). 5xx = "the server made a mistake". Use codes deliberately – a 200 with an error message in the body is bad style.

CRUD: the four basic operations

Almost every API maps CRUD – Create, Read, Update, Delete. These four operations map directly onto HTTP methods:

OperationHTTPExample routeSuccess code
CreatePOST/api/v1/books201
Read (list)GET/api/v1/books200
Read (single)GET/api/v1/books/42200
UpdatePUT/api/v1/books/42200
DeleteDELETE/api/v1/books/42204

Hands-on: your first API with Express 5

Now let's build it ourselves. We use Express, the most widely used web framework for Node.js. Express 5 has been the stable version since October 2024 and requires Node.js 18 or newer.

Step 1: Create the project

bash
mkdir books-api && cd books-api
npm init -y
npm install express
node --version   # should print v18 or newer

Step 2: Write the server

Create a file server.js with the following content. For simplicity we store the books in memory (in reality a database would go here).

javascript — server.js
const express = require("express");
const app = express();

// Parse JSON bodies automatically
app.use(express.json());

// In-memory "database"
let books = [
  { id: 1, title: "Clean Code", author: "Robert C. Martin" },
  { id: 2, title: "The Pragmatic Programmer", author: "Hunt & Thomas" }
];
let nextId = 3;

// READ – all books
app.get("/api/v1/books", (req, res) => {
  res.json(books);
});

// READ – a single book (with 404 handling)
app.get("/api/v1/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);
});

// CREATE – add a new book
app.post("/api/v1/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)
    .location(`/api/v1/books/${book.id}`)
    .json(book);
});

// UPDATE – fully replace a book
app.put("/api/v1/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;
  book.title = title;
  book.author = author;
  res.json(book);
});

// DELETE – delete a book
app.delete("/api/v1/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();   // 204 = success without a body
});

app.listen(3000, () => {
  console.log("API läuft auf http://localhost:3000");
});

Step 3: Start the server

bash
node server.js
# → API läuft auf http://localhost:3000

Testing the API with curl

Open a second terminal and hit the endpoints:

bash
# Fetch all books (GET)
curl http://localhost:3000/api/v1/books

# Create a new book (POST) – response: 201 Created
curl -X POST http://localhost:3000/api/v1/books \
  -H "Content-Type: application/json" \
  -d '{"title":"Refactoring","author":"Martin Fowler"}'

# Update a book (PUT)
curl -X PUT http://localhost:3000/api/v1/books/1 \
  -H "Content-Type: application/json" \
  -d '{"title":"Clean Code (2. Aufl.)","author":"Robert C. Martin"}'

# Delete a book (DELETE) – response: 204, use -i to see the status
curl -X DELETE http://localhost:3000/api/v1/books/1 -i
Tip

For graphical testing, Postman, Insomnia or the open-source Bruno are handy – there you can save requests and organise them into collections.

Best practices

One detail about Express 5: if an async handler throws an error or a promise is rejected, that error is automatically forwarded to the error middleware – the tedious try/catch around every handler is no longer needed.

javascript
// Async handler without try/catch (Express 5 forwards the error)
app.get("/api/v1/status", async (req, res) => {
  const daten = await ladeDaten();   // may throw an error
  res.json(daten);
});

// Central error middleware – define it right at the end
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: "Interner Serverfehler" });
});
In summary

A REST API addresses resources via URLs, uses HTTP methods as verbs and responds with meaningful status codes. With around 40 lines of Express you have a complete CRUD API. The next logical step: securing the write endpoints.