I highly recommend anyone to read Google's [AIP](https://google.aip.dev/). There's even a grpc schema linter for it. Put more focus on the resource data design than nitpicking on transport details. I would consider the best lessons to be:
- Optional but supported user defined identifiers, it's so frustrating to work with API that passes you back an identifier.
- String identifier (names) for resources, with some kind of type namespacing, i.e. the prefix in the author's document
- Consistent set of fields (create_time, update_time, annotations, ...)
- Avoid dynamic map (this is a JSON self-inflicted wound)
- Optional but supported user defined identifiers, it's so frustrating to work with API that passes you back an identifier.
- String identifier (names) for resources, with some kind of type namespacing, i.e. the prefix in the author's document - Consistent set of fields (create_time, update_time, annotations, ...)
- Avoid dynamic map (this is a JSON self-inflicted wound)