
API Practices If You Hate Your Customers - blopeur
https://queue.acm.org/detail.cfm?ref=rss&id=3375635
======
gtsteve
I was expecting to see two of my pet hates - returning a null array to
represent no items, and returning a single object without an array to
represent one item.

I also once worked with an API where you had to send the data in POST format -
abc=123&def=456. After much pressure from their customers, they finally
relented and added an XML version of their API... where your request could
look like this: <request>abc=123&def=456</request>.

Even better, note the & is not an &amp; - you can't even use a standard XML
parser to interpret the result.

Also: APIs that have a mix of strongly and eventually consistent calls and no
documentation about which is which. Or, an API that was at one point strongly
consistent turns eventually consistent without warning.

~~~
akurtzhs
_returning a null array to represent no items_

To be honest, that's what I'd expect. What do you dislike about that result,
and what would you prefer to see returned? Jump straight to 404?

 _returning a single object without an array to represent one item._

So an array if there's multiple results, and a bare object for a single
result? That's unpleasant.

~~~
ergothus
> Jump straight to 404?

That's my pet peeve. I completely understand the logic - using the HTTP status
code to show the result of interaction with the resource is very RESTful - but
my complaint is that unless you provide more context, a 404 doesn't tell me if
I'm getting a response of "that resource doesn't exist" vs "you're accessing a
url pattern that will never work".

So if you want this random internet user to be pleased, never return a 404
response unless the caller is able to see this difference. (Usually having
SOME form of body unique to the API is sufficient to prove the 404 is not
because of a bad API call).

Giving me the HTML to your site 404 page when I called a non-HTML API is
likewise sad-inducing.

~~~
WrtCdEvrydy
We have only one pattern like this... when there's a client resource
(containing personal information for contacting them) that the client has
asked to be private... we return an empty JSON object (versus an object with
the contact information keys)

------
Fradow
I was totally expecting to see something about using a protocol in an
unexpected way, because "the protocol is not good enough".

I had to work with an API where the company decided everything should return
http code 200 (well, at least all 4XX errors), and give the error code in the
JSON response, mixing existing 4XX errors and their own errors.

When pointed out, the support answer was "we chose to give meaningful error
messages instead of HTTP codes, that's why we respond with 200 in case there's
an error in the request". Not the answer I was expecting.

Another annoying practice is to answer 2XX, put the request in a queue, and
not provide ANY information about the queue, which can be minutes or even
HOURS long. Debugging is a nightmare. The one I worked with who did that did
not even have the excuse of being a startup or small company.

~~~
e9
It depends. I've seen bigco use this technique and their reason was that they
wanted to separate problems with API and request from actual issue with their
servers/platform. So if you get 200 it means they received request
successfully but if there is issue with request they'll include error in
response with 200. If it's anything else then there is a networking or
delivery problem. It's not standard way to handle things but can be useful at
times.

~~~
paulddraper
For example, suppose you want to distinguish between a missing/deleted
resource /myuser/23123 and a completely invalid query /muser/23123.

Both of these are 404 (or 410 for permanent caching) responses according to
HTTP, though they have very different reasons for "non-existance".

~~~
wool_gather
No, the "completely invalid query" is 400.

404 is only for "the request makes sense but that specific resource doesn't
exist".

~~~
akvadrako
In this case it’s a 404 because the query URL pattern doesn’t exist - the most
common cause of 404s.

~~~
pavel_lishin
Same thing, no? If I ask for /api/user/238885 and I get a 404 back, it's
because the resource "user" with ID of 238885 doesn't exist. If I ask for
/api/banana/wharrgarbl, it's because the resource "banana" with the ID of
"wharrgarbl" doesn't exist.

