Clarvo Blog·Backend Development

Build Your First REST API with Node.js and Express

Understand resources, HTTP methods and Express routing by building a small API from project setup to error handling.

Clarvo
Clarvo Editorial Team
11 min read·21 Sept 2026·521 words
Build Your First REST API with Node.js and Express
Source image via the referenced Medium article ↗

1. What REST means in practice

MethodRouteMeaningTypical success
GET/notesList notes200
GET/notes/:idRead one note200
POST/notesCreate note201
PATCH/notes/:idUpdate fields200
DELETE/notes/:idDelete note204

2. Create the project

Setupbash
mkdir notes-api
cd notes-api
npm init -y
npm install express
npm install --save-dev nodemon

3. Start the server

server.jsjs
const express = require('express');

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

app.use(express.json());

app.get('/health', (req, res) => {
  res.json({ ok: true });
});

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

4. Add in-memory data first

Temporary data storejs
let notes = [
  { id: 1, title: 'Revise networking', done: false },
  { id: 2, title: 'Read C pointers', done: true },
];
let nextId = 3;

5. GET routes

List and readjs
app.get('/notes', (req, res) => {
  res.json({ items: notes });
});

app.get('/notes/:id', (req, res) => {
  const id = Number(req.params.id);
  const note = notes.find((item) => item.id === id);
  if (!note) return res.status(404).json({ error: 'Note not found' });
  res.json({ item: note });
});

6. POST with validation

Create notejs
app.post('/notes', (req, res) => {
  const title = String(req.body?.title || '').trim();
  if (!title) return res.status(400).json({ error: 'title is required' });

  const note = { id: nextId++, title, done: false };
  notes.push(note);
  res.status(201).json({ item: note });
});

7. PATCH and DELETE

Update notejs
app.patch('/notes/:id', (req, res) => {
  const id = Number(req.params.id);
  const note = notes.find((item) => item.id === id);
  if (!note) return res.status(404).json({ error: 'Note not found' });

  if (typeof req.body?.title === 'string') note.title = req.body.title.trim();
  if (typeof req.body?.done === 'boolean') note.done = req.body.done;

  res.json({ item: note });
});

app.delete('/notes/:id', (req, res) => {
  const id = Number(req.params.id);
  const before = notes.length;
  notes = notes.filter((item) => item.id !== id);
  if (notes.length === before) return res.status(404).json({ error: 'Note not found' });
  res.status(204).end();
});

8. Middleware and request logging

Small loggerjs
app.use((req, res, next) => {
  const started = Date.now();
  res.on('finish', () => {
    console.log(req.method, req.originalUrl, res.statusCode, `${Date.now() - started}ms`);
  });
  next();
});

9. Central error handling

Error middlewarejs
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Internal server error' });
});

10. Test with curl

Requestsbash
curl http://localhost:3000/notes

curl -X POST http://localhost:3000/notes \
  -H "Content-Type: application/json" \
  -d '{"title":"Practise Express"}'

curl -X PATCH http://localhost:3000/notes/1 \
  -H "Content-Type: application/json" \
  -d '{"done":true}'

11. Replace memory with a database without breaking the contract

Once the route behaviour is clear, move persistence behind a repository/service layer. Your clients should still call the same resource URLs and receive the same response shapes. Add database constraints so correctness does not depend only on route code.

12. Production security checklist

  • ✓Validate every untrusted input.
  • ✓Authenticate protected operations.
  • ✓Authorise each user against the resource they are changing.
  • ✓Use rate limiting where abuse is realistic.
  • ✓Keep secrets in environment variables.
  • ✓Restrict CORS instead of using * blindly on authenticated APIs.
  • ✓Use structured logs and monitoring.
  • ✓Paginate large collections.
  • ✓Return predictable error shapes without leaking stack traces.

References

Sources and further reading

Clarvo articles are independently written. These references let you inspect the original inspiration and primary or official sources used to deepen the guide.

  1. Source inspiration — Building a Powerful RESTful API with Node.js and Expressmedium.com