Express.js REST API Development
Build professional REST APIs with Express.js. Learn about API design, versioning, documentation, rate limiting, and best practices.
Overview
Building RESTful APIs with Express.js requires understanding REST principles, proper response handling, and API best practices.
REST Principles
REST (Representational State Transfer) APIs follow these principles: - Use HTTP methods appropriately (GET, POST, PUT, DELETE) - Stateless communication - Consistent resource naming - Proper use of status codes
API Response Format
Consistent response formats make your API easier to use. Include status codes, data, and error messages in a predictable structure.
API Versioning
Version your API to make breaking changes without affecting existing clients. Common approaches include URL versioning (/v1/users) or header versioning.
Documentation
Good documentation is essential. Use tools like Swagger/OpenAPI to generate interactive documentation.
Code Examples
RESTful Resource Controller
// User Controller with CRUD operations
const User = require('../models/User');
exports.getAll = async (req, res) => {
const { page = 1, limit = 10, sort = '-createdAt' } = req.query;
const users = await User.find()
.sort(sort)
.skip((page - 1) * limit)
.limit(Number(limit));
const total = await User.countDocuments();
res.json({
status: 'success',
results: users.length,
pagination: {
page: Number(page),
limit: Number(limit),
total,
pages: Math.ceil(total / limit)
},
data: users
});
};
exports.getOne = async (req, res) => {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({
status: 'fail',
message: 'User not found'
});
}
res.json({ status: 'success', data: user });
};
exports.create = async (req, res) => {
const user = await User.create(req.body);
res.status(201).json({ status: 'success', data: user });
};API Versioning
const express = require('express');
const v1Router = require('./v1');
const v2Router = require('./v2');
const app = express();
// Version 1 API
app.use('/api/v1', v1Router);
// Version 2 API with new features
app.use('/api/v2', v2Router);
// Default to latest version
app.use('/api', v2Router);
// Version info endpoint
app.get('/api/versions', (req, res) => {
res.json({
versions: ['v1', 'v2'],
current: 'v2',
deprecated: ['v1']
});
});Rate Limiting
const rateLimit = require('express-rate-limit');
// General API rate limiter
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests
message: {
status: 'error',
message: 'Too many requests, please try again later'
},
standardHeaders: true,
legacyHeaders: false,
});
// Stricter limiter for auth routes
const authLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 5, // 5 attempts per hour
message: {
status: 'error',
message: 'Too many login attempts, try again in an hour'
}
});
app.use('/api/', apiLimiter);
app.use('/api/auth/login', authLimiter);Frequently Asked Questions
What HTTP status codes should I use?
How should I handle API pagination?
Should I use PUT or PATCH for updates?
Need expert help with Express.js?
Our team at Slashdev.io builds production-ready Express.js applications.