Building RESTful APIsLesson 3.2
How to structure consistent JSON API responses
response envelope pattern, data field, error field, meta pagination, success flag, HTTP status vs response body, JSend convention, consistent structure
Consistent API Response Structure
Inconsistent API responses — sometimes returning arrays, sometimes objects, sometimes errors as strings — make clients fragile. Define one envelope and use it everywhere.
Response helper
// utils/response.js
const sendSuccess = (res, data, statusCode = 200, meta = null) => {
const payload = { success: true, data };
if (meta) payload.meta = meta;
return res.status(statusCode).json(payload);
};
const sendError = (res, message, statusCode = 500, code = null) => {
return res.status(statusCode).json({
success: false,
error: { message, code }
});
};
module.exports = { sendSuccess, sendError };
Using the helpers
const { sendSuccess, sendError } = require('./utils/response');
app.get('/users', (req, res) => {
const users = [{ id: 1, name: 'Alice' }];
sendSuccess(res, users, 200, { total: users.length });
});
app.get('/users/:id', (req, res) => {
const user = findUser(req.params.id);
if (!user) return sendError(res, 'User not found', 404, 'USER_NOT_FOUND');
sendSuccess(res, user);
});Error codes like 'USER_NOT_FOUND' let clients handle specific errors programmatically without parsing the human-readable message. Always keep HTTP status codes and response body in sync — a 200 response with success: false is confusing.
