Fundamentalsownershipcataloggovernanceconsumersslo

API Ownership and the Catalog

Every API needs an owner, a version, a consumer list, an SLO and a deprecation status that a stranger can find in one place. An API nobody owns is a contract nobody keeps.

Follow the failure

Frame the contract

API design starts with a consumer, a design question and a guarantee — never with a URL.

Design question
For every API in the org: who owns it, who consumes it, what does it promise, and what is its lifecycle status?
Consumers
Engineers deciding whether to call an API (is it stable? supported?), on-call responders tracing a failure to its owner, and platform teams planning migrations across dozens of contracts.
The promise
A catalog answers the four questions — owner, consumers, promise, status — in seconds, turning cross-team API work from archaeology into lookup.
RequirementConsumersResource ModelStyleContractValidationAuthorizationErrorsIdempotencyPaginationVersioningObservabilityEvolutionTrade-offs

The four questions a stranger must be able to answer

Ownership sounds like org-chart bookkeeping until you need it at 03:00. The payments integration is timing out; the caller's on-call needs to know *whose* API this is, whether the current behavior violates its promise (is there an SLO? what is it?), and whether the deprecation warning in the response headers means "migrate this quarter" or "ignore, it has said that for years".

The same questions gate everyday decisions. Before a new integration: is this API stable, beta, or internal-only? Before a change: who consumes it and how much? Before an incident review: what did we actually promise? An org that cannot answer these per-API pays for it in duplicated integrations, accidental dependencies on doomed endpoints, and migrations that start with a spreadsheet-and-Slack census.

A catalog entry — the minimum that makes an API governable
Payments API                          v2 · STABLE
  Owner        payments-platform (on-call: #payments-oncall)
  Consumers    checkout-web, billing-svc, partner-gateway (+14 registered)
  SLO          99.95% availability · p99 < 300ms
  Docs         /docs/payments/v2       Changelog: /changelog
  Deprecation  v1 sunset 2027-03-31 — 3 consumers remaining
  Auth         service identity (internal) · API keys (partner)

Consumer tracking is the half that pays

Owner and SLO are easy fields; the consumer list is the one that changes outcomes, because it is the input to every evolution decision. "Can we remove this field?" is unanswerable without knowing who reads it (see Consumer-Driven Evolution: Telemetry Before Breakage); "can we sunset v1?" is a threat until the list says "3 consumers, all with migration tickets".

Registration must be enforced by mechanics, not by policy documents: credentials issued per consumer, service identity required on internal calls, and telemetry that attributes traffic to registered identities. A consumer list maintained by asking nicely is a consumer list that is wrong. The unknown-caller alert — traffic from an identity the catalog does not know — is the single highest-value signal the catalog produces.

Dependency direction matters too: the catalog should render the graph both ways. "What does checkout depend on?" plans checkout's risk; "who depends on payments v1?" plans payments' migration. Deep chains surfaced by the graph (frontend → BFF → user API → billing API) are latency and availability facts worth knowing before an incident draws the diagram for you (see Composed APIs: Aggregating Other Services).

registered consumerFrontendWeb BFFUser APIBilling APIPayments API v2
UserLLMAgentToolDataDecisionHumanGuardrail

Lifecycle status is a contract clause

Every API sits somewhere on experimental → beta → stable → deprecated → sunset, and consumers behave rationally only when the position is visible. An undeclared status is read as "stable" by every consumer who finds the endpoint — which is how experiments acquire production dependencies overnight. Declare status in the catalog, in the docs, and machine-readably where clients will see it (a header, an SDK annotation), and make status changes an announced event, not a silent edit.

Ownership must survive reorgs. APIs outlive teams; a catalog whose owner fields point at disbanded squads is worse than none, because it gives false confidence. The working rule: every API maps to an on-call rotation that currently exists, and org changes include a catalog-transfer step the same way they include a pager handoff.

Key points

  • Every API must answer four questions in one place: who owns it, who consumes it, what does it promise, what is its lifecycle status.
  • The consumer list is the highest-value field — it is the input to every evolution and removal decision.
  • Enforce consumer registration mechanically (credentials, service identity, attributed telemetry), never by policy alone.
  • Undeclared lifecycle status is read as "stable" by every consumer who finds the endpoint.
  • Ownership maps to a live on-call rotation and survives reorgs by explicit transfer.

Follow the failure

How the contract fails or gets misused, hop by hop — and what it costs when it completes.

  1. 1
    Org → APIs: teams ship contracts for years with no registry; knowledge lives in commit history and veterans.
  2. 2
    Consumers → APIs: integrate against whatever they can reach; some dependencies are known only to the code.
  3. 3
    Team → change: plans to sunset an endpoint; the consumer census takes six weeks of Slack archaeology.
  4. 4
    Census → reality: misses a quarterly batch job; the sunset ships.
  5. 5
    Batch job → quarter end: fails against the removed endpoint; the incident review's first finding is "we did not know they were a consumer".
What breaks
  • Removals and migrations become slow-motion incidents because the consumer set is unknowable.
  • On-call time is spent finding owners instead of fixing problems.
  • Accidental dependencies accumulate on experimental endpoints, freezing them into de-facto stable APIs.

Design, observe, evolve

A contract decision is incomplete until you know how you would notice it failing and how it changes later.

Design the contract
  • • Stand up the catalog with the four fields (owner, consumers, promise, status) before adding anything fancier; a repo of YAML beats a planned platform.
  • • Issue credentials per consumer and require service identity internally, so the consumer list is enforced by access, not etiquette.
  • • Declare lifecycle status machine-readably and treat status transitions as announced, dated events.
  • • Tie every API to a live on-call rotation; make catalog transfer a required step of reorgs.
Observe in production
  • • Alert on traffic from unregistered identities — it means the catalog and reality have diverged.
  • • Dashboard consumer counts per API version; migration progress is a burn-down of the v1 consumer list.
  • • Track SLO compliance per API in the same place as ownership, so the promise and its keeping are one lookup.
Evolve without breaking
  • • A populated catalog turns deprecation from a broadcast-and-pray into a targeted campaign with a named finish line (see [[deprecation]]).
  • • New governance (auth standards, error-taxonomy adoption, versioning policy) rolls out as catalog-tracked migrations instead of wiki aspirations.
What it costs
  • • The catalog is only as good as its enforcement; half-enforced registration produces confident wrong answers, which are worse than known ignorance.
  • • Registration friction is real: issuing credentials per consumer slows the first integration slightly to make every later change faster.

Misconceptions

Claim
“The service mesh / gateway logs tell us who calls what — that is our consumer list.”
Reality
Traffic attribution without registration tells you an IP or a pod called you, not which team owns it, why, or how to reach them before a breaking change. Logs are the audit; the registry is the contract.
Claim
“A catalog is a platform-team luxury for big orgs.”
Reality
The failure it prevents — breaking an unknown consumer — arrives at the third consumer, not the three-hundredth. A README table with four columns is already a catalog.