JSON in API Responses
Best practices for structuring JSON API responses: envelope patterns, error formats, pagination, status codes, and common conventions used by major API providers.
Detailed Explanation
JSON is the dominant data format for REST API responses. While the JSON specification defines the syntax, it does not prescribe how to structure API responses. Over time, community conventions and standards have emerged that help developers build consistent, predictable, and easy-to-consume APIs.
Common response structures:
The two main approaches are flat responses and envelope patterns:
Flat response (recommended for simple APIs):
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
HTTP status codes convey success or failure. The body contains only the resource data.
Envelope response (common in practice):
{
"status": "success",
"data": { "id": 1, "name": "Alice" },
"meta": { "requestId": "abc-123" }
}
An outer wrapper provides metadata alongside the payload. This is useful when HTTP status codes alone are insufficient or when clients cannot easily access response headers.
Error response conventions:
A good error response includes a machine-readable code, a human-readable message, and optionally detailed validation errors:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request body is invalid",
"details": [
{ "field": "email", "message": "Must be a valid email address" }
]
}
}
Standards like RFC 9457 (Problem Details for HTTP APIs) provide a formal structure for error responses, including type, title, status, detail, and instance fields.
Pagination:
Large collections should be paginated. Common patterns include:
{
"data": [...],
"pagination": {
"page": 2,
"perPage": 20,
"total": 150,
"totalPages": 8
}
}
Cursor-based pagination uses an opaque cursor string instead of page numbers, which is more efficient for large datasets and avoids issues with items being inserted or deleted between requests.
Common mistakes developers make:
Returning 200 OK for every response and putting the real status code in the body defeats the purpose of HTTP status codes and breaks standard HTTP clients and middleware. Another mistake is inconsistent response structures — sometimes returning {"data": ...} and sometimes returning the resource directly. Clients should not have to guess the response shape. Developers also sometimes return too much data (over-fetching), including sensitive fields like password hashes or internal IDs, because the database model is serialized directly without a presentation layer.
Best practices:
Be consistent: every endpoint should follow the same response structure. Use appropriate HTTP status codes (200, 201, 204, 400, 401, 404, 500). Always return Content-Type: application/json. Include a request ID in responses for debugging. Version your API to avoid breaking changes. Use HATEOAS links or a standardized format like JSON:API if your API is complex.
Use Case
Designing a REST API response format for a SaaS platform that includes consistent error handling, pagination metadata, and rate limit information across all endpoints.