Well-designed JSON APIs are a joy to consume. Inconsistent naming, unpredictable structures, and undocumented conventions are among the top frustrations developers face when integrating third-party APIs. This guide covers the conventions that make the biggest practical difference.
1. Pick a naming convention and stick to it
The two dominant conventions are camelCase (common in JavaScript ecosystems) and snake_case (common in Python and Ruby). Neither is objectively better — consistency is what matters. Mixing both in the same API is the worst outcome.
- ·camelCase: { "userId": 1, "firstName": "Alice" }
- ·snake_case: { "user_id": 1, "first_name": "Alice" }
- ·Avoid PascalCase, kebab-case, or SCREAMING_SNAKE_CASE for field names
2. Never return a bare array at the top level
Always wrap your response in an object, even when returning a list. A bare array can never be extended without a breaking change, and it complicates error handling.
// Bad
[{ "id": 1 }, { "id": 2 }]
// Good
{
"data": [{ "id": 1 }, { "id": 2 }],
"total": 2
}3. Use ISO 8601 for all dates and times
Always represent dates as ISO 8601 strings, not Unix timestamps or locale-formatted strings. ISO 8601 is unambiguous, human-readable, and natively supported by JavaScript's Date constructor.
// Bad
{ "createdAt": 1714521600, "date": "05/01/2025" }
// Good
{ "createdAt": "2025-05-01T00:00:00Z" }4. Standardize error responses
RFC 7807 (Problem Details) provides a standardized structure for HTTP error responses. Even if you don't follow it exactly, picking a consistent error shape and using it everywhere is essential.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "issue": "Invalid email format" }
]
}
}5. Handle pagination consistently
Offset-based pagination is simple but breaks when items are inserted or deleted. Cursor-based pagination is more robust for real-time data. Whatever you choose, document it and apply it to every list endpoint.
// Cursor-based (recommended for large/live datasets)
{
"data": [...],
"pagination": {
"nextCursor": "eyJpZCI6MTAwfQ==",
"hasMore": true
}
}6. Be deliberate about null vs. absent fields
Decide upfront: does a missing field mean the same as null? Many APIs treat them differently — null means "known to be empty", while an absent field means "not applicable in this context". Document your convention and apply it uniformly.
Tip: Use null for fields that exist but have no value. Omit fields entirely when they are not applicable to the current resource type.