Introducing the 3.1 Maturity Level of REST API Design: JSON Schema-Aware Hypermedia

REST API maturity is often evaluated using the Richardson Maturity Model (RMM), which defines four levels:

  • Level 0 – Single URI, typically using POST for everything
  • Level 1 – Resources identified by URIs
  • Level 2 – Use of HTTP methods to define behavior (GET, POST, PUT, DELETE)
  • Level 3 – Hypermedia controls (HATEOAS)

However, traditional REST maturity models often overlook an important aspect: schema awareness. That’s why I would like to propose a new, unofficial but pragmatic step after Level 3:

Level 3.1: JSON Schema-Aware Hypermedia

This level builds directly on HATEOAS by adding machine-readable JSON Schema definitions directly into your API responses and hypermedia links. This allows clients not only to discover available actions (via HATEOAS) but also understand exactly what data to send.

The Anatomy of a Level 3.1 API

Response Example

{
  "$schema": "https://api.example.com/schemas/user.json",
  "id": "123",
  "name": "Alice",
  "_links": {
    "self": { "href": "/users/123" },
    "update": {
      "href": "/users/123",
      "method": "PUT",
      "body": {
        "$ref": "https://api.example.com/schemas/user-update.json"
      }
    }
  }
}

Key Points:

  • $schema defines URL to the resource’s JSON Schema.
  • body in a link contains the expected JSON Schema for the request body — either inline or via $ref.

Example with Inline Schema:

{
  "$schema": "https://api.example.com/schemas/user.json",
  "id": "123",
  "name": "Alice",
  "_links": {
    "self": { "href": "/users/123" },
    "update": {
      "href": "/users/123",
      "method": "PUT",
      "body": {
        "type": "object",
        "required": ["name"],
        "properties": {
          "name": { "type": "string" },
          "email": { "type": "string", "format": "email" }
        }
      }
    }
  }
}

Why Add a 3.1 Level?

  • Self-validating
    Clients can validate requests before sending them. There is no need to duplicate validation rules between front-end and back-end applications.
  • Self-documenting
    No need for out-of-band docs — clients discover schemas in real time. Pacakges preparing the JSON Schema can also offer preparing OpenAPI specs based on the schema.
  • UI-friendly
    Dynamic form generators can use schema to render inputs. There is plenty of libraries which can render a form based on JSON Schema, sometimes optional UI metadata can be added for UX.
  • Consistent
    Ties in naturally with JSON Schema and OpenAPI tooling.

Caching and Versioning of Schemas

To ensure performance and long-term consistency, clients should cache any JSON Schemas once they are retrieved. Since schemas are often reusable and may not change frequently, caching avoids redundant network requests and speeds up validation and UI rendering. APIs should add Cache-Control headers ensuring that browsers will cache the schemas.

To support safe evolution over time, schemas must be versioned. This can be achieved by encoding version numbers in the schema URL (e.g., /schemas/v2/user.json or /schemas/user.json?version=1.2.3). Versioning ensures that cached schemas will be invalidated once a new API version will be available.

Best practices include:

  • Use explicit semantic versioning in schema URLs
  • Align schema version with API version
  • Avoid breaking changes in existing schema versions

Naming Conventions: Staying Idiomatic

Because this proposal extends HAL, naming should follow HAL conventions:

  • Use snake_case for custom properties (body, body_schema, etc.)
  • Keep _links and _embedded consistent

We chose body as the field name because it is short, intuitive, and always holds a JSON Schema compatible object.

Optional Enhancements

In future versions, we will extend the idea with:

  • Content types (e.g., application/xml) via a content_type property
  • Payloads alongside schema
  • Embedded UI metadata (like input widgets)

Final Thoughts

By adding JSON Schema awareness to your HATEOAS-powered links, you unlock a smarter, more self-sufficient API ecosystem. This 3.1 maturity level invites a world where clients no longer need hardcoded assumptions.

Your API becomes self-expressive.

TL;DR

  • Extend HAL links with a body field containing a JSON Schema.
  • Use $ref for external schemas or inline full definitions.
  • Prefer HAL-style naming (snake_case).
  • Achieve a new level of API self-discoverability and automation.

Welcome to Level 3.1.

Solutions architect, Node.JS developer, Knowledge Analyst

https://www.linkedin.com/in/bartosz-pasinski/

Leave a Reply

Your email address will not be published. Required fields are marked *