------
wokkel
I'm missing a few in the list: 1) Have an API but only expose that via some
weird-ass tool instead of a normal protocol. 2) Have a lot of documentation
but make it so bad it's useless (looking at Telebib2 right now) 3) Only return
generic errors which are always the same 4) Refer to standards so you don't
have to document them, but then deviate slightly so all standard tools don't
work 5) Make it ambiguous (best one I've seen so far: 30% of the required
fields must be filled in, doesn't matter which 30%).

I could go on looking back the projects I've done.

------
lapnitnelav
>"APIs also permit customers to use a lot more of your product. If they have
to click, click, click to use your product, they're going to use it only a
little. If an API exists, they can automate their use of your product, which
would let them use it a lot more. They could automate provisioning for their
entire company. They could build entire new applications based on your API.
Just think how much more of your product they would be able to consume with an
API."

This so much. One of our main adtech vendor is lagging behind on the API
front. We've been chasing them for a while on when they'll be up to date so
that we can build on top and they get back to us on how their other customers
don't really want an API.

Of course, no one (beyond us tech crowd) goes to bed thinking oh I need an API
to interface with my DSP. But I'm sure they'd be delighted about what the API
can enable them to do.

Here's an advice if you are building / improving a pretty consequent SAAS
product : Your UX sucks. Not that it is awful but it is likely not optimised
for what your customers are doing, simply because you keep adding features and
now it's bloated.

And I don't mean that it is an awful thing, it is the nature of such product
to keep growing, because marketing, justifying salaries and obviously adding
value.

Chances are, 80% of your customers are only using a good 20% of the features
you offered and they'd rather have something that is tailored for efficiency
to address their main pain point. So either you step up your game to offer
that flexibility or you get your API game up to speed. Your competition might
beat you to it and I know which product I'll choose.

------
avip
#DJI

Re: _hiding docs_ :

 _Luckily, this can be easily done by putting the documentation behind a login
screen..._ _consider making your documentation a PDF file..._

DJI's release notes for the DJI-SDK are only available for DJI registered
developers. As a zipfile - of a single pdf doc.

------
pirsquare
I've worked with plenty of APIs (> 50). The biggest headaches I came across
are bureaucratic stuffs rather than poor API designs. For example, there are
vendors (like ConstantContact) that requires you to provide your credit card
to get an account for API testing. You know what, they auto-bill your card
after X number of days and require you to call them up to cancel your
subscription. Because I'm on the other side of the world, I've to drop them a
call in the middle of the night just to cancel billing.

~~~
nothrabannosir
If you ever find yourself in that situation again: send them an email and
explain you’ll contact your bank and issue a chargeback if they don’t cancel
it without a phone call. The issue very quickly resolves itself; chargebacks
are expensive.

The power is in your hands; use it. Don’t play their games.

------
dullroar
Here's one from a vendor I currently integrate with - have multiple APIs (in
this case, a SOAP one, a REST one returning JSON, and then some language SDKs
that wrap the latter for convenience), and have their feature sets be an
interesting Venn diagram with various intersections but no unions. Just today
I found out that the in the extensive integration we've written using the SDK
(which wraps the REST API, remember), I will have to shell out and use SOAP
because one (1) parameter on one (1) object in their extensive object
hierarchy isn't supported by REST or the SDK, just by the SOAP protocol. Nice.

~~~
doppel
Same situation with private beta features, which "can not" be officially
supported in the official SDK for the product.

------
rwmj
Here are a few more:

* Aggressive rate limiting that makes it hard to use the API in real world situations. Especially if there is no documentation about what the limits are.

* Throwing errors with no explanation about what went wrong or how to correct it. Especially effective if given two very similar requests, one succeeds and the other one fails.

* Throwing errors randomly / when under load / when not under load / based on the phase of the moon.

* Having absolutely no example code anywhere in the documentation.

* Requiring hundreds of lines of code to even establish a connection to the API.

* Requiring a specific client library to access the API. Extra points if it's Windows only or requires a specific out of support version of Python 2.

------
jopsen
Use of multiple different sets of allowed characters in identifiers for
entities in your API is also a good way to show you customers that you hate
them..

Extra bonus points for intermittently using case-insensitive but case-
preserving identifiers.

Microsoft Azure storage APIs is a prime example of this with 4-5 different
sets of identifier restrictions dependening on what you're naming. (Including
one that allows any valid C# identifier, for which the documentation
conveniently refers to the ECMA specification of C#).

Also enabling some special characters like # when creating entities, while
knowing that # will be interpreted differently when fetching entities. Such
that entities with # in the key cannot be fetched or deleted, but only
created.

Extra extra, bonus points for retaining # support in the interest of backwards
compatibility :)

------
downerending
My favorite was an API for a product you've heard of that couldn't be bothered
to do datetime math correctly.

Their recommended solution: Make sure all of your intervals overlap by several
minutes to avoid any problems. :-P

------
jcims
I’d like to add ‘Avoid any permission model for API keys’.

