jsonapirestjsonapi

JSON:API: A Standard Format for REST Responses

·9 min read·APIs

Stop bikeshedding your response shape

Every team that builds a REST API re-invents the same decisions: where does the data go, how are errors shaped, how do you include related resources? JSON:API is a specification that answers all of this once, so your team (and your clients) stop arguing about envelopes and start building. Adopt it and a lot of design debate simply disappears.

The document structure

A JSON:API response wraps data in a consistent envelope:

json
{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API explained",
      "published": true
    },
    "relationships": {
      "author": { "data": { "type": "people", "id": "9" } }
    }
  }
}

Every resource has a `type`, an `id`, its `attributes`, and optional `relationships`. Collections put an array in data. This uniformity means a generic client can consume any JSON:API endpoint.

Relationships and compound documents

The standout feature is `included` — return a resource and its related resources in one response, avoiding extra round-trips:

json
{
  "data": { "type": "articles", "id": "1",
    "relationships": { "author": { "data": { "type": "people", "id": "9" } } } },
  "included": [
    { "type": "people", "id": "9", "attributes": { "name": "Ada" } }
  ]
}

The client asks for what it wants with ?include=author, and the server returns a compound document. It is the over-fetching/under-fetching solution that pushed many teams toward GraphQL — available within plain REST.

Sparse fieldsets, sorting, pagination

JSON:API standardizes the query conventions too:

text
GET /articles?fields[articles]=title&sort=-published&page[size]=10
  • fields[type] — return only the attributes you need (sparse fieldsets).
  • sort — comma-separated fields; - for descending.
  • page[...] — standardized pagination params.

Because everyone follows the same rules, tooling and clients work across APIs.

A standard error shape

Errors are an array of structured objects, so clients can handle them uniformly:

json
{
  "errors": [
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/title" },
      "title": "Invalid Attribute",
      "detail": "Title must be at least 3 characters."
    }
  ]
}

The source.pointer tells a form exactly which field failed — no custom parsing.

Is it worth it?

JSON:API fits when…Skip it when…
Multiple clients consume the APIA single tightly-coupled frontend
You have many related resourcesA handful of simple endpoints
You want off-the-shelf toolingYou need a very compact, custom shape

The format is more verbose than a hand-rolled envelope, which is the main trade-off. For public or multi-client APIs the consistency usually wins; for a small internal API it can be overkill.

Frequently asked questions

It standardizes how REST responses are shaped — data, relationships, includes, errors, and query parameters — so teams stop re-inventing conventions and clients can be generic.

Both solve over-fetching, but JSON:API is a convention layered on REST (fixed endpoints, include/fields params), while GraphQL is a separate query language with a single endpoint. JSON:API keeps REST's caching simplicity.

It is more verbose than a minimal custom envelope. That structure is the cost of its consistency and tooling — worth it for multi-client APIs, often overkill for a small internal one.

Try JSON Formatter

Format and validate your JSON:API response payloads.