Back to blog
JSON
APIs
data design

JSON Formatting Best Practices for APIs

Design consistent JSON responses with clear naming, dates, errors, pagination, and forward-compatible data shapes.

SimpleTaskTools TeamUpdated August 15, 202612 min read

Good API JSON is predictable before it is clever. Consumers should not have to guess whether a field changes type, which timezone a date uses, or how an error is shaped. A small set of consistent conventions prevents many integration bugs.

Pretty-print for people, compress for transport

Readable indentation is valuable in examples, logs, and debugging tools. Production responses can omit insignificant whitespace and rely on HTTP compression. Whitespace does not change the parsed JSON value.

Choose one naming convention

camelCase and snake_case are both widely used. The important rule is consistency across endpoints and versions. Avoid renaming public fields only for style; a rename is a breaking contract change for many clients.

Represent time explicitly

ISO 8601 strings such as 2026-02-05T14:30:00Z are readable and timezone-explicit. If you use Unix timestamps, document whether the unit is seconds or milliseconds. Never return a local date-time without a timezone when it represents an instant.

Use a stable error envelope

json
{
  "error": {
    "code": "invalid_email",
    "message": "Enter a valid email address.",
    "field": "email",
    "requestId": "req_123"
  }
}

Give programs a stable code and people a clear message. A field pointer helps form validation, while a request ID lets support teams correlate a client error with server logs. Do not expose stack traces or internal database details.

Plan pagination and evolution

Paginate any list that can grow. Cursor pagination is often more stable than offsets for rapidly changing datasets, but either approach can work when its ordering rules are documented. Clients should ignore unknown fields so you can add data without breaking them.

json
{
  "data": [],
  "pagination": {
    "nextCursor": "eyJpZCI6MTIzfQ",
    "hasMore": true
  }
}

Offset pagination drifts when rows are inserted or removed between requests, so a client paging through a busy list can see an item twice or miss one entirely. A cursor encodes a position in a stable ordering and avoids that class of bug.

Keep values unsurprising

  • Use booleans for true/false state rather than 0, 1, yes, and no.
  • Use descriptive string enums and document how clients should handle new values.
  • Keep a field type stable; do not alternate between an object, array, and empty string.
  • Use null only when it has a documented meaning distinct from an omitted field.
  • Avoid double-encoding an object as a JSON string inside JSON.

Prefer string enums to integer codes

A response containing status: 2 forces every reader to find a lookup table, and the mapping tends to live in one team’s head. status: "refunded" is self-describing in logs, in tests, and in a support ticket. Reserve integers for values that are genuinely numeric.

Name booleans so the answer is obvious

A field called admin could plausibly be a boolean, a role name, or a user object. isAdmin, hasVerifiedEmail, and canEdit read unambiguously at the call site and survive being skim-read during an incident.

Keep nesting shallow

Every level of nesting is another optional-chaining step and another null check in client code. Two or three levels is usually enough. When a structure grows deeper than that, it is often a sign the nested data deserves its own endpoint or its own resource.

Anti-patterns worth avoiding

  • Returning stringified JSON inside a string field instead of nesting the object.
  • Mixing casing conventions within a single response.
  • Returning a different shape for the same field depending on state.
  • Using sentinel values such as -1 to mean unknown.
  • Trailing commas and comments, neither of which is valid JSON.

Validate examples and contracts

Run example payloads through a strict parser and validate important responses with JSON Schema or contract tests. Formatters help people inspect a payload, but automated validation is what prevents an accidental shape change from reaching production.

Summary

Dependable APIs are unexciting to integrate against. Consistent names, explicit timestamps, one error envelope, documented pagination, and stable field types cover most of it—and none of those decisions are expensive if you make them before the first client ships.