https://docs.connect.squareup.com/
It was really interesting work and the team was quite committed once we found the right team.
People always asked what does a designer do on an API. It turns out that if the team cares, quite a lot.
Documentation is the obvious one but lots of other things like structuring the actual information, setting up apps, working on API explorers, look at terminology even how the endpoints are thought of and of course, how do you easiest get up and running with the API.
It was surprisingly interesting work from a design point of view.
They are amazing (of course I am talking about the right kinds).
I would generally suggest to hang out with radically different perspectives than your own.
Luckily, in my new company both my partner feel the same way.
Did you use a third party documentation CMS for that, or roll your own internally for all the formatting etc.?
Do you think that the Square API hit the level of design just because of the people involved? Or are there organizational factors that played into it? I.e. was good API design seen at the top as a good reason to take longer with a release? I really want to find suggestions to take into my company.
From the day I started back in 2012 it was clear to me that in order for us to grow functionality to enough verticals in the merchant space we would have to build an API as that was the only way to actually allow for the platform to grow beyond what we could build internally.
It was a hard push for a while though as the focus was in some of the other areas that made us actual money.
The first inception had a pretty strong team but less backup in the organization. We did a lot of great work that never saw the light of day.
Then the last couple of years it all changed and there was suddenly a push to do proper API I was "called into duty" again. This time the foundation was product led rather than tech led and that changed things a lot.
My personal experience was that people just saw API as some technical curiosity rather than as an actual foundation for the business.
Luckily plenty of people in the organization was aware of its importance.
This has changed a lot the last couple of years I think not the least because of Stripes documentation which is almost legendary today.
For some reason, I was always aware of its importance. I even wrote an essay about it back in 2009 and wrote:
"The next big battle is going to be a battle between digital ecosystems; not gadgets, not products and not services.
The most important weapon is going to be the WMCs: Weapons of Mass Connection, a.k.a. the APIs.
These APIs will make it possible for different organizations to have data flow freely between them. Allow for anyone with the right idea to leverage on others’ success without taking anything away from them. On the contrary, the more trusted interpreters you can give access to the data flow, the more robust the digital ecosystem will be."
For example, imagine if all your error messages were basically documentation style prose. That would be a nightmare, and would set you up to a lot of error message refactoring. A better strategy is somewhere in the middle.
When building API end points, I take a different approach by including both messages and message codes, as well as a general "result" code (to make it easy to determine if it's a basic success/error result (also including the right HTTP code)).
An example that I'm working on right at the moment:
{
"result": {
"code": "error",
"message_code": "too_many_user_agents",
"message": "You have sent %s user agents; this is more than the maximum allowed per batch (%s user agents). Please send fewer in each batch."
}
}
The message describes the problem; what they did wrong, what the limit is and how they can fix it so it doesn't happen again.As well as this, the developer can easily check that the response code was an error, and there's the message_code - this will NEVER EVER change for this problem, so a developer could write code to specifically deal with that scenario.
However there's also a human readable message, which may potentially change (perhaps a grammar or punctuation fix, or if it included a URL it might change one day...)
I've found this approach is the best sort of middle ground.
bad request type, see http://company.com/API/ce32h
except that it always seems the company forgets and removes the page.maybe that could be fixed to some degree in a build step
As is having a hook in github which notices that a PR updates your API schema and adds a comment with a checklist of things to be sure you've considered.
For instance, if you build a simple REST interface with a list at /object/ and details at GET /object/1 and changes at POST /object/1, then you're good, right? This is a well-understood way of structuring things?
Well, what if your objects are really simple and someone has to synchronize 100k of them. It's not possible to do that efficiently through such an interface.
The API has to see some use, and it has to be able to evolve as you learn. And you need to be ready to make some sacrifices on your side of the fence, to make the life of the API user easier.
Some of the worst APIs I've seen have been ones designed by a backend developer based upon some vague specifications handed down by a non-technical PO. They were often designed with half of the stuff that was necessary missing, lots of stuff that wasn't necessary and some stuff which made no sense before being thrown over a wall.
The better APIs were 'designed' by the developer who would write the code that would consume them. Even if that just meant an email or a scrap of paper with a few example URLs and snippets of JSON.
* this talk by Jesse Noeller from PyTexas a few years ago: https://www.youtube.com/watch?v=-vZ_E1OO_PY
* the WriteTheDocs community, which is sortof a mashup of traditional technical writers and software engineers. http://www.writethedocs.org/meetups/
* the mailing list GET PUT POST (shameless plug): https://getputpost.co/overhauling-api-docs-with-gocardless-9...
There's also a Django-specific version called "Your Django app is a User Interface": https://www.youtube.com/watch?v=Mnzvjn1v1CY
It almost never is.
Everything about the experience sucks. The documentation is usually a mess and the code flow is usually strange as hell. But I can live with that.
It's the completely opaque error states that kill me. The article dedicated an entire section to it and I hope people take it to heart. When I pass bad data or something you're not expecting give me some clue as to what it might be!
I just spent 60+ hours working on an integration. 95% of that was spent changing parameters and encodings hoping that something would magically fix the 400 I kept receiving back from the server.
It turns out a shared secret had a typo (on my end).
The thing is this bad design is costing that company real $$. Not only was it a frustrating experience for me, I took a couple of hours of their engineers time trying to hunt it down. The lack of error handling made it difficult for them to track the issue down on their side as well.
I'll never forget the first time I touched Twilio's API. Everything was so clear. I had screwed something up, and got a clear message about what was wrong. It was magic.. and the whole thing was up and running in less than an hour.
Give me more of that please!
I use it frequently as an example of how not to build an API. I find it hard to integrate efficiently with it - it got worse from version 2 to 3, although some of the blunders have later been fixed.
You're probably right that the error messages are relatively thorough. Many of the constraints aren't documented in the reference documentation, though, so it requires trial-and-error.
> (in general, always use ValueError and avoid assert).
ValueError is for when,
> an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception
(the docs explicitly note only for builtins, but I'm frankly okay w/ people using it in their code.)
You should not be raising this when you should be raising AssertionError, however, the two conditions are very different; the latter is for conditions that should be true but for some reason aren't. I find these usually crop up when running through a bunch of ifs:
if a:
elif b:
elif c:
else:
# *One* of the above should always match, in this case.
# This branch should never be taken, and it wasn't any fault of the user we're here.
raise AssertionError('good description of the situation')
Attempts to restructure the above are usually fairly bad: you can omit the `else`, but then execution will never take any branch, and if the branches do something like initialize a variable that the code following the branches will make use of, you're doomed anyways, and it's better to bail in an informative manner. You can meld the last elif and else together (i.e., the else just handles case C above), but then it also inadvertently handles unexpected states D, E, etc. too.IMO, AssertionErrors should indicate bugs in the called API. ValueErrors indicate bugs in the caller's use of the API.
(You may choose a less "destructive" method of asserting, such as logging, but in my experience, these get lost, and if you're in an undefined state then you still need to find some way to repair that state, and in my experience most attempts to do so are more trouble than they're worth. It's better to fail earlier and harder and louder, s.t. bugs are discovered and swiftly fixed.)
Yes, I agree with this stance. `ValueError` should be used for user-provided input validation (as well as `TypeError` in some cases). But as it happens, many Python developers use `assert` statements to do input validation, and generally don't provide any error messages in their `assert` statements. I'm suggesting going with `ValueError` (and a nice message) instead.
The great thing about doing usability studies on APIs is that it is easy to mock up a prototype of the API that people can start to code against. The API doesn't have to work but you get to see how people react to the names of classes, methods, parameters etc. I used to blog about API usability and what we were learning here: https://blogs.msdn.microsoft.com/stevencl/tag/api-usability/
There is a group of researchers and practitioners currently working on API usability. Some good links here: http://www.cs.cmu.edu/~NatProg/apiusability.html
Many APIs are targeted to internal teams creating SPAs nowadays. Maybe the same developer writes both the backend API and the fronted app. Those APIs tend to be a wild west of all the mistakes the post is about. Documentation is often sub optimal, not to talk about vulnerabilities introduced by quick and dirty hacks because the team decides that the backend can trust the frontend (missing validations and missing authorization checks are common in the experience of a collegue working on penetration tests.)
Unfortunately such badly designed APIs are going to hinder the development of new functionality for the time being. We're moving from spaghetti code to spaghetti APIs.
The only breath of fresh air I've had lately is interacting with the NetBox API which uses Swagger to sort of self-document and allow for testing.
1) If an API value can be changed any time, it should probably be a plain object property
2) If an API value can be changed but there are side effects, it should probably be a "setFoo" method
3) If an API value can be specified, but not changed after init/instantiation, it should probably be an argument to the constructor or init function
Someone made a Joi playground a few months ago, Joi Tester[2], that makes it really easy to test your Joi schemas. If you're curious, feel free to give it a try (I'm not affiliated with the tool in any regards but I do think it's awesome).
However, where is the current trend of functional programming in this piece? (I am not disparaging FP, on the contrary, I think it's a good development.)
Shouldn't API calls be, for example, easy to test? In functional programming, we often avoid doing actions directly, and instead give descriptions of actions (in form of functions) that are to be made. Does your API support that?
What about minimization of the state that the API requires to keep, and its transparency?
I am sorry if I come off a little incoherent. Best would be if I could give some tool a program that calls an API, say a sequence of API calls. And I would be told, this sequence is valid for the API. So I could prove for my program that it is accessing the API correctly.
http://bryanhelmig.com/your-api-consumers-arent-who-you-thin...
Really good tip! Going to spend a little more time reworking my onboarding workflow with this in mind.
https://github.com/fchollet/keras/issues/3921#issuecomment-3...
A similar guidance is pop-ups in games (e.g. when next to car, "F to enter").