Designing a resource model you will not regret in a year
The most common API design mistake is publishing the internal database structure with a thin layer over the top. It works immediately and it couples every consumer to your storage, so the first refactor becomes a breaking change for everybody who integrated. Designing the resources around what a consumer actually needs, rather than around how the data happens to be stored today, costs a little more thought at the start and preserves your ability to change your mind later.
Consistency is worth more than elegance. Identifiers formatted the same way everywhere, timestamps in one format with an explicit time zone, monetary values with an explicit currency and a stated precision, pagination that behaves identically on every collection, and errors with a stable machine readable code alongside the human readable message. A consumer integrating with five endpoints that each behave slightly differently will spend most of its budget on the differences rather than the work.
Decide early what is deliberately out of scope. An API trying to serve an internal service, a partner integration and a public developer audience all at once usually serves none of the three well, because their tolerance for change and their security requirements differ sharply from each other. Separating them, even where they share an implementation underneath, lets each one have an appropriate versioning and deprecation policy instead of a single awkward compromise that satisfies nobody and constrains everybody.
- Resources modelled on consumer needs rather than on internal table structure
- Identifiers, timestamps, currency handling and pagination consistent across every endpoint
- Stable machine readable error codes alongside human readable messages
- Internal, partner and public audiences separated so each gets an appropriate change policy
- Contract generated from the same definitions the implementation uses, so it cannot drift