There are 2 that I'll never forget:
- The first one was designing an API in french (get /écureuils instead of get /squirrels). As I later introduced design concepts coming from Hydra that were in english, I ended with a totally awkward "frenglish" API (It was the topic of my first post on my blog http://apihandyman.io/why-you-must-design-your-private-api-in-english/
- The second one was to focus too much on the resources or the data should I say (/customers or /accounts) and totally set aside the use cases that needed to be fulfilled by the API. It resulted in a very fine grained API needing to endlessly do the 5 same APIs calls to do a simple thing. That's why I in the book I focus on analyzing the needs BEFORE designing data models :-)
Regarding the second part of the question "how to overcome these mistakes", these 2 mistake represents 2 types of design problems.
- The first one, the french design, is the perfect example of shitty-design-you-have-to-live-with. Indeed, while not as good as it should have been ,this design was doing the job and as the API was already consumed, it was too late to change it because it would have been a breaking change for consumers. We had to wait some opportunity like introducing totally awesome new features to make the move to a v2 full of breaking changes worth the cost for consumers.
- The second one (design not fulfilling needs efficiently) was solved by adding a new operation doing what was really expected inside the existing API (without introducing any breaking change). As it was a pain-in-the-ass solver, consumers were happy to make the change (to avoid doing the same 5 API calls). And ff some of them don't want to do it they could still use the original operations.