Overview
Curated: · Written: · Reviewed:
A technical specification is an executable agreement, not a diagram with happy-path JSON
A technical product manager does not need to implement every endpoint, but must be able to test whether a proposed contract expresses the intended product behavior and can evolve safely. Begin with consumers, user outcome, trust boundaries, owners and service-level expectations. Then trace concrete workflows through operations, schemas, states, failures and observability. A polished OpenAPI document is useful evidence, but machine-readable validity alone does not prove that the API is usable, secure, operable or compatible.
For HTTP APIs, review resource identity separately from actions. Method semantics matter: safe means the client does not request a state change, while idempotent means repeating the same intended request has the same intended effect; neither means a request is free, authenticated or automatically retryable. Check status codes, headers, content types, redirects, conditional requests and caching against HTTP semantics. Do not encode every domain outcome as 200 or invent endpoint verbs merely to bypass modeling decisions.
Define the contract at the wire boundary. For each operation specify path and query parameters, required headers, request and response media types, schemas, constraints, examples, authentication, authorization-relevant resource context, success variants and documented errors. Distinguish omitted, null, empty and default values. State identifier stability, precision, time zone, ordering and pagination rules. Examples help people understand but never substitute for schemas and behavioral prose.
Model errors for programs as well as humans. Stable problem types or error codes should distinguish validation, authentication, authorization, conflict, quota, dependency and server failures without leaking sensitive internals. Explain whether the client should correct, retry, wait, reauthenticate or contact support. Retry guidance needs a limit, backoff and jitter, a retryable condition, deadline budget and idempotency protection. A generic 500 with an exception string is neither a safe contract nor an operational strategy.
Authentication establishes a credential or principal; authorization decides whether that principal may perform this action on this object in the current context. A declared OAuth scheme in OpenAPI does not implement either control. Review token audience and scope, object- and function-level authorization, tenant isolation, redirect handling, credential storage, expiration, revocation and logging. Minimize data returned and reject fields the caller may not set. Threat-model both direct clients and upstream APIs whose data or redirects the service consumes.
Compatibility must be defined from the consumer's perspective. Adding an optional response field is often wire-compatible for tolerant readers but can break strict deserializers, generated clients, signatures, snapshots, storage or business assumptions. Removing or renaming a field, changing type, units, meaning, requiredness, enum behavior, ordering or error semantics can be breaking. Protocol Buffers field numbers must not be reused; removed fields and names should be reserved. Test changes against representative consumers rather than trusting a simplistic additive/non-additive rule.
Versioning is a last line of isolation, not a replacement for evolution discipline. Decide what is versioned—contract, resource representation, SDK or behavior—and how consumers discover, negotiate and migrate. Publish deprecation status, replacement, adoption evidence, support dates and retirement authority. Maintain an inventory of deployed versions, shadow or unknown consumers, and dependencies. A version in the URL does not make an abrupt semantic change safe.
Large collections need deterministic pagination. Specify a stable sort and tie-breaker, cursor meaning, page-size bounds, filter interaction, snapshot or consistency expectations, duplicate and omission behavior under concurrent writes, and cursor lifetime. Offset pagination is simple but can drift as rows change; opaque cursors can preserve server flexibility but require validation and expiry behavior. Never expose sensitive internal state merely to make a cursor debuggable.
Caching is part of the contract. Define which responses are cacheable, freshness, validators, variation dimensions, authorization and privacy boundaries, purge or invalidation behavior, and behavior during origin failure. Shared caches can leak personalized data when keys or directives are wrong. A performance requirement that says "add caching" is incomplete without staleness tolerance and consistency consequences.
Reliability requirements need measurable boundaries: availability target, latency distribution, throughput, payload and concurrency limits, deadline behavior, dependency budget, rate-limit semantics and overload response. Averages hide tail latency. Unlimited requests and payloads are an abuse path. For asynchronous operations, specify acceptance, status resource or event, idempotency, cancellation, completion, failure, redelivery and reconciliation; returning 202 does not guarantee work completed.
Observability is a cross-service contract too. Define request or operation identifiers, metrics, structured safe logs and trace-context propagation without treating client-supplied tracing data as trusted authorization. Preserve enough correlation to support users while redacting credentials and personal data. State audit requirements separately from debug telemetry, including access, retention and integrity.
Review a specification with examples and adversarial scenarios: wrong tenant, missing scope, repeated mutation, stale precondition, malformed value, unknown enum, oversized page, partial dependency failure, timeout after commit, concurrent update, duplicate event and old client against new server. Use contract linting, schema validation, generated-client compilation, provider and consumer tests, security tests, load tests and staged production observation. Each catches different defects.
A decision-ready spec records unresolved questions, alternatives, trade-offs, dependency owners, rollout, migration, rollback or roll-forward, success measures and acceptance authority. Normative words such as MUST should identify an enforceable requirement, not add drama. Link product requirements to operations and tests, and version the spec in source control. The goal is not maximal detail; it is a precise, reviewable boundary that lets independently changing teams build the same behavior safely.
