Ask HN: What is your go-to example for a good REST API?
Anyone have some good examples of a particularly well laid out API?
Anyone have some good examples of a particularly well laid out API?
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.
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.
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.
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.Thank you so much for the response! Complaining on the internet finally worked! :) I definitely hold nothing against Stripe, I still love you guys.
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?
What do you mean by "Leaks the JSON structure of the document to the client"?
Some parts are great, other parts not so much. My thoughts echo the other's here.
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.
And in 2008/9 their API was always given as an example for REST APIs done right and it's still true today
They do an excellent job of providing a clear and robust API. I work there (but not on the engineering team), and still genuinely love the API itself.
Sorry for not pointing to specific examples, but things I really love to see in an API:
- Fully qualified URLs in all links (makes navigating and discovery in Postman a breeze).
- Ability to expand resources represented by links (even deeply nested resources) so I can get exactly what I need in a single request.
- The ability to specify what parts of the response resource to include / exclude, allowing me to slim the response to exactly what I need. More important in clients running on mobile devices where slender responses make a noticeable performance difference.
- The exact same URLs (including hostnames) for the test and production API, the difference between the environments being determined by the credentials used in the request. This greatly simplifies code in the client test and production environments.
- Security schemes that allow me to write serverless client applications (OAuth 2 implicit grant). This certainly requires more work by the API developer, but makes it possible to crank out all sorts of useful tools quickly, and massively reduces client IT overhead. This may not be appropriate for all APIs, but could be used a lot more often than it is.
- Along with the above, support for CORS so we don't have to mess around with JSONP and other hacks in the browser.
- If you make me eat your timezone, please please make it UTC. But spend a little extra effort and allow me to pass a timezone in, either as an account settings and/or request parameter (and a simple offset isn't good enough - support actual timezones so daylight saving is handled). It can be incredibly hard to analyze data in responses when you're constantly having to translate the time to your own to give proper context. Timezone support isn't fun but libraries make it pretty easy. This is more important in APIs that provide lots of transactional data.
- Let me attach meta data to resources - it doesn't even have to be a lot. Sometimes allowing me to slip in a handful of bytes removes the need for an entire database on my side.
- Be painfully explicit in error responses. State the obvious, especially in errors that are likely to occur at the beginning of integration such as issues with authentication, content types, payload structure, etc.
So much +1's for this. Even better if I can query for it.
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)
If you have any other questions, feel free to reach me directly at charley@plaid
You were very helpful! I am looking forward to having access to more banks! (If that is in the plan)
This, so much. Especially when it is a developer tool, where the switching cost is high because other software sits on top of it.
They're due to get hit with a nasty suit regarding fraud.
Also, what's up, homie? Hope you're well.
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.
Long poll lets the polling be efficient.
Says who?
Maybe not "streaming". Maybe not "real time". But certainly asynchronous.
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!
1. https://www.amazon.com/REST-Practice-Hypermedia-Systems-Arch...
2. https://www.amazon.com/Building-Hypermedia-APIs-HTML5-Node/d...
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).
The examples are PHP-based and there is an active Slack channel supporting the book.
http://www.vinaysahni.com/best-practices-for-a-pragmatic-res...
Oh and still is today because it's a good API - timeless
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.
Instead of /persons/23/edit, maybe POST /person/23
Instead of /persons/77/delete, maybe DELETE /person/23
Also, verbs are not RESTful. Verbs imply an RPC interface.
RPC (verb):
POST https://<payments-api>/card_authorizations/<id>/capture
REST (noun): POST https://<payments-api>/card_authorizations/<id>/chargesThe REST paper has good ideas, and people are picking and choosing what they want. There is no REST specification that makes HATEOAS mandatory. Maybe Roy Fielding should have written one on top of HTTP to make it clear what it is about instead of writing an dissertation.
How do you represent a link semantically? 100 businesses will have 100 different answers. That's why, by the way, HTML was so ingenious. HTML tags ARE semantic. If Roy came with a core set of tags describing things then people would know how to write basic HATEOAS APIs.
So don't blame the people, blame the absence of a clear specification(and no, the REST paper is not a spec, a spec is normative).
All this shouldn't matter as long as every IS documented. HATEOAS can't replace a good documentation. Today, for most developers REST is about urls, verbs and caching + a few other headers, nothing more.
[1] https://github.com/kevinswiber/siren [2] http://stateless.co/hal_specification.html
The REST API is designed intuitively, just as one would expect.
I've been using it a lot for prototyping and internal applications. Now with the help of native row level security from postgres, it would become also a good choice for production. Or just wrap it behind your gateway.
http://postgrest.com/ http://postgrest.com/api/reading/ http://postgrest.com/api/writing/
I've seen "OData" mentioned here and there, but I've never understood the difference between OData and a classic REST API.
Excel is a nice example, you can have a sheet with data pulled in over odata from any app that supports odata.
(By internal interface I mean: an interface that is used only by the team that created it)
Good error handling, easy to get started, and they provide Postman collections for each API
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?[1] https://kenai.com/projects/suncloudapis/pages/Home
[2] https://www.tbray.org/ongoing/When/200x/2009/03/16/Sun-Cloud
is there a good example of an OPEN SOURCE REST API?
I would like to see how the versioning is achieved, how the versions are incremented, etc?
Bonus points if it is in the Java ecosystem.
Here is an example: https://github.com/wing328/test-java-okhttp
Please pull the latest version and give it a try.
I would suggest you to create separate Github repo for API clients in different languages so that developers can install the PHP, Python, Ruby, etc API clients directly from the Github repo.
You can leverage "git_push.sh" to push the auto-generated SDKs (with doc, sample code) to Github.
Also, they are usually a few months behind releasing API coverage of new features and modules.
Also, it is a bit fiddly having to specify a 'scope' parameter when authenticating yourself for the API otherwise you won't be able to access certain data.
Lastly, I don't like the way there is almost a separate API for the AU and US version of Payroll. I get that they are fairly different beasts, and that they are actually third party systems that have been 'integrated' in, but I wish they had more commonality.
[1] http://www.zettajs.org. "An API-first, open source software platform for the Internet of Things."
- Documentation is complete and concise.
- Responses are consistent (in terms of data structure)
- Status codes are consistent
I really hate this notion. It makes jumping to page 100 of a 345 page result set impossible. You would literally have to follow 100 pages, or have some ridiculously long index with 345 separate links.
I believe that it should be possible for an API to document a URL formula, and rely on the API client to follow that formula to generate a URL.
That's where things get sticky, though, because as far as I know, there's no good standard defined for how an API can document a dynamic URL formula that is programmatically discoverable.
What resources (books/blogs) are you guys/gals looking at that talks about best practices for creating/implementing great REST API endpoints?
I'm an engineer at Lob. We'd love any feedback! support@lob.com.
Hey, wait a minute! Those examples are using test credentials... Your API responds to those curl calls with real output, and the output matches what your documentation says it should be. Okay, that is awesome! Also when I force myself to get rate-limited, my requests fail gracefully with a "429 Too Many Requests" and a descriptive error, which is refreshing. Nice API!
A lot has been written on API design that makes for interesting reading.
If a client starts to construct URIs, then there is a flaw.
Caching doesn't solve the problem of "what if I want to look up the travel time between this other city and this other city via this other means".
Carry on...