REST API JSON Best Practices
Designing consistent, predictable JSON responses is one of the most impactful things you can do for your API’s usability. This guide covers the conventions used by top APIs like Stripe, GitHub, and Twilio.
Naming Conventions
Choose one naming convention and use it consistently across all endpoints:
| Convention | Example | Used By |
|---|---|---|
| camelCase | firstName, createdAt | JavaScript, Stripe |
| snake_case | first_name, created_at | Python, GitHub, Twitter |
| kebab-case | first-name | Rare in JSON (used in URLs) |
Convert between conventions instantly with our String Case Converter.
Rule: Match the naming convention of your primary consumer. If your API is consumed mostly by JavaScript frontends, use camelCase. If by Python backends, use snake_case.
Response Envelope Pattern
Wrap your responses in a consistent envelope:
{
"data": {
"id": "usr_123",
"name": "Alice Johnson",
"email": "alice@example.com"
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-03-22T14:30:00Z"
}
}
This pattern separates the actual data from metadata and makes your API easier to extend without breaking changes.
Error Response Format
Use a consistent error format across all endpoints:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body contains invalid fields.",
"details": [
{ "field": "email", "message": "Must be a valid email address" },
{ "field": "age", "message": "Must be a positive integer" }
]
}
}
Rules:
- Always return an
errorobject (never a plain string). - Include a machine-readable
codefor programmatic handling. - Include a human-readable
messagefor debugging. - Use
detailsarray for field-level validation errors.
Pagination
For list endpoints, use cursor-based pagination:
{
"data": [
{ "id": "usr_001", "name": "Alice" },
{ "id": "usr_002", "name": "Bob" }
],
"pagination": {
"hasMore": true,
"nextCursor": "usr_002",
"totalCount": 150
}
}
Cursor-based pagination is more reliable than offset-based (?page=2) because it handles insertions and deletions without skipping or duplicating records.
Dates and Timestamps
Always use ISO 8601 format with timezone:
{
"createdAt": "2026-03-22T14:30:00Z",
"updatedAt": "2026-03-22T15:45:30+03:00"
}
Convert timestamps between Unix epoch and human-readable dates with our Unix Timestamp Converter.
Rules:
- Use UTC (
Zsuffix) for server-generated timestamps. - Include timezone offset for user-facing times.
- Never use ambiguous formats like
03/22/2026(US) or22/03/2026(EU).
Null vs Absent Fields
Be explicit about null values:
{
"name": "Alice",
"avatar": null,
"bio": null
}
Rule: Include fields with null values rather than omitting them. This tells the consumer “this field exists but has no value” versus “this field doesn’t exist,” which are semantically different.
Performance Tips
- Minify production responses — Remove whitespace with
JSON.stringify(data)(no indentation). Use our JSON Formatter during development, minified in production. - Use pagination — Never return unbounded lists.
- Support field selection — Let consumers request only the fields they need:
?fields=id,name,email. - Compress responses — Enable gzip/brotli compression at the server level.
- Generate TypeScript types — Create client-side type safety from your API responses with our JSON to TypeScript Converter.
This article is part of our JSON Developer Guide series.