Ask HN: What is your go-to example for a good REST API?

401 points by goostavos ↗ HN
I tend to always look to api.github.com when I need a little inspiration.

Anyone have some good examples of a particularly well laid out API?

188 comments

[ 5.3 ms ] story [ 241 ms ] thread
http://developer.okta.com/docs/api/getting_started/design_pr...

Good error handling, easy to get started, and they provide Postman collections for each API

Nice stuff.

One nitpick: it always feel weird to me to have an error (or any other object) where the attributes are named like this:

    {
        "errorCode": "E0000001",
        "errorSummary": "Api validation failed",
        "errorLink": "E0000001",
        "errorId": "oaeHfmOAx1iRLa0H10DeMz5fQ",
        "errorCauses": [
            {
                "errorSummary": "login: An object with this field already exists in the current organization"
            }
        ]
    }
Why have "error" in there at all?
To make it absolutely obvious everywhere in your code that you're talking about an errorSummary, not just a summary?
Stripe. Their docs are amazing too, I always find it a pleasure integrating their API.

https://stripe.com/docs/api

^ Came in to say this. I use Stripe for inspiration on their API, docs, and even the general UI/UX to get a feel for something simple yet elegant.
Jeez, glad I'm not the only who feels Stripe's API is basically the golden standard when it comes to a properly implemented REST API and documentation.
nit picking devil's advocate: not all of the API is documented. There are some features that exists, but you have to know about. Granted, this is intentional. e.g.: "billing_cycle_anchor" in the subscription API.
+1 for Stripe. BlockScore is another one similar to Stripe in terms of docs and intuitive design.
Nooooooooo.

I dislike Stripe's API. There are parts of it that just make no sense.

Say, you want to set a billing date for that fancy subscription. Yeah, just set a trial date until the billing date you want. Oh, and don't forget to charge a prorated difference (by hand, with charges)!

Want to upgrade that subscription? Yeah, cancel that subscription and start a new one. Oh, and don't forget to set that trial again!

Want to cancel that subscription but not until their next billing date? Hahaha, yeah no. You need to cancel now through Stripe and set up a process to cancel on your side. (Not the biggest complaint, but really. If I am having Stripe manage my subscriptions, they should do it all)

And I am sure there are many other details which would also drive me mad.

With all of that said, I think Stripe's API is definitely one of the better ones since my complaints are more functionality / feature requests than complaints about how it is set up.

I agree. Their subscription functionality is half-baked. We're 2 years into using Stripe for subscription management and it's such a hassle to move anywhere else that we keep hobbling along with it.

My advice when starting a SaaS company: think through your subscription software early on, before it's a headache to even think about migrating away.

So you want to set a billing date and then charge a pro-rated amount that first month?

And what do you mean "upgrade"? You can move from one plan to the next and charges are pro-rated automatically for you.

I, too, loath the amount of time we've spent on subscription/billing but I'm just surprised that none of the issues you've listed are really causing any pain for us.

(I work at Stripe.)

Although it’s kind of proving your point that the API could be easier to use/better documented, here are some simpler ways to do what you’re looking for:

* Upgrading a plan (no cancellation needed): https://stripe.com/docs/api#update_subscription-plan

  > `curl https://api.stripe.com/v1/subscriptions/sub_foo -u sk_test_bar: -d plan={new_plan}`
* Canceling a subscription at the end of the billing cycle (no need to handle on your end): https://stripe.com/docs/api#update_subscription-at_period_en...

  > `curl https://api.stripe.com/v1/subscriptions/sub_foo -u sk_test_bar: -X DELETE -d at_period_end=true`
* Anchoring subscription to a date (sorry! :( , this is undocumented but should be out soon): https://stripe.com/docs/api#create_subscription

  > `curl https://api.stripe.com/v1/subscriptions/sub_foo -u sk_test_bar: -d billing_cycle_anchor={timestamp}`
That said, agreed overall that our subscriptions support needs some love. We're starting to spend more time on exactly this, so would love any feedback you (or anyone else reading) are willing to share. I'm eduardo@stripe.com.
Thanks Eduardo. I've interacted with you (I think) a couple times and really appreciate the effort you all put into customer outreach. It is appreciated. I will have my team jot down thoughts on subscription functionality and send it over.
No way!

Thank you so much for the response! Complaining on the internet finally worked! :) I definitely hold nothing against Stripe, I still love you guys.

