07 Response Formatting
title: Response Formatting in Node.js REST APIs weight: 17 date: 2026-06-28 lastmod: 2026-06-28 description: Learn response formatting in Node.js REST APIs including JSON responses, status codes, headers, response envelopes, and formatting helpers for consistent output. tags: [api-development, nodejs]
Response formatting in Node.js REST APIs standardizes how data is returned to clients using consistent JSON structures, proper status codes, response headers, and envelope patterns for success, error, and paginated responses.
```mermaid
flowchart TD
A[Response] --> B[Status Code]
A --> C[Headers]
A --> D[Body Format]
B --> E[200, 201, 204, 400, 404, 500]
C --> F[Content-Type, Cache-Control]
D --> G[Success Envelope]
D --> H[Error Envelope]
D --> I[Pagination Envelope]
style A fill:#e1f5fe
style B fill:#fff9c4
style G fill:#c8e6c9
style H fill:#ffcdd2
A response formatting strategy defines how every response looks. Success responses include status, data, and optional metadata. Error responses include status, error code, message, and details. Paginated responses include items, total, page, and links.
Think of response formatting like packaging. No matter what you are shipping (data), the box should look the same: same label position (structure), same tape (status code), and same handling instructions (headers).
Example: Response Helper Functions
class ApiResponse {
static success(res, data, statusCode = 200) {
return res.status(statusCode).json({
status: 'success',
data
});
}
static created(res, data) {
return res.status(201).json({
status: 'success',
data
});
}
static paginated(res, items, total, page, perPage) {
return res.status(200).json({
status: 'success',
data: items,
meta: {
total,
page,
perPage,
totalPages: Math.ceil(total / perPage)
}
});
}
static error(res, message, statusCode = 500, code = 'INTERNAL_ERROR') {
return res.status(statusCode).json({
status: 'error',
error: { code, message }
});
}
}
// Usage in controller
app.get('/api/users/:id', (req, res) => {
const user = findUser(req.params.id);
if (!user) {
return ApiResponse.error(res, 'User not found', 404, 'NOT_FOUND');
}
return ApiResponse.success(res, user);
});
Expected output:
{"status": "success", "data": {"id": 42, "name": "Alice"}}
Example: Setting Response Headers
app.get('/api/users', (req, res) => {
const users = getAllUsers();
// Custom headers
res.setHeader('X-API-Version', '1.0');
res.setHeader('X-Total-Count', users.length);
res.setHeader('Cache-Control', 'public, max-age=300');
// Link header for pagination
const links = [
`<https://api.example.com/users?page=1>; rel="first"`,
`<https://api.example.com/users?page=3>; rel="next"`
];
res.setHeader('Link', links.join(', '));
res.json({ status: 'success', data: users });
});
Example: Content Negotiation for Response Format
app.get('/api/users/:id', (req, res) => {
const user = findUser(req.params.id);
// Based on Accept header
if (req.accepts('xml')) {
// Return XML
res.setHeader('Content-Type', 'application/xml');
res.send(`<user><id>${user.id}</id><name>${user.name}</name></user>`);
} else if (req.accepts('json')) {
// Default to JSON
res.json({ status: 'success', data: user });
} else {
res.status(406).json({ status: 'error', error: { code: 'NOT_ACCEPTABLE' } });
}
});
Common Mistakes
- Inconsistent response structure across endpoints — Mixing {data: ...} in one endpoint and {result: ...} in another forces clients to handle multiple formats.
- Not setting Content-Type header — Express sets Content-Type automatically for res.json(), but ensure custom formatters set the correct type.
- Returning raw arrays without metadata — Returning just [user1, user2] without count or pagination info forces clients to guess the total.
- Exposing internal data in responses — Filter out sensitive fields like passwords, tokens, and internal IDs before sending responses.
- Missing error details for validation failures — Return field-level error details so clients can display specific error messages next to form fields.
Practice Questions
- What are the benefits of a consistent response envelope?
- How do you set custom response headers in Express?
- What should a paginated response include besides the items?
- How do you handle content negotiation for response formats?
- Challenge: Build a response formatting middleware that wraps all responses in a consistent envelope. It should support success, error, and paginated responses automatically based on the data returned from route handlers.
FAQ
Mini Project
Create a response formatting module with helper functions for success, error, created, paginated, and no-content responses. Integrate it into an Express app and ensure every endpoint uses the formatters. Add a middleware that catches unformatted responses and wraps them.
What's Next
Now learn about error middleware in Building REST APIs with Node.js.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro