05 · API Governance & Design Reviews¶
Once an organization has dozens of teams each building APIs, without coordination they diverge: different pagination styles, different error formats, inconsistent auth. Governance is the process that keeps many independently-built APIs feeling like one coherent platform.
A design-first review process¶
Before a team writes implementation code, they submit an OpenAPI spec for review:
paths:
/v1/refunds:
post:
summary: Issue a refund
requestBody:
content:
application/json:
schema: { $ref: "#/components/schemas/RefundRequest" }
A review checklist a governance team applies to every new spec:
- Does pagination match the org standard (cursor-based,
limit/cursorparams, per Level 2 module 1) — not a one-offpage/per_page? - Does the error shape match the org standard envelope (Level 1 error handling module) — not a custom format for this one team?
- Are resource names and casing consistent with existing APIs
(
snake_casefields, plural resource paths)? - Is versioning strategy consistent (Level 3, module 6)?
- Are auth scopes named consistently with other services'?
Catching inconsistency at the spec-review stage, before code exists, is far cheaper than a "fix it later" migration once clients depend on the inconsistent shape.
A shared style guide as the actual standard¶
## Org API Style Guide (excerpt)
- Timestamps: ISO 8601 UTC, field name suffix `_at` (`created_at`).
- Money: integer cents, field name suffix `_cents` (`total_cents: 4250`)
— never a float for currency.
- Errors: `{ "error": { "code", "message", "field" } }` — always.
- Pagination: cursor-based, `meta.next_cursor` — never offset-based for
new APIs.
A written, linkable style guide turns subjective review comments ("I don't like this") into objective checks ("this violates section 3 of the style guide") — faster reviews, less friction between teams.
Linting the spec automatically¶
5:7 error org-money-as-integer "total" must not be type "number" for a currency field
12:3 warning org-error-shape error response missing required "field" property
Automating the style guide as lint rules that run in CI catches violations before a human reviewer even looks at the spec — reserving human review for judgment calls (is this resource modeled well?) rather than mechanical formatting checks.
Federated governance: guardrails, not a bottleneck¶
A common failure mode is governance becoming a slow, centralized gatekeeper every team waits weeks on. The healthier model:
- Automated checks (linting, contract tests) run instantly, in CI, for every team, no human bottleneck.
- Human review is required only for genuinely new patterns (a new auth model, a new resource type unlike anything existing) — not for every routine endpoint addition.
- The style guide itself is versioned and owned collaboratively, not dictated unilaterally — teams that hit a real limitation propose a change to the guide, not a one-off exception for themselves.
Worked example: reviewing a new team's first API¶
A newly-formed team submits a spec for a notifications API before
writing any code.
- Automated lint flags:
sent_timeshould besent_at(naming convention), and pagination usespage/per_pageinstead of the cursor standard. - Team fixes both mechanically — five-minute change, caught before any client integrated.
- Human reviewer flags a real design question: the spec models
"notification preferences" as a sub-resource of
users, but the org has a precedent (from thebillingteam) of preferences as their own top-level resource with a reference touser_id— reviewer asks the team to align, for consistency other teams can rely on. - Spec approved; implementation begins with the shape already validated, no rework needed after the fact.
How It Actually Works¶
API governance enforces its rules the same way a linter enforces code style — as an automated check run against the machine-readable OpenAPI spec (module 4, Level 2) in CI, not as a human reviewing PRs by memory.
A governance tool like Spectral walks the parsed spec's AST and evaluates rules against it:
rules:
paths-kebab-case:
given: "$.paths[*]~"
then: { function: pattern, functionOptions: { match: "^/[a-z0-9-/{}]+$" } }
must-have-error-schema:
given: "$.paths[*][*].responses[?(@property >= 400)]"
then: { field: content, function: truthy }
The first rule's given is a JSONPath expression selecting every path key
in the spec; the then checks it against a regex — a PR that introduces
/getUserOrders instead of /user-orders fails this rule automatically,
the instant the spec is linted, before a human reviewer even looks at it.
The second rule walks every response definition with a status code ≥ 400
and fails the build if no error schema is defined for it — enforcing "all
error responses must be documented" as a structural, not stylistic, check.
Because this runs against the same OpenAPI document that also drives mock servers, SDK generation, and documentation (a running theme across Level 2-4), a single governance failure blocks the same CI pipeline stage that would otherwise publish an inconsistent doc site or generate a badly-shaped SDK — governance and documentation share one source of truth by construction, not by policy alone.
Exercise¶
- Why is design-first review (spec before code) cheaper to act on than reviewing the finished implementation?
- Give two style-guide rules besides the ones shown that you'd want enforced automatically across every API in an organization.
- Explain the difference between what should be an automated lint rule versus what needs human judgment in a spec review.
- A team argues their new API needs offset-based pagination instead of the org's cursor standard, for a genuine technical reason. What's the healthier governance response — grant a silent exception, deny it outright, or something else?