| name | api-design |
| description | API contract design: resource naming, error model, versioning, pagination, backward compatibility, OpenAPI.
A predictable interface that evolves without breaking consumers.
Trigger phrases: "api design", "api contract", "api versioning", "openapi", "swagger", "rest contract", "breaking api change"
|
API Design
Goal: a contract the consumer can predict and that can evolve without breaking. Once published, a
public API is a commitment; a breaking change is expensive. Stack-agnostic (REST as the baseline; GraphQL/gRPC follow similar principles).
Checklist
How
- Model the resource — a noun not a verb:
POST /orders (✓), POST /createOrder (✗).
- Status codes: 200/201/204 · 400 validation · 401/403 authorization · 404 · 409 conflict · 422 · 429 · 5xx. Use them meaningfully.
- Error contract — every error has the same shape:
{ "code": "ORDER_NOT_FOUND", "message": "Order not found", "details": [] }
No stack trace / internal detail leakage (overlaps with security-scan).
- Versioning: additive changes in the same version; breaking (remove/rename a field / add a required field) →
/v2.
- Collection: pagination (cursor or offset), filter/sort parameters; a consistent envelope.
- Write the contract — OpenAPI/schema; with examples. Wire the change to
docs-writer, and if breaking to release/CHANGELOG.
Breaking vs additive
| Additive (safe) | Breaking (needs a version) |
|---|
| Add an optional field/endpoint | Remove / rename a field |
| A new optional parameter | Add a required parameter |
| A new enum value (if the consumer is tolerant) | Change a type/meaning, change a status code |
Invariant rules
- A public API is a commitment — a breaking change is not made silently; version + announcement.
- Consistency > local cleverness — a single naming/error/pagination pattern across the whole API.
- The error model is uniform and machine-readable.
- No internal detail leakage — a stack trace / DB error does not go to the consumer.
- The contract is documented — OpenAPI + example; at design time, not after the code.