I opted to just roll my own subscription system and use normal charges periodically as needed.
I did that too, mostly because I am splitting transactions to connected accounts and subscriptions don't play nicely with that functionality, according to the docs.
I recently used Laravel Spark [ https://spark.laravel.com/ ] to manage all the subscriptions and I really love it! Before I had to do it all by myself and it was a nightmare and so much time taken away to develop the real app. I highly recomment it for any SaaS product. It gives you a huge jumpstart and you can concentrate on developing just your app. Btw, it supports both Stripe and Braintree.
Also, the provided Java client is garbage (you need to put all the arguments into an untyped hashmap that corresponds to the JSON, WTF?).

And why are there separate clients for Java and Android, which both use the same namespace differently?

And why do I need to set the API key as a global for the general Java client, while the Android client (sensibly) lets me give it as a constructor argument?

-1 for Stripe. The API is designed without any thought how the use cases need to use it. Leaks the JSON structure of the document to the client. This breaks your code when they change the JSON structure.
Well, all code depending on JSON presumably breaks when that JSON changes. That's what versioning is for.

What do you mean by "Leaks the JSON structure of the document to the client"?

I'm not sure what you mean about changing the JSON structure; the Stripe API is versioned and you have to opt-in to any updates, including breaking changes like removing or renaming keys in the response.
+0.

Some parts are great, other parts not so much. My thoughts echo the other's here.

I feel like their API isn't super uniform in a lot of the ways it's integrated, but I will give them a +1 for allowing very easy versioning.
Even better is the realtime support on their IRC channel.
Sadly, Stripe API is not so great :(

It seems like the API is way too complex to do certain operations. Especially some very common use cases: for example, how to apply discount for next year for customers who already have subscription (we wanted to emulate how Comcast always gives you discount if you want cancel and took us weeks to make that working ...). I think they do want to fix all these issues but API is not designed to be easily expandable.

It's actually very hard to find a decent REST API :(

My points here are the following:

1. Think very very hard about how people will use your API <-- this is critical. This also includes operational characteristics of your API (performances, how often it is going to be called, optimization, etc.)

2. Make API easily expendable. Especially relationships between models. Sometimes, it is ok (or even better) just to organize it as "SQL wrapper". Like SOQL by Salesforce - but that again depends on number 1.

(comment deleted)
I came here to say this. I recently built a pretty tight integration between Trello and our app, and using the API was quite pleasant. The documentation isn't stellar (it has examples for requests, but not responses, s you need to use trial and error), but everything is standardized, so once you figure out the logic, you're golden.
I actually found Trello's API to be one of the worst most non-compliant restful API's I've seen. Nothing about it is restful with the extra actions they have on resources. It's hard to follow. The docs are sub-par too.
Care to contribute one you do find appealing?
I like stripe / twilio a great deal.
I love Trello and have built a few things on their API but have to agree the API docs are painful, hard to navigate.

Also, what's up, homie? Hope you're well.

I interviewed with Trello and one part of my interview was building a super simple app in an hour using their API. As far as APIs go, and never having used Trello's API before, I found it to be fairly intuitive and documented well enough for me to skim quickly to needed information. I completed the task with time to spare, and only choked a bit on the authentication. If you don't like Trello's API, give the AWS API a shot!
Are we just talking about API documentation? Stripe's the obvious go-to for that, but for big business stuff I was pleasantly surprised with HubSpot's API and documentation. Their own UI uses the API, which means debugging a lot easier I think: http://developers.hubspot.com/docs/overview
Follow up. Anyone care to recommend a good book or reference on good design of REST APIs?
My employer (Apigee) makes a good introductory ebook on this topic. Be forewarned this is a huge topic with many (strong) opinions on what 'good' REST actually is.

http://apigee.com/about/resources/ebooks/web-api-design

I can vouch for this. It really helped me when I was getting started with REST APIs.
REST in Practice[1], Building Hypermedia APIs with HTML5 and Node[2] and Designing Hypermedia APIs[3].

1. https://www.amazon.com/REST-Practice-Hypermedia-Systems-Arch...

2. https://www.amazon.com/Building-Hypermedia-APIs-HTML5-Node/d...

3. http://www.designinghypermediaapis.com/

+1, if you have to do REST, this is the book.

Our book study group covered this book a few years ago. This book is rational, its advice actionable.

Like "Agile", "REST" is merely a pretext to start an argument. Just do what works, focusing on reducing the cost of change (risk mitigation).

Which one? There are three listed.
My bad. #1. I blindly assumed links were all to same book.
I read this after patio11 linked to it. It's an amazing resource, thank you!
Well done. I opened your link, expecting more banal hand waving dogma. Instead, I found myself nodding agreement with most items in your list. Thank you.
+1 for Vinay's post on API design. I came across it a few months ago and it was a brilliant checklist/guide for us developing an API for our web app.
Make sure to read the Fielding Dissertation to understand what REST actually is.
I always found Flickrs api to be easy to use, and well documented
Google Drive's REST API documentation is a good place to start:

https://developers.google.com/drive/v2/reference/#Children

i wish all of their APIs were this nice.
It's ok but once you start implementing things it gets a bit hairy. Mostly because folders aren't really folders in their API, even though they are in every app that uses them. And their search API to find folders is flaky at best, as it's a consequence of the above problem.
Related: anybody have some good examples of a good asynchronous API? This claims to be the standard, but it has confused many of our customers. http://restcookbook.com/Resources/asynchroneous-operations/

To summarize: send a 202 for the initial request, redirecting to a job URL. The client polls on the job URL, which returns 200 with progress information until it's done, when it returns a 303 redirecting to the final output.

One particular problem spot is that many http libraries automatically follow the 303 redirect, and some even follow the 202 redirect.

I definitely think we would have been better off just putting status and final location information as JSON attributes in the body rather than putting it in HTTP response codes and Location headers. Non-standard, but much less confusing for our customers.

If you have to poll then it's not asynchronous. A better design would utilize something like webhooks.
Yes, we have webhooks, and a grand total of 1 of our customers uses them. Setting up an HTTP server just to receive a webhook is a lot to ask.

Long poll lets the polling be efficient.

> If you have to poll then it's not asynchronous.

Says who?

Maybe not "streaming". Maybe not "real time". But certainly asynchronous.

All push models are poll models down an abstraction layer.
And all computations can be modeled as Universal Turing Machines at some level. That doesn't mean it's the most useful level at which to analyze the semantics of what you are trying to accomplish.
Sure but saying something isn't asynchronous because its polling is flat wrong.
The short answer is that there is really no good general purpose way to deal with asynchronous communication in a "restful" HTTP API. All solutions have major drawbacks. This is one of the biggest shortfalls of rest/http in my experience. People tend to switch to other protocols to address these use cases (this is a common reason for adopting message bus infrastructure like Kafka as part of a SOA).
Plaid API! So well done and documented IMHO: https://plaid.com/docs/api/
I like where Plaid is going but it bothered me that they are coy about their pricing.

Typically when a company refuses to say their price or says "Contact Us", that means "Prepare your wallets".

With that said, very economical. I think it was something like $0.10 per account you add. I am looking forward to Plaid expanding what banks are offered since currently they only work with 10 or so (although if they pick you, they give you access to a few thousand more. Not sure the criteria)

(comment deleted)
Hi Madeline - Charley from the Plaid growth team here. Totally get where you're coming from in regards to pricing, we're working on a bunch of improvements to the site, of which pricing is at the top of my list to get on there! So that will be on there soon :)

If you have any other questions, feel free to reach me directly at charley@plaid

Ha! You are actually the person I got in contact with when I complained to the help email.

You were very helpful! I am looking forward to having access to more banks! (If that is in the plan)

> Typically when a company refuses to say their price or says "Contact Us", that means "Prepare your wallets".

This, so much. Especially when it is a developer tool, where the switching cost is high because other software sits on top of it.

> I like where Plaid is going

They're due to get hit with a nasty suit regarding fraud.

I am interested in learning more about this. Can you provide links to more information?
What prices have to do with the subject discussed here?
Not a big fan of Accounts being structured differently based on product.
The Slack API is a thing of beauty

https://api.slack.com/

I think it could use improvement. Look at https://api.slack.com/methods/chat.postMessage and explain how "as_user" makes any sense. And it gets more convoluted depending on other parameters used (IM channels, etc.)

Also, why can't I use a secret key with my basic postMessage script? I have to navigate OAuth2 just to make a post? Argh the pain!

Twilio does a pretty good job as well.
Just curious. What do you think it is that makes twilio a good example of a REST API? Other than the fact that they have one?
It used to always be cited as an example of a good REST API see this same question from 7 years ago and you'll see Twilio is top recommended https://news.ycombinator.com/item?id=867972

Oh and still is today because it's a good API - timeless

From a development perspective it isn't so much the actual API or the structure of it.. but how easy they make it to understand and integrate into it.

They have a plethora of getting started guides and examples that make it really easy to 'hello world' quickly.

You have to actually dig to get to the reference when you first sign up.

Hello world in 30 minutes or less is important for any API program.

OData! So underused. http://www.odata.org/
What is OData? The website does a poor job of explaining it from a high level. The only discernible feature I see is adding "functions" to url's (ex: http://services.odata.org/V4/TripPinServiceRW/People("russel...)

I've seen "OData" mentioned here and there, but I've never understood the difference between OData and a classic REST API.

OData is more or less SQL over HTTP. You get a rich toolbox for selection, projection and transformation of datasets exposed as an OData source (think EBay listings and SQL Server tables and reports), along with the remaining letters of CRUD.
Odata is à standardized rest use case for generaal purpose data access, so client tools can use it out of the box. Something like sql but over http. Some tools that provide odata support: tableau, tibco spotfire, linqpad, excel.

Excel is a nice example, you can have a sheet with data pulled in over odata from any app that supports odata.

I like Stripe, but the design of an API is not always cookie cutter.

A lot has been written on API design that makes for interesting reading.

Related question: Does a REST API make sense for an internal interface? Or is the overhead prohibitive compared to a more specialized interface?

(By internal interface I mean: an interface that is used only by the team that created it)

Maybe. It adds a whole layer of complexity, but it might be worth it. Depends on your team's structure and relevant experience, and on the details of the project.
I'd argue that it removes complexity, not adds it.
I think it's more maintainable and easier to test
It depends on the problem - if the particular interface is semantically suitable for REST, then there won't be any overhead and REST will just be a useful convention on how exactly you should represent it; and on the other hand if that particular interface needs are not suitable for REST then you probably should implement it with RPC, message queues or whatever other option better suits the problem instead of trying to mangle it into REST paradigm.
I like tumblr's api