Script Valley
Express.js: APIs and Middleware
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.

Up next

Express error handling middleware — how to catch all errors

Sign in to track progress