Skip to content

Public API contracts (JSON + schema layers)

Problem

JSON’s flexibility is a gift for browsers and integrators. It is also a curse for accidental breakage. Fields appear without notice. Types drift. One example is "1" versus 1. Renames ship without a version bump. Saying “we use JSON” is not a contract.

A contract is a machine-checkable agreement about shapes, types, and allowed changes. Public APIs need an external schema and process. That process should be as strict as IDL cultures. The artifacts are different. In other words, text on the wire does not remove the need for governance.


Short answer

For public or cross-organization HTTP APIs, pair JSON with a published contract. Use OpenAPI and/or JSON Schema, or an equivalent. Add server-side validation. Add consumer-driven or contract tests. Add a versioning policy. See versioning in the wild.

  • OpenAPI is a widely used document format. It describes HTTP endpoints, parameters, and body shapes.
  • JSON Schema is a vocabulary for describing what a JSON document is allowed to contain.
  • Server-side validation means the server rejects illegal bodies early. That happens before business logic runs.

Choose JSON libraries for performance and correctness. See implementation variance. Do not skip the contract layer because the bytes happen to be text. A binary dual stack is optional. It must be earned. See case: public REST.


Constraints that matter

Layer Job
Wire JSON bodies (or dual content types when a second encoding exists)
Contract document OpenAPI, JSON Schema, or Protobuf if you offer a dual stack
Runtime validation Reject illegal bodies early, before business logic runs
Tests Provider checks and consumer-driven checks
Process Review, deprecation windows, and a changelog

This matters because a beautiful OpenAPI file that no one validates against is documentation theater. It is not a contract.


Decision frame

Need Action
Third-party integrators Publish OpenAPI; keep URLs stable; write a deprecation policy
Type-safe clients Generate clients from OpenAPI, or offer dual Protobuf for selected clients
Rapid internal-only iteration Still validate; shorter deprecation windows may be acceptable
“Schemaless for agility” Accept silent client breakage—or stop claiming the API is stable

For example, suppose partner companies build against your API. A field rename without a version is an outage for them. That is true even if your server still “works.”


Failure modes

Mistake Outcome
OpenAPI goes stale relative to the server Documentation lies; clients fail in surprising ways
Validation only in one gateway Alternate entry points drift from the contract
Everything is optional There is no real contract
Breaking change without a version Integrator outages
PII in documentation examples Documentation becomes a leak surface (payload surfaces)

Real-world sketch

A fintech publishes OpenAPI 3. It generates TypeScript and Kotlin clients. Continuous integration fails if the server’s request models drift from the specification. A “quick” field rename without a version bump is blocked. Later performance work swaps Python JSON libraries using the Dashboard. That work does not touch the public contract at all.

In other words, the contract stayed stable while the implementation improved. That is the separation you want.


In this suite

Resource Role
JSON-family Dashboard slice Pick implementations per language
Categories JSON versus other families
Using this suite Fair comparisons inside a family

Experiments

Question: Is the public wire contract hard enough (schema, OpenAPI, or JSON Schema), and what breaks if we only “use JSON”?

Setup

  1. Collect public endpoints and current docs. Those may be OpenAPI or ad hoc examples.
  2. List client languages and critical fields.
  3. Prepare one proposed additive change and one breaking change.

Procedure

  1. Validate production samples against the published schema. They should pass.
  2. Ship the additive change. Confirm old clients still work.
  3. Attempt the breaking change behind a new version or content type. Confirm the old route is unchanged.
  4. Check error bodies for accidental internal leakage. See payload surfaces.
  5. Optionally compare JSON libraries for the server language. Do this after the contract exists.

Decision rule

  • No machine-readable contract plus multi-party clients is insufficient. Add a schema before optimizing codecs.
  • Run performance experiments only among codecs that honor the published contract.

Metrics

Metric / signal Role
Schema coverage (percentage of endpoints with a formal schema) Primary
Contract-test pass rate in CI Enforcement quality
Breaking-change escape rate Process quality
Client SDK regenerate success Contract usability
Suite JSON deser_median_ns and size Secondary server cost
mean_fidelity Implementation correctness

Conclusion style: “OpenAPI and JSON Schema are required; breaking changes use content-type versioning.”


What this suite cannot tell you

  • OpenAPI style-guide politics inside your organization.
  • Whether to use URL versioning versus header versioning.
  • Partner communication reliability agreements (service-level agreements).

Common mistakes

  • Treating JSON Schema as optional documentation only.
  • Generating OpenAPI from code without review. That creates noise and accidental breaks.
  • Different field names in Android versus web clients “by accident.”

Key takeaways

  • Public JSON needs a hard contract process. Good intentions are not enough.
  • Validation and tests enforce what prose promises.
  • The suite helps you choose JSON libraries. It does not decide whether a contract exists.
  • Dual binary APIs are additive products. They are not a substitute for JSON governance.