- [1] broadly, we should make APIs as simple as possible for the users requirements. not necessarily less endpoints to call but more straightforward
- [2] “make the common case awesome, and the advanced case possible”. this means the common case should be the most obvious way to use your API, advanced cases should be sufficiently hidden from a typical user only interested in the common case
- [3] good apis are easy to learn and predictable
- [4] names should be expressive (explain themselves fully), simple (the minimal length to do so), and consistent (the same name is always used to refer to the same thing)
- [5] always use american english since it’s the most commonly used language in global code, for plurals e.g persons or people, check the standard accepted pluralisation in american english, in this case people
- [6] avoid prepositions like “with”, “to”, “for”. they are usually a smell because it limits future scope, e.g. ‘books_with_authors’ means we will have to add a ‘books_with_publishers’ and maybe even a ‘books_with_authors_and_publishers’
- [7] use the single form for resources (i.e. book not books)
- [8] variable name conventions (snake case/camel case/kebab case) aren’t so important as long as they are consistent
- [9] avoid deep hierarchies (and inheritance), move to referential structures
- [10] always use positive boolean values
- [11] represent large or floating point numbers in strings, utf8 normalisation form C (to avoid equality errors with different byte representations of the same unicode strings)
- [12] instead of enums to represent data, strings are preferred. this way if a new value is added the client code will see a descriptive name in an error rather than a number. an example of this is mime types
- [13] list values should be a single homogenous primitive data type, usually strings
- [14] UUIDs for resource identifiers. you can have front facing shorter versions with base64 or however that worked with the hyphens if they might need to be read on a support call
- [15] never have indexes in web apis to interact with resources in a list. web apis should always be idempotent
- [16] REST
- [17] if we ever use custom methods, we use a POST request.
- [18] custom methods should also avoid prepositions e.g. ‘POST /launchRocket’ over ‘POST /launchRocketToMars’
- [19] resources can be made for promises and schedulable jobs
- [20] associated resources should be referenced with a string ending in id e.g. “author_id”
- [21] for polymorphic resources (text message, image message) we use a polymorphic (in this case message) interface and a type field that accepts a string (not an enum)
- [22] dry run option for results on batch actions, counts, result subset
- [23] for anonymous aggregate data we use a custom write method for “entries” (rather than resources because we can’t perform methods on specific entries - we can’t get them back)
- [24] pagination for large data, page token and max page size. don’t use offset/limit params since that leaks implementation details and the underlying data representation might change, while the API will still have to support those same operations
- [25] filters should be strings with a certain syntax (like SQL) not functions, this way they are more readable and can change in the future without the baseline API changing, i.e extended with prefix matching without causing a change in the API
- [26] for versioning, start on v1, then collect breaking changes — once you have enough, make a v2. continue this and if you see that an API version has very few to no users anymore, deprecate it. alternatively, semver (major.minor.patch)
- [27] soft deletion with a delete flag or something like that with a custom undelete (expunge) method. also expire time e.g deleted automatically after 30 days, reset after undeleting (expunging)
- [28] resource revisions accessed with @ (like GitHub issues), don’t soft delete revisions