Node.js / API / Backend
Building RESTful APIs with Node.js and Express
A comprehensive guide to building robust and scalable REST APIs using Node.js, Express, and best practices.
|12 min read
Introduction
Building RESTful APIs is a fundamental skill for backend developers. In this guide, we'll create a robust API using Node.js and Express.
Setting Up the Project
Initialize a new Node.js project:
mkdir my-api
cd my-api
npm init -y
npm install express cors helmet
npm install -D typescript @types/express @types/node
Basic Express Server
Create a simple Express server:
1
import express from 'express';
2
import cors from 'cors';
3
import helmet from 'helmet';
4
5
const app = express();
6
const PORT = process.env.PORT || 3000;
7
8
// Middleware
9
app.use(helmet());
10
app.use(cors());
11
app.use(express.json());
12
13
// Routes
14
app.get('/', (req, res) => {
15
res.json({ message: 'Welcome to the API' });
16
});
17
18
app.listen(PORT, () => {
19
console.log(`Server running on port ${PORT}`);
20
});
RESTful Routes
Implement CRUD operations:
1
// GET all items
2
app.get('/api/items', async (req, res) => {
3
const items = await Item.findAll();
4
res.json(items);
5
});
6
7
// GET single item
8
app.get('/api/items/:id', async (req, res) => {
9
const item = await Item.findById(req.params.id);
10
if (!item) {
11
return res.status(404).json({ error: 'Item not found' });
12
}
13
res.json(item);
14
});
15
16
// POST create item
17
app.post('/api/items', async (req, res) => {
18
const item = await Item.create(req.body);
19
res.status(201).json(item);
20
});
21
22
// PUT update item
23
app.put('/api/items/:id', async (req, res) => {
24
const item = await Item.update(req.params.id, req.body);
25
res.json(item);
26
});
27
28
// DELETE item
29
app.delete('/api/items/:id', async (req, res) => {
30
await Item.delete(req.params.id);
31
res.status(204).send();
32
});
Error Handling
Implement centralized error handling:
1
// Error handling middleware
2
app.use((err, req, res, next) => {
3
console.error(err.stack);
4
res.status(500).json({
5
error: 'Something went wrong!',
6
message: process.env.NODE_ENV === 'development' ? err.message : undefined
7
});
8
});
Validation
Validate request data:
1
import { z } from 'zod';
2
3
const itemSchema = z.object({
4
name: z.string().min(1),
5
price: z.number().positive(),
6
description: z.string().optional()
7
});
8
9
app.post('/api/items', async (req, res) => {
10
const result = itemSchema.safeParse(req.body);
11
if (!result.success) {
12
return res.status(400).json({ errors: result.error.errors });
13
}
14
// Create item...
15
});
Conclusion
You now have the foundation for building robust REST APIs with Node.js and Express. Remember to always validate input, handle errors gracefully, and follow REST conventions.
I've shipped APIs like this across fintech and SaaS products for over a decade — more about my background, or read Multi-Tenant SaaS Architecture Lessons for how these patterns scale to production.
Written by Erik Yuntantyo·Software Engineer·About me