Even with multiple keys, if they are all god-mode it’s difficult for a central
operations team to give internal users API access without risking unauthorized
changes or audit findings in regulated environments.

------
tomaszs
Personally i think API should be obligatory. Every company should provide it
with respect for private data. Additionaly if a company does not have it, it
should be prohibited to block automatic measures to process the system and
data.

There should be a pricing model to cover basic expenses made by the API usage.

Maybe you wonder why on earth it should be legally allowed to process
automatically system data?

We have a lots of great services online. But we can not move further,
integrate them into even better ones, because of lack of APIs and bot bans.

Without it, we wont be able to create high level services people expect. And
currently if these will be provided, than only by companies that have Monopoly
over vast parts of online offering. Because they can make more monopolistic
deals with service providers.

Another problem is that service owners have adventage over users. Because they
can process users data to drive business decisions torwards them. But users
can not process thr same data for their adventage. With more and more
complicated systems user ends up being dependant on the company service and
has no possibility of validation.

And this means even more trouble than we have today. So ye, open programmatic
access as a human right.

~~~
hnick
Does "every company" include the thousands of local businesses running
Woocommerce or Shopify?

Larger companies love regulations like this because they can afford it, and it
keeps smaller competitors from ever growing to be a threat.

I'm not saying they should be able to do whatever with data - but for such
providers, manually replying to an email is preferable than implementing a
complicated technical solution they can't understand (and will often likely
mis-configure, exposing your data) when they just want to sell hats.

~~~
yjftsjthsd-h
That's fine. The second point was precisely that if the company doesn't want
to provide an API, fine; but they then don't get to try and stop people from
scraping it instead. And I agree with my sibling comment; Woocommerce or
Shopify or whatever just build it in like everything else they provide.

~~~
hnick
Agree re: scraping, I was more stuck on "obligatory" so I guess I glossed over
that.

I also agree that the big players would roll it into their core offering which
would make life easier, but I'm wary of monocultures. A lot of people are
already a bit annoyed at how much Wordpress is out there and this would just
be another reason to skip a smaller (or bespoke) alternative and raise the
barrier of entry for anyone thinking of making an alternative. But if we're
agreeing that no one is forced to do it and scraping is OK, that's fine.

------
NedIsakoff
I really liked Strip's API version scheme and how well done it is.

Recently I'm writing code that interacts with API of a Enterprise Product
(fairly new, less then 3 years old) and its driving me crazy. They version
every single API endpoints separately. So endpoint A to create a user is at
version 7 but endpoint B to assign a group to a user is at version 4.

WTF?

~~~
inputespresso
Stripe's API is well documented, but I don't understand why it uses form data
instead of JSON. Seems weird/scary to have an API driven by completely
unstructured text.

~~~
peterwwillis
It is structured. The first page of the Stripe API links to the encoding
standards. The main difference between it and JSON is JSON supports complex
data structures while form encoding is flat key-values. In fact, with RFC7578,
multipart/form-data encoding allows arbitrary Unicode strings, unlike JSON,
which requires weird handling of some Unicode data.

------
mleonhard
> Technique #8: Ignore the IaC revolution

Google Firebase has no API for creating projects. Therefore it is impossible
to use Terraform or other IaC (Infrastructure as Code) tool to provision
backends that send push notifications to Android apps. Manual steps are
required. In this way, Google Cloud prevents its customers from using SRE
best-practices.

