If this is true about systems — and it is — it's even more true about APIs: good APIs are boring.
https://www.seangoedecke.com/good-api-design/
However, you can't remove or change the types of fields. You can't change the structure of existing fields (for instance, moving user.address to user.details.address in the JSON response).
https://www.seangoedecke.com/good-api-design/
I don't like API versioning. I think at best it's a necessary evil, but it's still evil. It's confusing to users, who can't easily search for your API docs without making sure that the version selector matches the version they're using. And it's a nightmare for maintainers.
https://www.seangoedecke.com/good-api-design/
Of course, adding a new version doesn't double the size of your codebase. Any sensible API versioning backend will have something like a translation layer that can turn a response into any of your public API versions.
https://www.seangoedecke.com/good-api-design/
In short, you should only use API versioning as a last resort.
https://www.seangoedecke.com/good-api-design/
Nobody uses an API because the API itself is so elegantly designed. They use it to interact with your product. If your product is valuable enough, users will flock to even a terrible API.
https://www.seangoedecke.com/good-api-design/
Writing good APIs is really hard.
https://www.seangoedecke.com/good-api-design/
A technically-poor product can make it nearly impossible to build an elegant API. That's because API design usually tracks the "basic resources" of a product. When those resources are set up awkwardly, that makes the API awkward as well.
https://www.seangoedecke.com/good-api-design/
You should let people use your APIs with a long-lived API key. Yes, API keys are not as secure as various forms of short-lived credentials, like OAuth (which you should probably also support). It doesn't matter.
https://www.seangoedecke.com/good-api-design/
Be careful about APIs that do a lot of work in a single request.
https://www.seangoedecke.com/good-api-design/
You should put a rate limit on your API, with tighter limits for expensive operations. Include rate limiting metadata in your API responses. X-Limit-Remaining and Retry-After headers give clients the information they need to be respectful consumers of your API...
https://www.seangoedecke.com/good-api-design/
Almost every API has to serve a long list of records. Sometimes a very long list (for instance, the Zendesk /tickets API can contain millions of tickets). You just can't serve every ticket in a single request. Instead, you have to paginate.
https://www.seangoedecke.com/good-api-design/
You should always use cursor-based pagination for datasets that might end up being large.
https://www.seangoedecke.com/good-api-design/
It's usually wise to include a next_page field in your API list responses. That saves consumers having to figure out the next page number or cursor on their own.
https://www.seangoedecke.com/good-api-design/
API maintainers' primary duty is to NOT BREAK USERSPACE. Never make breaking changes to public APIs.