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)
Declarative friendly makes writing scripts, pipelines so much better because of idempotency. It also pairs very naturally with resource Oriented design.
LROs are applicable to any request that runs longer than a second or a couple of seconds. Having a unified interface can be very powerful for implementing offline task workers and pipelines.
This one is probably controversial as it's makes implementing basic filtering quite a bit harder. I haven't quite seen the issues it's supposed to solve play out in practice but it's interesting nonetheless.
- 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)