[https://github.com/terraform-providers/terraform-provider-
go...](https://github.com/terraform-providers/terraform-provider-
google/issues/2973#issuecomment-468180542)

Google as an organization is simply unable to focus on users.

------
6gvONxR4sf7o
I only ever use internal APIs at work. I've never used anyone's external APIs
and am wondering if there's a whole tech ecosystem I'm missing out on. What
are some commercial use cases you all have had?

~~~
davidwparker
A great source to learn from is ProgrammableWeb:
[https://www.programmableweb.com/](https://www.programmableweb.com/)

But in general, a lot of things on the web that you would expect. Using
Stripe, Paypal, Ebay, Amazon, Google Maps, etc have APIs into their services.

------
Glyptodon
I thought the chosen example for idempotent requests was a bit funny as I
don't think POST is necessarily idempotent and depending on your specific use
case making it so may or may not be easy.

~~~
paulddraper
POST is explicitly not idempotent.

~~~
AgentME
POST isn't required to be idempotent, but to be clear it's not improper to
make an API with idempotent POST endpoints.

~~~
Glyptodon
Which is exactly why it's a fairly unusual choice for an example.

~~~
AgentME
It would be weird if he used a method like GET which is normally idempotent.
People already make those be idempotent, so they would miss that the point is
that a good API has all idempotent endpoints, POST and not.

------
james_s_tayler
Can someone start an "API practices if you hate your developers" version?? I'm
sure HN has some great stories to share about that.

------
jbob2000
This article is junk. There are many reasons for not offering an API to
customers.

I run a small b2b app between two completely non-technical businesses. There
is absolutely no need for me to have an API available to them, they’ve never
asked for it and have no desire or ability to consume it.

Believe it or not, there is also an expense to offering an API! An API is a
product offering like anything else, and products need customer support. API
products need advanced support because they are technical in nature, you can’t
use a call center for this type of support.

And I don’t really want random joes signing up for my API and doing god-knows-
what with it. I’d much rather create a relationship with you so I know what
you’re trying to do (so you don’t bring down my servers in the middle of the
night or run up a huge bill because you’re use case is a little beyond what I
can support).

The other points can just be summarized as “have a perfect API and perfect
docs”. Ok. Thanks. Can you show me an example of this in the wild? Didn’t
think so.

The better suggestion is to analyze your business and decide if offering an
API furthers your businesses’ goals.

~~~
hpoe
I would argue the primary benefit of having an API even if not made public is
that it will encourage better architecture , design, and development making
the product more maintainable over the long run.

It also means you can scale if you ever do need to add a customer that wants
to make use of an API.

Saying not to do an API because customers don't want it is similar to not
using source control because you're the only developer.

~~~
aldoushuxley001
Is having an unnecessary API really better architecture though? It adds quite
a bit of complexity and there are other ways to address separation of
concerns.

~~~
corebit
Depends on how big your team is. If it's just you and you feel like you dont
need one then dont. If its 3 teams of 10 then an API is extremely helpful.
It's a great way to frame conversations in something beyond personal
preference.

------
chundicus
This article really made me think about the Google Ads API. Miserable to work
with.

~~~
lowdose
What would you change?

~~~
rwmj
Everything, it's a horrible horrible API.

------
tsukikage
A seemingly common one in the move fast and break things world is to provide
all information in the form of hello world tutorials and youtube videos. The
source code is its own reference, amirite?

------
kube-system
This seems to be written from the point of view that the "industry" is all
enterprise SaaS software or something. I don't think I'd agree with calling
any of these "industry best practices". Maybe "commercial business software
best practices". #2, 3, and 4 aren't really applicable to a ton of software
products. There's a lot of niche software that isn't intended for the general
public.

------
amelius
How about "shutting down your API"?

------
bvm
Question: do you guys find a graphql-only API acceptable in 2019? For us to
develop a (good) REST API layer on top of our existing solution is a non-
trivial piece of work, and GQL offers us all we need on the front end.
Customers seem ok with it, but we haven't got any large enterprises yet.

------
unnouinceput
Ha! Anybody who implemented a payment processor on their side of the fence to
interact with Visa/Mastercard on the other side will have seizures while
reading this article. Those API's are definitely written with "hate your
customer" practices in mind.

~~~
hackerm0nkey
Ooh yeah. If you have ever integrated with Vantiv you will know what all this
means. Heavy lifting is on the customer side. What a pain

------
enz
I used to work in a company like that almost all techniques described in the
article were in use.

Turns out it doesn’t piss only customers but developers (of the API) as well.

------
angry-sw-dev
The API that was dragged out of my company's software team ticks oh so many of
these boxes...

It's eerie, almost as if the author tried to use our system and then decided
to write this...

------
jackcviers3
Interestingly, many of Amazon AWS's apis don't break these rules, and I don't
really hate them.

Charges for use. Manual documentation. Idempotency. A weirdo protocol.

------
musicale
I guess that explains why the ACM Digital Library doesn't have an API.

Even worse, they seem to forbid any sort of programmatic access in their ToS.

~~~
yjftsjthsd-h
API practice number one if you hate your users: Don't provide one, and then
ban them from working around the gap:D

------
cm2012
As a non programmer, I use Zapier constantly for all my API needs

------
3xblah
"Technique #5: Use a terrible protocol

Debugging is boring. Wouldn't you rather appeal to customers who write bug-
free code on the first try?

To really show disdain for your customers, use a proprietary protocol so that
language support is limited to the client libraries you provide, preferably as
binary blobs that are never updated. If you design it carefully, a proprietary
protocol can be difficult to understand and impossible to debug, too.

Alternatively, you can use SOAP (Simple Object Access Protocol). According to
Wikipedia, SOAP "can be bloated and overly verbose, making it bandwidth-hungry
and slow. It is also based on XML, making it expensive to parse and
manipulate—especially on mobile or embedded clients"
([https://en.wikipedia.org/wiki/SOAPjr](https://en.wikipedia.org/wiki/SOAPjr)).
Sounds like a win-win!"

I remember when the early days of Amazon S3, trying to write Bourne shell
scripts using shell built-ins and single purpose UNIX utilities to form the
HTTP and interact with the servers, instead of scripting languages with
libraries like Perl, Python, Ruby, etc. This is how I interact with HTTP
servers normally. I never have any problems keeping things simple and
dependency-free.

To do this with S3, it felt nigh impossible. There were small errors in their
documentation of how things actually worked. It felt like they were
intentional just to trip me up. I know they were not.

The official recommendation back in those early days of AWS was to use one of
the protocol options provided by Amazon, HTTP or SOAP. You would think, heh, I
will avoid SOAP and keep it simple. I will just use HTTP.

The truth is both required using scripting languages with libraries. Amazon's
own utilities were written in Java. I know developers have their reasons for
making these choices, but as a user, that complexity really put me off.

From my perspective, this ACM article is right on point.

"When I see a top-down description of a system or language that has infinite
libraries described by layers and layers, all I just see is a morass. I can't
get a feel for it. I can't understand how the pieces fit; I can't understand
something presented to me that's very complex. Maybe I do what I do because if
I built anything more complicated, I couldn't understand it. I really must
break it down into little pieces." \- Ken Thompson
[http://genius.cat-v.org/ken-thompson/interviews/unix-and-
bey...](http://genius.cat-v.org/ken-thompson/interviews/unix-and-beyond)

~~~
wholepointofcc
That's a bit of a strawman. The cultural tradeoffs between "inspectable" JSON
and "bloated" SOAP have to do with their most common consumption environment.

In my current life I work mostly with JSON and a typical workflow involves
checking API documentations, querying the endpoints, and understanding the
structure. I need to own the mapping between JSON and domain objects.

In a previous life I worked with .NET and C#, mostly SOAP APIs. A typical
workflow involves right-clicking somewhere, pasting the link to the SOAP
endpoint's WSDL file, and automagically getting a collection of strongly typed
classes that I can manipulate directly and operate on as if they were domain
objects.

The idea that when using SOAP one spends any time (manually) parsing and
trying to make sense of XML is a misconception.

To put it in a modern parlance, one shouldn't compare SOAP to JSON. SOAP is
JSON + Swagger, with the Swagger integration costing 0.

------
sergiotapia
A pretty bogus article. If you can charge for an API and people are paying for
it, why would you not charge for it? If people aren't paying then think about
making it free and making it a doorway into your general product.

~~~
pc86
I don't think they were arguing not to charge, I think they were arguing a)
not to charge an obscene amount, and b) not to charge individually for every
little thing someone might like to do (e.g. have a couple tiers but not full-
blown a la carte pricing).

------
MadWombat
> An operation is idempotent if performing it multiple times yields the same
> result as performing it exactly once.

And then he casually offers an API that does different things on first and
second call as the "good" example. If you have a "create a virtual machine"
API it better create a fucking virtual machine. If I call the damn thing
twice, I expect to have two VMs. If there is some sort of unique argument like
create a named VM, I would expect API to throw an error if the name is already
taken, no to just return like everything is normal.

And this guy is being all snarky about API design?

~~~
tlb
The idempotent operation is usually "Ensure that a VM exists with this name
and spec".

An advantage of this style is that if the client dies or times out during the
(long) operation, it can retry and get the same answer instantly.

~~~
MadWombat
What happens if some other process has already created a VM with this name and
spec? Under most realistic scenarios I would rather VM creation failed than
silently clobber someone else's VM.

