REST API JSON Best Practices for Clean, Stable APIs
Design JSON APIs that are predictable and easy to consume: naming conventions, consistent error shapes, dates and money, pagination, versioning, and validating responses against a schema.
A REST API is only as good as its JSON. Consistent, well-shaped responses make an API a joy to integrate; inconsistent ones generate support tickets and brittle client code. This guide collects practical JSON best practices for API design — naming, errors, dates, pagination, and versioning — the conventions that separate an API people trust from one they dread.
Pick one naming convention and keep it
JSON keys should follow a single, consistent casing across every endpoint. camelCase is common in JavaScript-centric APIs; snake_case is common elsewhere. Either is fine — what matters is consistency, because a response that mixes userId and user_name forces clients to remember exceptions. Decide once, document it, and never deviate.
Return consistent, structured errors
Errors should be JSON too, with a stable shape clients can parse — typically a machine-readable code, a human-readable message, and optional details about which fields failed. Do not return HTML error pages or bare strings, which break JSON parsers and leave clients guessing. A predictable error envelope lets every client handle failures the same way, and pairing it with the correct HTTP status code is the standard contract.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Email is invalid",
"details": [{ "field": "email", "issue": "format" }]
}
}Be deliberate about dates and money
- Dates and times: use ISO 8601 strings in UTC (for example 2026-04-03T12:00:00Z). Never invent a custom date format or send ambiguous local times.
- Money: avoid floats, which lose precision; send integer minor units (cents) or a decimal string, plus an explicit currency code.
- IDs: send them as strings, not numbers, so large or zero-padded identifiers survive intact.
- Booleans: use real JSON true/false, not strings or 1/0.
Design for collections: pagination and envelopes
List endpoints should never return an unbounded array. Paginate with limit and offset or cursor-based paging, and wrap results in an object that carries metadata — the items array plus fields like total count and next-page info. An envelope is more future-proof than a bare top-level array because you can add metadata later without breaking clients.
{
"data": [ /* items */ ],
"pagination": { "total": 240, "limit": 20, "nextCursor": "abc" }
}Version your API
Breaking changes to your JSON shape — renaming a field, changing a type — will break clients. Plan for it with versioning, whether in the URL path or a header, and treat the response shape as a contract. Additive changes (new optional fields) are usually safe; removals and renames are not, and should land in a new version.
Validate the contract on both sides
Define your response shape as a JSON Schema and validate against it in tests so a regression cannot silently change the contract. On the client side, validate incoming responses and generate typed models from the JSON so your code and the API stay aligned. A schema validator catches drift, a code generator produces the types, and a formatter makes responses readable while you debug.
Frequently asked questions
Should JSON API keys use camelCase or snake_case?
Either works — the rule is consistency. Pick one convention (camelCase suits JavaScript-heavy APIs, snake_case is common elsewhere), document it, and apply it to every endpoint so clients never have to remember exceptions.
What is the best way to format errors in a JSON API?
Return a stable JSON object with a machine-readable code, a human-readable message, and optional field-level details, paired with the correct HTTP status code. Avoid HTML error pages and bare strings, which break JSON clients.
How should I send dates in a JSON API?
Use ISO 8601 strings in UTC, such as 2026-04-03T12:00:00Z. JSON has no date type, so a standardized string format avoids ambiguity and parses reliably in every language.
Should IDs be numbers or strings in JSON?
Prefer strings. Large numeric IDs can exceed safe integer limits in some languages, and zero-padded IDs lose leading zeros as numbers. Strings keep identifiers intact regardless of the consumer.
How do I keep a JSON API contract stable?
Define the response shape as a JSON Schema and validate against it in tests, version the API for breaking changes, and make only additive changes within a version. Generate typed client models from the JSON to catch drift early.
Related tools
Try these tools
JSON Schema Validator
Validate JSON documents against a JSON Schema.
JSON to TypeScript Types
Generate TypeScript interfaces and types from any JSON sample.
JSON Formatter & Beautifier
Format, prettify, and beautify messy JSON with configurable indentation and key sorting.
JSON Validator
Validate JSON instantly with precise, human-readable error messages and line numbers.