35 ms·
API Practices If You Hate Your Customers
- gtsteve 7y agoI 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 & - 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 7y agoreturning 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.
- saagarjha 7y ago> What do you dislike about that result, and what would you prefer to see returned? It’s inconsistent and means I need to write special case code to check for it, when before I could choose to. It should return an empty array.
- irishsultan 7y agonull array sounds like it's an array (presumably an empty one), it would have been clearer if OP had said null instead.
- saw-lau 7y agoNot sure why you're getting downvoted - that was how I read it as well.
- bobbylarrybobby 7y agoPresumably they would prefer an array always be returned. If zero items, an empty array; if one item, an array of length one; if more items, a longer array.
- deleted 7y ago[deleted]
- Sohcahtoa82 7y agoIf an API is expected to return an array, but the data set is empty, I expect an empty array. I should be able to go straight from the request to a for-each loop without checking for null.
- ergothus 7y ago> 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 7y agoWe 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)
- thaumasiotes 7y ago>> 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? I'd expect an empty array to represent no items. It's the difference between "" and "[]".
- ako 7y ago404 indicates an error, if the result is just empty but not erroneous 204 "no content" may be better.
- wwweston 7y ago+1, 204 is underutilized for no-result cases.
- jbverschoor 7y agoIn the browser it will also do no page refresh as there is nothing to render.
- jandrese 7y agoWhat would you suggest instead of an empty array for a 0 item return?
- chihuahua 7y agoThe person you replied to doesn't like returning "null". He/she would probably prefer returning an array that contains 0 items.
- compscistd 7y agoThis makes sense now. If I did a GET to posts and got a "null", I would think I made some kind of error. If I get an empty array, I would (correctly) assume there are no posts yet. Basically, GET to posts would always return an array of posts. Whether there are 0 (empty array), 1 (just one object in the array), or many (array with n length). This makes API logic way easier to handle without having to check what structure I received even with a 200 status code
- WrtCdEvrydy 7y agoAlso makes a lot of iteration easier... just a for loop over the array to dump something on the page with no edge cases. You can add a warning by just checking the length against that array blindly.
- jandrese 7y agoHe called it a "null array" which I interpret as an array containing zero items. If it was just a plain old null then yeah, that's super annoying.
- BurningFrog 7y agoIf you return an empty array, I can always process the result by looping through the array. If it's sometimes an array and sometimes null, I need branched logic for each call.
- hermitdev 7y ago> returning a null array to represent no items, and returning a single object without an array to represent one item. This just reminded me of a long ago incident at a former employer. I worked in back-office at a hedge fund and was responsible for maintaining several APIs & services written in C++. The APIs were pretty straight forward query for object(s), get back a vector of objects. If nothing was found, you'd get back an empty vector. The company also had a program where they'd hire grad students right out of school and immerse them in the trading desk, working on trading algorithms and such. One such kid sent in a "bug report" directly to me, CCing all of front office. The "bug"? We was querying for something that didn't exist, so he got back an empty vector. He didn't check that it wasn't empty, and immediately accessed the front of the vector. Boom, segfault. Normally, I would have been kind to such a junior dev, but their original email was very condescending and went to an unnecessarily large audience - like hundreds of people that didn't have time for this. His email read something to the effect of "Your API is crashing my code. Fix your API." Instead, this junior got a whole other lesson instead. I replied all, and included all of back-office on the email (so the rest of the team was aware to watch out for this clown). "The API is working perfectly fine and as designed. The fuck up is on your end. You queried for something that doesn't exist and proceeded to dereference and empty vector. Fix YOUR fucking code."
- sealthedeal 7y agoI would expect an empty array to always be returned regardless
- tbirdz 7y agoI really don't like your story. The junior is clearly behaving immaturely and inappropriately by CCing others and not using an appropriate tone, but your response is to... retaliate by doing the exact same thing to him? What lesson is the junior supposed to learn here? That acting that way is A-OK as long as you have seniority and are factually correct? At least the junior has the "excuse" of being a junior, but really as a more senior person you should have known better. Surely there must have been a better way for you to handle this situation.
- 7y ago
- omgtehlion 7y ago> returning a null array to represent no items, and returning a single object without an array to represent one item this happens when you add JSON version for old XML-based APIs (seen this multiple times)
- purple_ducks 7y ago> this happens when you add JSON version for old XML-based APIs (seen this multiple times) ...without using an XSD schema. With a schema,not an issue
- deleted 7y ago[deleted]
- favorited 7y agoThere's often a semantic difference between null and empty. Like, if I'm checking the result of a batch processing job, I want to know if the job finished & resulted in an empty set, or there is simply no result yet. It's "the thing you're looking for doesn't exist" vs. "the thing you're looking for exists, but is empty."
- gtsteve 7y agoThat's fair to say I guess - but it should be accompanied by some other property to indicate a condition like that. The API I'm thinking of though was effectively a wrapper around a database query which retrieved items. That's what gets me about that decision you see. When you get nothing from a database, you get an empty set. The runtime was some version of .NET Framework, which by default would write an empty set as an empty array. So it wasn't even an accident - someone actually had to add extra logic to make it return null.
- hnick 7y agoPerl's DBI module gets around this with a value "zero but true" aka 0E0. It is useful in cases such as indicating an operation was successful, but zero rows were affected. Using it as a number resolves to zero, using it as a boolean results in true. I think in the general sense under API though, a status flag is the best way to avoid confusion as you say. Null could just as easily mean 'error' as 'not yet finished'.
- sopooneo 7y agoI've seen this happen due to system evolution. At first some entity may have a parent record or not. So when you ask for the parent, you either get it, or null. But then the system evolves to not be many-to-one, but many-to-many. To avoid breaking old clients, they make it so the only difference is when they return multiple related records, in which case they're given in an array. Thus you now have: null for empty, the record it self if there is only one related, and an array of records if there are more than one related.
- 7y ago
- inputespresso 7y agoFor those Gophers reading this and sobbing silently, there may be hope: https://github.com/golang/go/issues/27589 https://github.com/golang/go/issues/27589
- lilyball 7y agoWhy would you want to marshal a nil slice to json as non-null? That just hides the fact that you had a nil slice. In fact, that's the exact opposite problem; representing nulls as empty arrays.
- simiones 7y agoAs explained in the thread, that is because Go best practice is to treat `nil` and `[]T{}` as the same thing in every API. If you want an explicit `null` in your JSON you can use `*[]T` as your field type, and then it makes more sense. The very idea of allowing the nil value for slices seems to be very strange and inconsistent, as slices are struct types, not pointer types in Go (they contain a pointer and other members). Just one of the many ways that builtin types in Go are fundamentally different from user-creatable types, I guess...
- lilyball 7y agoIt is admittedly very weird that Go supports nil slices/maps instead of just having the nil value be an empty slice/map that points to constant storage. But as long as Go has a semantic difference internally, representing that as null externally makes sense. Though I suppose as long as the conversion from null to empty array/object is opt-in it's fine. For context, we recently had a bug where backend forgot to initialize their map, so they were sending us a null where we expected an object, and it would have gone undetected for much longer if the JSON didn't contain a literal null there.
- yencabulator 7y agoThe nil value for a slice is an empty slice that points to constant storage: Data=0, Len=0, Cap=0. That's just not the same as Data=somethingelse, ... which you get if you allocate something. (And all Go zero values are exactly what you get with the relevant RAM filled with the zero byte.)
- Ididntdothis 7y ago“returning a single object without an array to represent one item.” I saw the same thing when working with PHP consuming data from a SOAP endpoint. First I thought PHP is stupid. But then I realized that XML can’t model single item arrays versus single objects. They look the same. JSON is better that way. You can model empty arrays and single item arrays.
- benoitg 7y agoYou can force PHP to handle sngle-element arrays consistently, with the SOAP_SINGLE_ELEMENT_ARRAYS option, the behaviour is much saner when enabled.
- Ididntdothis 7y agoGood to know! Unfortunately I have a call to a “FixSoapArray” all over the code already :(
- thaumasiotes 7y ago> XML can’t model single item arrays versus single objects. They look the same. <results> <result> <property>value</property> ... </result> </results> I don't really see the problem.
- Ididntdothis 7y agoYou need to know that “results” is an array so you need the schema. In JSON an array is an array without doubt.
- thaumasiotes 7y agoIf you don't know that "results" is an array... how do you handle the uncontroversial case of getting back an array of two results?
- Ididntdothis 7y ago
- jiggawatts 7y agoI had this happen with a vendor that was told that they needed to add REST support to their legacy Java app. They turned up with an API that encoded XML as base64 and put that in a POST variable on HTML page. Then they added their own crypto on top with hard-coded RSA keys. They helpfully included both the public and private keys in their documentation. When they turned up for a meeting to present the fruits of their labour they got patted on the back by all the managers for a job well done. Record time too! They faces fell when I told them that I'm flat out rejecting their API design and that they will have to start from the beginning. Their excuse for the design was that ampersands are too hard to process, so base64 encoding made them "safe" to include in the REST API. Sometimes you just have to put your foot down about this kind of idiocy.
- arethuza 7y agoUnfortunately I have vivid memories of one API I worked with (many years ago) that included entire encoded XML documents as attribute values within top level XML. At least there was only one level of recursion. Still, perhaps not as bad as using XML documents as database keys...
- tasogare 7y agoI saw that in HTML. Not from a professional developer but it still blow my mind. That was the final straw that made me quit the project.
- jefftk 7y agoI've needed to do that for HTML. If you need to put part of a document inside an iFrame (perhaps because you don't trust it) you have your backend generate <iframe sandbox srcdoc="..."> and nest it.
- perl4ever 7y agoA common misconception is that you can put anything in xml via CDATA so long as it doesn't have the ending delimiter embedded. https://stackoverflow.com/questions/21087648/xml-invalid-characters-when-creating-cdata-node-from-unicodestring https://stackoverflow.com/questions/21087648/xml-invalid-cha... I know about this because I received a file with illegal CDATA characters once.
- donkeyd 7y agoI worked with a product for natural language processing that wanted the text in a query string. This led to 100+ page documents begin sent as a string in the request. My usual REST testing app would freeze up if I wanted to test some of the largest documents in the data set.
- sangnoir 7y ago> This led to 100+ page documents begin sent as a string in the request How were you able to do this when the standard maximum length of a query string is 1024 bytes? I guess you could flaunt the standard as you were responsible for the backend
- Piskvorrr 7y agoExcept that standard...isn't. It's what some ancient version of MSIE did and that used to count for a standard in Triassic; nowadays, it gets passed around as cargo cult advice. (The relevant RFC recommends no more than 8000 bytes, sure.) https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers https://stackoverflow.com/questions/417142/what-is-the-maxim...
- sangnoir 7y agoIt's not cargo-cult: anyone who's worked on cross-browser front-end development probably encountered this at least once. I ran into this personally a few years back when I was trying to be too clever by half with base64-encoded queries. It's not just ancient IE that has limits - in my case it was a corporate proxy that was truncating the query (which is why only that customer was getting that bug). A year or 2 before that, I ran into the MSIE limit (must have been IE8 or 9: don't know if that counts as the Triassic period, because I don't know what we'd call the IE4-6 era)
- Piskvorrr 7y agoI did encounter this multiple times...not in the last decade though.
- bouke 7y agoI had the pleasure of working with the API of a customer that wanted to expose a JSON/REST API to their existing XML/SOAP backend. Instead of going the sane rout and re-use the XSDs to serve as the structure for the JSON, they just made the JSON structure up on the go. One child node? That would be one JSON object / value for you sir. Multiple child nodes? That would be on JSON array for you sir. No child node? No JSON type for you sir. So what happened when the amount of child nodes was dynamic? You would either get: nothing, an object, or an array of objects. Oh the fun times we had!
- leetrout 7y agoI bet $50 there was a junior dev promoted too high too fast proud of that technical feat.
- Xelbair 7y agoThat sounds like absolute nightmare - at least keep a convention.
- DCoder 7y agoThat reminds me of a vendor who wraps SAP Business One in their own webservice. This webservice has two business methods. The first one, ExecuteXML, takes an <XmlBody> representing a regular SAP B1 XML request and passes it on to one of the real SAP services. We have to find our own XSDs for the inner part, because they sure as hell don't have those. The second one is ExecuteSQL. It lets us run raw SQL against the SAP database. It doesn't have any support for prepared parameters. What it does have is a blacklist to prevent DDL and other funny business, such as semicolons. This blacklist runs on the raw string you send, and doesn't understand any escape characters. To send a string containing a literal semicolon, I had to turn it into CONVERT(VARCHAR(MAX), 0x...).
- deleted 7y ago[deleted]
- pbreit 7y agoI actually really like POST format. Very easy, very standard, very readily available. I also like that it encourages flatter data models.
- jbob2000 7y agoThis 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.
- pc86 7y agoI didn't downvote you but I do strongly disagree with pretty much everything you've said. > 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. Whenever I've used "small b2b apps," especially between non-technical businesses, if you don't have it I'm not asking for it. I know how hard it is to be a solo founder or part of a very small team so I'm either going to use your product as-is, or I'm not going to use it. > API[s]...need customer support There are plenty of small, niche APIs where there is out-dated documentation and not much else. I'm saying that's a great experience, but let's not pretend it's illegal to have an API without on-demand live support. > And I don’t really want random joes signing up for my API... The reasons listed here can all be handled via code. There are very few reasons to prevent automated sign-ups. > The better suggestion is to analyze your business and decide if offering an API furthers your businesses’ goals. If you think it can't, you're just not being creative enough. Every single API with more than 2 users is being used in ways its designers hadn't originally thought of. Many brains are better than one brain and you can often get more (and better) ideas from what other people are doing with your tech than you ever could on your own.
- sergiotapia 7y agoA 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 7y agoI 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).
- TrackerFF 7y agoI think that if your product is something which is available (by browsing, for example), but you only offer a very expensive API - no stripped down free use - you're setting yourself up to both web scrapers, and giving away potential customers to the competition.
- NedIsakoff 7y agoI 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 7y agoStripe'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.
- shantly 7y agoWhat's unstructured about HTML form data format?
- peterwwillis 7y agoIt 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.
- downerending 7y agoMy 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
- chundicus 7y agoThis article really made me think about the Google Ads API. Miserable to work with.
- Glyptodon 7y agoI 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.
- seph-reed 7y agoIt requires passing in an id of some sort. Client generated ids are cool for a lot of things; I wouldn't use them for everything.
- Glyptodon 7y agoCompletely agree with you.
- paulddraper 7y agoPOST is explicitly not idempotent.
- AgentME 7y agoPOST isn't required to be idempotent, but to be clear it's not improper to make an API with idempotent POST endpoints.
- Glyptodon 7y agoWhich is exactly why it's a fairly unusual choice for an example.
- AgentME 7y agoIt 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.
- Glyptodon 7y ago
- tomaszs 7y agoPersonally 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.
- paulddraper 7y agoLinkedIn would like to have a word with you.
- yjftsjthsd-h 7y agoLinkedIn is a worked example of why we need such a law.
- jan6 7y agoof course, I think everyone here would agree it's always good to have an API... too bad you're not gonna succeed in pushing this "rule" out, especially scraping stuff...bot bans are in part because it's rather easy to overload the system with bot calls, which, since they use same page as users, will also affect normal users...especially taxing if the page is dynamic with server-side stuff, like maybe some aspx or php page, which at best would just hog the system resources, at worst could possibly break altogether (most likely due to no free ram), etc... I'm no expert tho, so these specifics might be wrong...
- kube-system 7y agoThis 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.
- Fradow 7y agoI 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.
- save_ferris 7y ago> decided everything should return 200 Sounds like that decision came from someone who didn’t spend much of their career consuming APIs.
- avgDev 7y agoBut they are higher ups and should obviously be allowed to make ALL decisions, why listen to some developer who is beneath them. That dev has only spent the last 5 years working with APIs, databases, and web applications, what does he even know, probably nothing? /s
- jeltz 7y agoI spent a quite big part of my career consuming APIs and an API which always return 200 is no big deal. The opposite which I have also encountered is much worse, returning successes with 4XX, because some libraries do not like that. Why does the opposite happen? Because sometimes it is not obvious if something is an error or just another return value.
- avgDev 7y agoHa, I love it when people make dumb excuses for awful decisions like that. /s I much prefer colleagues who can say, woah that was dumb thanks for informing me of a better way. Making excuses doesn't help anyone unless one has a valid logical reason they did a certain thing, otherwise I DONT WANNA HEAR IT.
- MadWombat 7y ago> 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 7y agoThe 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 7y agoWhat 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.
- xsmasher 7y agoI agree with the author re: returning success on retries; it lets you automate the retry process. I work in mobile games; because someone might play in a tunnel or bad network area, I need to make sure that every request is retry-able. To do that I generally include a GUID of some kind in the request; if the client says "create an entry for XXYY," there's a chance that the request will get to the server but the response will fail to reach the client. If the client is able to retry the request (with the same GUID) and get a success response, then I can have the retries handled transparently in the communication layer; all the client code needs to know is "I made this request and it was a success," without any knowledge of how many tries it took. If the second/third/etc request returned an error of some kind, I wouldn't have a good "success" response to hand back to the game code. (I'm assuming the "success" response contains some information that the game code needs.)
- 6gvONxR4sf7o 7y agoI 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 7y agoA 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.
- peterwwillis 7y agoFrom an ops perspective, many *aaS providers simply don't have working features that we need, so we use their API and build our own solution. From a dev perspective, there are industry standard APIs which a range of products support, and to design a new product that we want to sell, we have to use said APIs and work with different providers and customers. There are so many differing APIs to do the same thing that we have an internal team whose job is to write an internal API that internal customers use to interface with all the external APIs. This model scales well, as this API-of-APIs team can integrate new solutions transparently to the internal customers, so we don't have to rewrite products just because an external API/provider/customer/etc changed. (back in the day this was with straight databases and apps, and the intermediate layer was called "db apps", and was basically an early API)
- TrackerFF 7y agoStock / financial data.
- jcims 7y agoI’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.
- pirsquare 7y agoI'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 7y agoIf 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.
- musicale 7y agoI 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 7y agoAPI practice number one if you hate your users: Don't provide one, and then ban them from working around the gap:D
- dullroar 7y agoHere'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 7y agoSame situation with private beta features, which "can not" be officially supported in the official SDK for the product.
- lapnitnelav 7y ago>"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.
- jopsen 7y agoUse 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 :)
- angry-sw-dev 7y agoThe 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...
- james_s_tayler 7y agoCan someone start an "API practices if you hate your developers" version?? I'm sure HN has some great stories to share about that.
- wokkel 7y agoI'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.
- rwmj 7y agoHere 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.
- 3xblah 7y ago"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-beyond http://genius.cat-v.org/ken-thompson/interviews/unix-and-bey...
- swiley 7y agoSome proprietary protocols are easier to implement than open ones. The other day I wrote against one API server that just accepts messages in json format over an ssl socket. It was maybe 3 or 4 lines of python? (Not counting setting up the connection) and probably wouldn’t have been bad in C. For the shell you could use OpenSSL s_connect and something to generate json (awk or echo would probably be enough since it was all flat dictionaries of strings.) > There were small errors in their documentation of how things actually worked. that sucks, but I’ve run into that with people speaking “http” and not just special protocols.
- cm2012 7y agoAs a non programmer, I use Zapier constantly for all my API needs
- jackcviers3 7y agoInterestingly, 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.
- unnouinceput 7y agoHa! 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 7y agoOoh 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
- deleted 7y ago[deleted]
- mleonhard 7y ago> 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-google/issues/2973#issuecomment-468180542 https://github.com/terraform-providers/terraform-provider-go... Google as an organization is simply unable to focus on users.
- amelius 7y agoHow about "shutting down your API"?
- bvm 7y agoQuestion: 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.
- avip 7y ago#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.
- tsukikage 7y agoA 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?
- enz 7y agoI 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.