At a glance
What you need to know.
An API is a contract for performing work across an application boundary. Engineering it well requires agreement on the authoritative record, permitted operations, response meaning and recovery behavior, followed by verification using the clients and identities that will actually call it.
Define the business operation and response meaning
Start with the operation a caller needs to complete, such as creating a service request or reading an authorized order. Specify required fields, identifiers, validation rules and the state established by a successful response. Distinguish a missing field from an explicit empty value and document how corrections or deletions work. Use an interface description such as OpenAPI for HTTP contracts, while verifying that it matches the deployed implementation. Include examples of rejected input and permitted results. Documentation should explain the workflow boundary and acknowledgement semantics, not merely list endpoint names and leave callers to guess whether downstream work is complete.
Design writes for repeated and ambiguous requests
A caller may retry after a timeout even though the first write succeeded. Define an operation reference and the scope of duplicate recognition for commands that create important records. Confirm whether the same reference with different content is rejected, replaces the prior request or represents an explicit revision. Use optimistic version checks where a stale client could overwrite newer state. When an operation starts asynchronous work, expose a stable status resource or an equivalent completion reference. Multiple service writes need reconciliation or compensation according to their business meaning; a sequence of successful HTTP calls does not provide a shared database transaction.
Plan change with actual consumers
Inventory the clients that depend on the interface and the contract elements they use. A field removal, changed validation rule or revised enum may break a client even when the route name stays the same. Prefer changes that permit old and new clients to overlap where practical, and document retirement conditions for incompatible behavior. Test a deployed older client against the new API in an appropriate environment. Preserve error semantics and pagination assumptions during changes. Contract checks help reveal divergence, but they cannot replace testing the user journey that consumes the API. Assign ownership for documentation, compatibility review and provider or library updates.
Make failures useful to callers and operators
Return errors that distinguish invalid input, missing authority, conflicting state and unavailable dependencies without exposing internal secrets. Give callers enough information to choose correction, bounded retry or support escalation. Carry a correlation reference across permitted downstream calls so operators can locate partial work. Exercise a lost response, unavailable dependency and exhausted connection budget. Define timeout and retry behavior that avoids multiplying traffic during an outage. For event delivery, document authenticity verification, replay handling and ordering assumptions. A failed operation should have a durable or otherwise understandable recovery path appropriate to its consequences, rather than disappearing into an undifferentiated error log.
Prove the contract through saved state and client behavior
Validate normal and exceptional operations using representative records and deployed roles. Inspect authoritative state after a write, test repeated delivery and compare a stale-client update with the expected conflict behavior. Review record access across two organizations and verify any exported data follows the same authority model. Load-test the important routes with a documented workload and dependency capacity. Confirm the published documentation, domain path and intended version match the release. Acceptance evidence should connect an actual client operation to the stored result and recovery procedure. A generated specification, a reachable documentation page or a successful status code establishes only part of that contract.
Before you start.
- Define operation meaning, field semantics and acknowledgement states.
- Test record-level access using intended caller identities.
- Specify duplicates, request revisions and stale-update handling.
- Verify old-client compatibility and retirement conditions.
- Provide actionable errors and traceable partial-operation recovery.
- Compare deployed documentation, saved state and real client journeys.
Common questions.
Is an OpenAPI document enough to prove an API works?
It describes the intended HTTP interface. Verification also needs the deployed routes, actual role permissions, validation behavior and stored outcomes to match that description. Test representative callers and failure cases, especially where an acknowledgement precedes asynchronous completion.
Should a client retry every failed write?
No. Business rejections need correction, and an ambiguous timeout may follow a successful write. Agree stable operation references, duplicate semantics and bounded retry rules for the destination. If completion is uncertain, use the contract's status or reconciliation path before repeating an important action.
