380 words
2 minutes
REST API Design Best Practices
REST API Design Best Practices
After building 50+ APIs, here’s how I design them.
Basic Principles
1. Use Nouns, Not Verbs
Good:GET /usersGET /users/123POST /usersPUT /users/123DELETE /users/123
Bad:GET /getUsersPOST /createUserDELETE /deleteUser/1232. Use Proper HTTP Methods
| Method | Purpose | Example |
|---|---|---|
| GET | Read | Get users |
| POST | Create | Add new user |
| PUT | Update (full) | Replace user |
| PATCH | Update (partial) | Update email only |
| DELETE | Remove | Delete user |
3. Use Status Codes
// Success200 OK // Request succeeded201 Created // Resource created204 No Content // Successful, no body
// Client Errors400 Bad Request // Invalid input401 Unauthorized // Not authenticated403 Forbidden // Not authorized404 Not Found // Resource doesn't exist422 Unprocessable // Validation error
// Server Errors500 Internal Error // Something brokeExample API (Express.js)
const express = require('express');const app = express();
// GET all usersapp.get('/api/users', async (req, res) => { try { const users = await User.find(); res.json({ success: true, count: users.length, data: users }); } catch (err) { res.status(500).json({ success: false, error: 'Server Error' }); }});
// GET single userapp.get('/api/users/:id', async (req, res) => { try { const user = await User.findById(req.params.id);
if (!user) { return res.status(404).json({ success: false, error: 'User not found' }); }
res.json({ success: true, data: user }); } catch (err) { res.status(500).json({ success: false, error: 'Server Error' }); }});
// POST create userapp.post('/api/users', async (req, res) => { try { const user = await User.create(req.body); res.status(201).json({ success: true, data: user }); } catch (err) { res.status(400).json({ success: false, error: err.message }); }});Response Format
Always consistent structure:
{ "success": true, "count": 2, "data": [ { "id": 1, "name": "User 1" }, { "id": 2, "name": "User 2" } ]}Error response:
{ "success": false, "error": "User not found"}Pagination
GET /api/users?page=1&limit=10
Response:{ "success": true, "count": 10, "total": 100, "page": 1, "pages": 10, "data": [...]}Filtering & Sorting
GET /api/products?category=electronics&price[lte]=1000GET /api/posts?sort=-createdAtGET /api/users?fields=name,emailAuthentication
// Middlewareconst protect = async (req, res, next) => { let token;
if (req.headers.authorization?.startsWith('Bearer')) { token = req.headers.authorization.split(' ')[1]; }
if (!token) { return res.status(401).json({ success: false, error: 'Not authorized' }); }
try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = await User.findById(decoded.id); next(); } catch (err) { res.status(401).json({ success: false, error: 'Not authorized' }); }};
// Protected routeapp.get('/api/profile', protect, getProfile);API Versioning
/api/v1/users/api/v2/usersDocumentation
Use Swagger/OpenAPI:
paths: /users: get: summary: Get all users responses: 200: description: SuccessGood APIs are intuitive. Make them easy to use!
REST API Design Best Practices
https://blog.lukkid.dev/posts/rest-api-design/