Simple JSON:API for Higher Velocity

As an engineer who values output over ceremony, I often find the full JSON:API specification a bit heavy on the “feeling” and light on the “doing.” While the spec provides great structure, the deep nesting and required metadata can often feel like busywork.

To move faster, I’ve adapted the spec into a simplified version that keeps 90% of the structural benefits while stripping away the friction. Here is how I’m handling it.


0. The “Before”: Full JSON:API Specification

This is what the standard requires for a single resource. Notice the deep nesting and the repetition of metadata:

{
  "links": {
    "self": "http://api.clearthehaze.com/animals/101"
  },
  "data": {
    "type": "animals",
    "id": "101",
    "attributes": {
      "name": "Luna",
      "species": "Canis lupus familiaris",
      "habitat": "Domestic",
      "updated-at": "2026-02-24T14:00:00Z"
    },
    "links": {
      "self": "http://api.clearthehaze.com/animals/101"
    }
  }
}

1. The Core Shift: Flattening the Data

The biggest “win” in this adaptation is removing the attributes wrapper. Instead of nesting properties two levels deep, I bring them directly into the data object.

  • No type property: The endpoint context (e.g., /animals/1) already tells us what it is.
  • Flattened Properties: Data like name or species lives at the same level as the id.

Example: Single Resource (Animal)

JSON

{
  "data": {
    "id": "101",
    "name": "Luna",
    "species": "Canis lupus familiaris",
    "habitat": "Domestic"
  }
}

2. Minimalist Meta

In the standard spec, meta can get cluttered. In this simplified version, I only include meta when returning a list. It is strictly for quantifying the result set.

  • Required for lists: total_count
  • Optional for pagination: pageper_pagepage_count

Example: Collection with Meta

JSON

{
  "data": [
    { "id": "101", "name": "Luna" },
    { "id": "102", "name": "Felix" }
  ],
  "meta": {
    "total_count": 52,
    "page": 1,
    "per_page": 2
  }
}

3. The Omissions

To keep the payload lean and the implementation fast, I’ve explicitly removed:

  • Links: No selfrelated, or pagination links. URL construction is handled by the client via IDs.
  • MIME Type: We don’t need application/vnd.api+json. Standard application/json works perfectly and is more compatible with default toolsets.

Summary

By ditching the ceremony and focusing on the data, we get a predictable, scannable API that doesn’t require a map to navigate. It’s about accomplishing the transfer of data with as little overhead as possible.