Unit 01.01: The contract is the product
The contract is what you ship. Everything behind it can be rewritten; nothing in it can be quietly withdrawn.
Request, response, errors, guarantees
Four sections. The caller writes their code against these and never sees your source.
The code prints a contract for one endpoint.
import json
contract = {
"endpoint": "POST /v1/classify",
"request": {"text": "str, 1-4000 chars"},
"response": {"category": "billing|technical|account|other",
"confidence": "float 0-1"},
"errors": {"422": "request failed validation",
"429": "rate limited, retry after the header says",
"503": "model unavailable, retry"},
"guarantees": ["response always has both fields",
"category is always one of the four",
"no request body is logged"],
}
print(json.dumps(contract, indent=2))
print("\nThe caller writes their code against this, not against your source.")
# Everything inside can be rewritten -- language, model, storage -- as long as
# this holds. Everything here is a promise you cannot quietly withdraw, which
# is why the guarantees list is the part to write carefully.
The guarantees list is the part worth writing carefully. "No request body is logged" is a promise a caller may be relying on for their own compliance position, and it constrains your implementation permanently.
The errors section is what lets a caller write correct retry logic. Without it they discover your status codes in production, one at a time.
The mistake this prevents
The mistake is documenting the happy path and leaving the errors to be discovered. A caller who does not know 429 exists will not back off, and will hammer you at exactly the moment you are struggling.
Takeaway
The contract is request, response, errors and guarantees. Everything behind it is replaceable; everything in it is a promise you cannot silently withdraw.
