Structuring Response Payloads
1. Structuring JSON Responses
| Convention | Example |
| camelCase keys | "firstName" |
| ISO 8601 dates | "2026-05-15T10:30:00Z" |
| Numbers unquoted | "price": 19.99 |
| Booleans lowercase | "active": true |
| No trailing commas | JSON spec forbids |
2. Using Response Envelopes
| Style | Pros | Cons |
| Bare resource | Concise, REST-pure | No room for metadata |
| Envelope (data/meta) | Pagination/links inline | Verbose, extra nesting |
| JSON:API | Standardized, tooling | Heavy, learning curve |
{
"data": [{"id": 1, "name": "Alice"}],
"meta": {
"page": 1,
"perPage": 20,
"total": 145
},
"links": {
"self": "/users?page=1",
"next": "/users?page=2"
}
}
| Metadata Field | Purpose |
createdAt / updatedAt | Audit timestamps |
version | Optimistic locking |
_links / _embedded | HAL hypermedia |
etag | Concurrency token |
4. Handling Empty Responses
| Scenario | Response |
| Empty collection | 200 OK + {"data": []} (NOT 404) |
| Resource not found | 404 Not Found |
| Successful DELETE/PUT | 204 No Content (no body) |
| Field | Description |
page / perPage | Current page, page size |
total | Total record count |
totalPages | Total page count |
hasNext / hasPrev | Navigation booleans |
nextCursor | Cursor pagination token |
6. Including HATEOAS Links
{
"id": 100,
"amount": 250.00,
"_links": {
"self": {"href": "/orders/100"},
"user": {"href": "/users/42"},
"cancel": {"href": "/orders/100/cancel", "method": "POST"}
}
}
| Link Field | Purpose |
self | Canonical URI of resource |
related | Related resource |
next / prev | Pagination |
7. Structuring Error Responses
Use RFC 7807 Problem Details for HTTP APIs as the standard.
Example: RFC 7807 Problem Details
{
"type": "https://example.com/errors/validation",
"title": "Validation Failed",
"status": 422,
"detail": "Email is required and must be valid",
"instance": "/users/42",
"errors": [
{"field": "email", "code": "REQUIRED", "message": "Email is required"}
],
"traceId": "abc-123-def"
}
8. Using Consistent Naming Conventions
| Convention | Use | Example |
| camelCase | JSON keys (most common) | userId, createdAt |
| snake_case | Python, Ruby APIs | user_id, created_at |
| kebab-case | URL paths only | /user-profiles |
9. Handling Null vs Omitted Fields
| Approach | Meaning |
"field": null | Field exists, no value |
| Omit field | Field unknown / not applicable / not requested |
Empty string "" | Distinct from null (e.g. cleared text) |
Note: Be consistent. Document choice in API spec. Omitting reduces payload size.
| Header | Purpose |
Content-Type | Response format |
Content-Length | Body size |
ETag | Cache validation |
Last-Modified | Cache validation |
Cache-Control | Cache directives |
Location | Created resource URI |
X-Request-ID | Echo correlation ID |
X-RateLimit-* | Rate limit status |