Don't be overwhelmed by this though -- API design isn't an exact science. It's also very opinionated.
Personally, I would just start reading actual API documentation (GitHub is a great place to start -- their API is a joy to work with). Find things you like and don't like about it and try to figure out why those decisions were made.
This would be a good related subthread: links to API docs for what people consider to be both great, and terrible, APIs.
At least the great part has happened:
https://news.ycombinator.com/item?id=867972
There was one _much_ more recently (a week or two ago), but funnily enough the only one I can find is ~2.5k days old..
Related - best documented:
[1] https://news.ycombinator.com/item?id=868102
[2] http://web.archive.org/web/20090520234149/http://chaos.troll...
People get into really philosophical discussions around versioning, resource structure, etc... but in reality think about what makes you like the APIs you like over another alternative. Then think about what you would do to make it even easier to use/integrate with.
There also with some APIs is the tradeoff of easy integration and long-term flexibility.. things like that.
Everyone has different recommendations - dont get discouraged by this.
Make sure also to look into newer standards like JsonAPI if they are suitable - last time i tried to use it the tooling around it was still not strong enough and i decided to go w/ simpler custom api.
Assuming it has to be a restful api (vs graphql) and assuming you want to create an api for multiple kinds of clients (that's the the harder part) - Here my personal TL;DR:
- Autogenerate your docs with your tests
- Do versioning in URL (easier to route/cache/etc)
- Worry about caching (a lot)
- Personalized info only in isolated namespace, rest is fully cacheable
- Never embed personalized information (eg not `{ post: { user_has_commented: true } }`
- Never nest data (not `post: { author: { … } }` but reference only `post: {author_id: …}`)
- Embed referenced objects only by whitelist
- Never nest routes (not `/posts/343/comments` but `/comments?post_id=232`) filtering tends to become more complex
- Use public feedback tools (eg github issues) for your user questions/complains - so it can become searchable for people with similar problems
hth - happy to answer some of those in detail if useful
As said - highly subjective opinions - i am sure others might disagree w/ some of the points
I'm creating a huge API on my dayjob and we have nested A LOT. So many levels of nesting, the responses have become too big.
Yet, the clients refuse to call additional endpoints and always insist on this. And it _does_ make sense for them to make 1 call and retrieve all information they need.
How does everyone handle this on REST?
(I know GraphQL is a solution.I'm wondering how people use REST API's)
This eventually can become the basis of your test harness. In fact, every time I write my tests, I end up writing a client library...
{
posts: [ /* 100 records */ ],
authors: [ /* 3 records */ ]
}
Each post references the author by ID only and all required data is sent in one API call.This is a bit of a contrived example but with a structure like /comments?post_id=232, a developer might mistakenly assume comments are independent resources and not explicitly tied to posts when, in reality, there are can be no comments without posts. In this case, /posts/343/comments is much more intuitive.
The way we ended up handling it was forcing ourselves to limit sub-resources to a maximum of 1 level deep. So /posts/343/comments was allowable but something like /posts/343/comments/23/author was not allowed.
Problem with nesting is that very rarely your resource classes will make an acyclic graph. Even in your example '/posts/343/comments/23/author' resource class AUTHOR may be a child of either comment or the post itself. And if a user wants to view all posts by particular author? Intuitive use might as well be '/posts/343/comments/23/author/posts/123/comments' ad infinitum :)
Such problems can be solved by providing an endpoint for each distinct resource class and making it search provider. In your example case 3 endpoints are needed: /post, /comment, /author, all accepting other two as search parameters, e.g. /author?comment=123456 or /author?comments|id=123456 (inspired by FHIR).
you end up w/ a lot of filters very quickly and related post id will be just one of them
also linking it to another resource usually involved expecting defaults (default ordering, default display, pagination etc)
if you stay "flat" this tends to be less of an issue when usecases become more complex
However, the argument being made here is that you may not want to expose post comments as sub-resource of a particular post, but rather as completely separate resource.
And there is a point to that. Suppose you serve the post content as a static content, and comments from some application (octopress + disqus style). The latter format allows you to route anything matching `^/posts/(.*)` directly at web server level without touching application server at all. If you decided to use the former, then your infrastructure becomes dependent on your API structure. Not very nice :)
Until you hear from an iOS developer that it is a huge pain trying to figure out if the user has left a comment on an item or not and including this little flag would save tons of time.
you can just add it as separate key (similar how you embed eg user objects)
``` posts: {…} interactions: { commented_on_posts: [1212,12,1212,121] } ```
btw most people over estimate this problem the _total_ amount of user interactions is usually very small
in almost all cases you could download it once at boot for the user.
In Stripe's case, I normally find an initial integration is a better experience than most payment services. The API is reasonably designed and well documented.
However, I also find Stripe integrations are effectively impossible to maintain or update over time. Older API versions aren't documented anywhere I can find, only the current one. There are decent changelogs with warnings of incompatibilities, but you can't write an automated integration test suite. I've never found any documentation that explains how their versioning actually works, what is affected, and how to revert if you update and there's a problem.
In practice, that means older versions of the API aren't fully supported indefinitely, nor is there a safe, systematic path to manage an upgrade to a newer API version. For that reason, we normally treat Stripe integrations as write-only code, where once you've got something written, tested and into production, it's never touched again (short of a serious security issue or the like, obviously).
How to Design a Good API and Why it Matters (Josh Bloch): http://static.googleusercontent.com/media/research.google.co... https://www.youtube.com/watch?v=aAb7hSCtvGw
He keeps writing like he's an expert and I am still waiting for evidence to back that up,
1. Restful API with WCF - https://msdn.microsoft.com/en-us/library/dd203052.aspx
2. Restful API using WebAPI - https://github.com/Microsoft/api-guidelines/blob/master/Guid...
3. API via dll - https://www.amazon.com/Framework-Design-Guidelines-Conventio...
This is a must watch and encapsulates good design and theory: https://www.youtube.com/watch?v=hdSrT4yjS1g
Good API design, if you are trying to learn from zero, comes from learning from good examples.
These are some of my favorites APIs by design
+ Stripe
+ Twilio
+ Slack
+ Stormpath (fd: I work here)
There is a lot of work that goes around the API design to make it a great API (examples, documentation, live samples, etc)
It falls into the category of non-web API. It's a good read and I think it carries over to web APIs quite well.
Many of the comments here take API to mean an HTTP exposed API (REST), but API stands for "Application Programming Interface"
It is much more generalized than APIs designed for HTTP consumption.
These days the unit of work is very often some HTTP-exposed service rather than a platform library, or an interface to hardware or the like. But, I'll join your point and say there aren't too many (recent) generic resources about how to design non-HTTP APIs, since the idioms and patterns tend to be language-specific.
The code examples almost become irrelevant because they make the patterns so clear.
If you're talking about REST APIs, then the best book I've come across is RESTful Web APIs by Leonard Richardson and Mike Amundsen:
It actually shows you how to do REST properly, not that shoddy knock-off REST that some people push, where you have to document all your URI structures and hard-code them in your clients. There's solid examples that you build upon throughout each chapter, and jumping off points to standardisation work like JSON-LD etc.
Indeed the only real negative I've seen is people going out of their way to make it REST and in the process adding needless details, or requiring me to set a bunch of options on my HTTP request. Hint: setting a bunch of headers and a verb is not easier than passing some querystring params.
In my experience, the "shoddy REST" the original commenter is talking about usually involves developers ignoring the design principles behind HTTP and trying to pretend like they can't or don't need to map their organization's domain model to HTTP's resource model. This typically happens because they either don't understand how to do this, don't have time, or think that the effort involved to rethink their model isn't worth the effort.
What they end up with is a cobbled-together mess of endpoints that perform unintuitively specific functions constructed in the language of a system that wasn't designed to work that way.
A really good example of this might be a blog API. Which is better?
POST /entries/<id>/publish
or
PATCH /entries/<id> with a request body of { published: true }
The POST seems more immediately intuitive to the API developers, because they can just add all publish-related tasks in the publish route handler or controller and call it a day. But the PATCH is more immediately intuitive to the API consumer, because they probably understand that entries have a "published" field (this gets more into hypermedia and semantics and beyond the scope of this post), and that PATCH allows them to change a field, and that if "published" is true then the entry is live.
A good analogy is trying to construct your own special-purpose language using English words, but with totally new meanings and purposes for each word, then expecting to communicate with others in this language. It superficially looks like English, but cannot be understood without volumes of documentation explaining how it is different.
I cannot recommend this book enough. Read it, read it again, take in everything it is trying to say and try as hard as you can to understand it.
There is a whole world of awesome and tragically misunderstood tools in the book.
https://www.amazon.co.uk/Framework-Design-Guidelines-Convent...
>The number of APIs produced by Google’s various business units grew at an astounding rate over the last decade, the result of which was a user experience containing wild inconsistencies and usability problems. There was no single issue that dominated the usability problems; rather, users suffered a death from a thousand papercuts. A lightweight, scalable, distributed design review process was put into place that has improved our APIs and the efficacy of our many API designers. Challenges remain, but the API design reviews at scale program has started successfully.
http://delivery.acm.org/10.1145/2860000/2851602/ea849-macvea...
On my last project I found myself revising the API surface twice as a result of doing so.
and the accompanying slides: http://static.googleusercontent.com/media/research.google.co...
I've recommended this talk to numerous colleagues over the years, always with extremely positive feedback. And I've re-watched it myself 3 or 4 times as a refresher before starting out on a new API.
It's easily in my top ten favourite programming talks. If anyone hasn't watched it, I can't recommend it highly enough.
This page is a more concise overview of the levels: http://sweng.the-davies.net/Home/rustys-api-design-manifesto
There is also this Medium post: https://bradfults.com/the-best-api-documentation-b9e46400379...
It documents a number of things we've learned building, using, and supporting APIs at Twilio, major banks, major hotel chains, and others. It's 100% driven by practices in the wild, not academic or theoretical info.
The docs have similar content: https://swift.org/documentation/api-design-guidelines/
Restful service design - https://drive.google.com/open?id=0B8qU9uFznmLsUEZ3TEFMbDZQcU...
Notes on RESTful APIs - http://wooptoo.com/blog/notes-on-restful-apis/ - written by yours truly some years ago
It becomes interesting once you start to use/read "hard" or "shitty" APIs. You may discover that many of them aren't either of their given labels, but that they solve really complex problems, that can't be solved (even) more intuitively.
- Good summary of best practices for documentation: https://bocoup.com/weblog/documenting-your-api
- Tips for good api doc design: http://blog.parse.com/learn/engineering/designing-great-api-...
A good starting point in this area is Steve Yegge's famous platform rant:
http://www.aristeia.com/Papers/IEEE_Software_JulAug_2004_rev...
http://apigee.com/about/resources/ebooks/web-api-design
I was impressed with the Rackspace Cloud API and documentation too. Especially their authentication services.
*Like a freshman preaching Rand
https://pages.apigee.com/rs/apigee/images/api-design-ebook-2...
This page was started by a dozen or so researchers back in 2009 and has a list of publications on the subject.
C Interfaces and Implementations: Techniques for Creating Reusable Software By David R. Hanson
Read their stuff for what to NOT do. Use it for real torture.