SA-201b · Module 1

APIs as Contracts

4 min read

An API is not a technical artifact. It is a contract between your system and every system that depends on it. When you change an API response format, you are not making a code change — you are breaking a promise. Every consumer that built their integration on the assumption that the field "created_at" returns an ISO 8601 timestamp will break if you change it to a Unix epoch. The technical debt of a broken API contract is not measured in code. It is measured in trust.

  1. Design for the Consumer The API exists to serve its consumers, not to mirror your internal data model. The consumer does not care about your database schema. They care about getting the data they need in a format they can use with the fewest possible calls. Design from the outside in — start with what the consumer needs and work backward to your implementation.
  2. Version from Day One Every API should be versioned from the first release. /v1/resources is a commitment to backward compatibility. When you need to make breaking changes, /v2/resources provides a migration path while /v1 continues serving existing consumers. The cost of not versioning is discovered on the day you need to make a breaking change and realize every consumer must update simultaneously.
  3. Document the Contract An undocumented API is an undefined contract — consumers will build on assumptions, and those assumptions will diverge from your implementation. OpenAPI specifications, request/response examples, error code documentation, and rate limit descriptions are not optional. They are the contract terms.
  4. Fail Predictably When something goes wrong, the error response should tell the consumer what happened and what they can do about it. A 500 error with no body is an abdication. A structured error response with a code, message, and remediation guidance is a contract that accounts for failure. Design error responses as carefully as success responses.