UI bugs are easy to screenshot. Contract bugs are easy to deny.

A field renames from full_name to fullName on a Friday. Mobile still builds. Web still builds. Production still fails for half the clients until someone notices the empty profile header.

Frontends do not primarily break on color tokens. They break when the agreement about data and errors silently moves.

Sealed envelope with indigo thread

If the seal changes without notice, every client is a victim.

What belongs in the contract

  • Resource shapes (required vs optional fields)
  • Error model (code, message, fields)
  • Auth scheme and 401/403 behavior
  • Pagination and filtering rules
  • Idempotency keys for writes
  • Deprecation and version policy

OpenAPI (or equivalent) should be generated or verified in CI — not a wiki page last edited two years ago.

Contract rules diagram

Compatibility rules that save weekends

  1. Additive changes are usually safe (new optional field).
  2. Renames and type changes are breaking — version or dual-publish.
  3. Null vs missing must be documented; clients disagree forever otherwise.
  4. Enums grow carefully; unknown values need a client policy.
  5. Dates have one timezone and format story.

Consumer-driven checks

Keep contract tests where you can: consumer expectations in the client repo, verified against a provider or stub in CI. Even a small golden JSON fixture suite beats “we tested in staging once.”

Errors are UX

Return stable machine codes. Do not overload HTTP 200 with { success: false }. Map validation errors to fields the form can highlight. Log correlation IDs clients can send to support.

Closing

Treat the API as a product with a changelog and an owner. CSS can be hotfixed in an afternoon. A broken contract is a coordinated recall across every surface you shipped.


Need contract tests or an API review for a web/app pair? Start a project inquiry with your OpenAPI file and two clients that disagree.

Version strategies

  • URL version (/v2/) — explicit, cache-friendly
  • Header version — flexible, harder to debug in the wild
  • Dual-publish fields during migration — temporary bridge with an end date

Pick one. Document deprecation windows (for example 90 days) and communicate in a changelog clients actually read.

Pagination and filtering

Specify:

  • Cursor vs offset
  • Max page size
  • Sort stability
  • Filter operators

Ambiguous pagination is a classic “works for page 1” trap.

Auth errors

401 means re-authenticate. 403 means authenticated but not allowed. Do not swap them. Clients implement wrong recovery loops when the contract lies.

Example error object

{
  "code": "validation_failed",
  "message": "Check the highlighted fields.",
  "fields": { "email": "Enter a valid work email." },
  "requestId": "req_123"
}

Stable enough for i18n on the client; human enough for support.