API Design Principles
Consistency
Promote usage by consistent language wherever possible.
- Consider using names provided by schemas in schema.org. They’ve thought through conceptual pitfalls you may not have (e.g. firstName becomes inaccurate outside of Western culture; givenName is better).
- Use standard names for common operations like sorting, filtering, searching, paging, and projecting.
- Use ISO formats for dates, currencies, country codes, and standard representations for types like Money.
Note: referring to schema.org for naming guidance does not imply following schema.org naming conventions (e.g. camelCase vs snake_case) which are defined elsewhere in this document
Usability
Build design affordances into your API.
- Aspire to make it so developers “don’t have to think” by making the API as easy as possible to consume, even if that makes the implementation harder.
- Always send JSON keys back for null values rather than stripping the key out of the payload (avoids existence checks by clients).
- Always send a response body on create and delete operations so that the developers can see the full resource representation after creation and after deletion.
- Use a standard error convention, and be as specific as possible when reporting the error.
- Define the HTTP Response Codes used and the purpose/meaning behind each one.
- Don’t mutate the meaning of standard error codes.
- Don’t return 200-with-an-error-payload.
Evolution
APIs should be built with an eye towards future evolution, without forced upgrades of clients.
- Avoid returning top-level raw arrays, which don't allow non-breaking evolution to add metadata (like paging).
- Implement pagination for all result-sets that may grow without bound (i.e. search results).
- Turn off all strict deserialization.
- Adding fields is a non-breaking change (Postel’s Law - be liberal in what you accept, and conservative in what you produce).
- It’s better for the contract to be incomplete than inaccurate.
Encapsulation
Use the API to hide dependency complexity.
- All ids are global, even if the System(s) of Record are federated. The client should not have to care about the origin of the id.
- Treat ids as opaque. There should be no intrinsic meaning in the value of the id.
- Avoid leaky abstractions by mapping System of Record field names and values to meaningful values.
Externalization
Build the API with the expectation that it will be consumed externally.
- API must be derived from the domain model and the intended use-cases it is meant to support.
- API contract must meet the need of the customer.
- Externalization of the contract must not require reimplementation, or a change in service contract.