Last week, I posted on LinkedIn:
The mantra of a good API Program Manager/Product Manager/Developer Advocate:
APIs should help you solve your problems. APIs should not be your problem.
— David Biesack
Today, I want to break this down and discuss API Success.
As I’ve stated multiple times in podcasts where I’ve been a guest, the most important measure for API success is if it is solves real problems — if developers can use your API to build their applications. This means the API must be fit for purpose. I won’t be successful sending a text message to someone if I try to use the Amazon Web Services S3 cloud storage API, and I will find the Tenth Level of Hell if I try to upload a PDF of a Platinum Checking Account Terms and Conditions document, March 2025 revision, using the Twillio API.
Of course, to obtain this highest level of success, someone has to be able to find (i.e. discover) your API. This normally means being able to find it in an API registry (alas, ProgrammableWeb.com is no more but RapidAPI may suit you), or find it through a search service (Google, Bing, Ask Jeeves!, pick your poison), as long as the API is on a web site that can be indexed by search services. [Pro tip - don’t put your API documentation behind a paywall or require registering and logging in to see the API documentation.] You may even try the AI chatbot of your choice to find the API that solves your problem, but for that to work, the AI engine needs to be able to see the API doc too…
Either way, success in finding the right API requires that 1) the API be discoverable, and that 2) the API documentation clearly describes what the API does using the terms the potential consumer understands. I’ve seen way too many APIs described with woefully inadequate documentation. This often stems from technical people documenting the API “from the inside out” - i.e. describing how the system behind the API was designed (at one point in time…), or using internal code names or marketing terms, rather than documenting the API from the perspective of a consumer who, at least initially, knows next to nothing about your API.
This problem often extends deeply into the API documentation. There are few things worse than wasting bits and bytes (and your readers’ time) by providing a circular description of a field or operation that has an obscure or non-obvious purpose, described with undefined, obsolete, or misleading terms that raise more questions than answers:
paths:
/lincoln/v14/indications/:
post:
summary:
Create a new laminar indication in the layers V12 API.
Don’t. Do. This.
A successful API clearly articulates its purpose, and the API design and documentation is built upon a foundation of a good conceptual model of the API's domain. Such APIs arise when the team applies an API design process [ADDR recommended] rather than simply generating an API from a (soon to be obsolete) database schema or other structure which has been optimized for completely different use case than a clean API. (For my thoughts on using Generative AI to design APIs, see my The Art of API Design talk at Nordic APIs Austin API Summit, 2024)
A successful API designed via a solid process is more likely to provide the needed services.
Other problems you may encounter which inhibit API success are listed below. (Fret not, I’ve included lots of guidance on how to avoid the problems.)
An API that uses proprietary authorization. I led a Birds of a Feather session at an API conference a few years ago, the largest hurdle that most of the participants expressed was getting API authentication/authorization right. It’s not too hard to use OpenIDConnect / OAuth2 correctly, especially if you use a good library that implements the protocol, but if an API has proprietary auth, then auth becomes a problem for your API users, an thus, your API becomes a problem for them.
An API that shuns HTTP standards.
The most common “hall of shame” for APIs (as I shared in my favorite API memes) is not using correct 4XX and 5XX HTTP response codes and their semantics, but instead returning a 200 OK HTTP response code with
{ "error": true, … }
or{ "success": false, … }
A related problem is not using the correct 2xx response codes. If your POST creates a new resource, return 201, not 204. If your operation only has side effects but does not return any data, use a 204, not a 200.
Other examples are violating the uniform interface constraint of RESTful APIs - i.e. misusing the HTTP methods
GET, PUT, POST, PATCH, DELETE
; or aGET
operation not being idempotent and safe (I once saw an API which used aGET
operation to shut down a server! Do. Not. Do. This. Run, don’t walk, away from such APIs.) There was a lot of thought put into the design of the HTTP protocol, and the protocol ecosystem (libraries, proxies, gateways, and other intermediaries, etc), works well only if the protocol is followed. Ignorance or hubris says “I know better….”.Not using the standard HTTP headers can be a problem. When a POST operation creates a new resource, return the new resource’s URL in the standard
Location
response header. If a resource is not ready, the GET operation should return the standard HTTP Retry-After response header.Always use date-time values in RFC 3339 date-time format in UTC (“Zulu”) time done. Let clients map these to the user’s time zone or date/time format. The 5 laws of API dates and times by Jason Harmon is an oldie but a goodie…
An API that tries to avoid or minimize good use of JSON Schema is a problem. If you are defining an API, you owe it to your consumers to use JSON Schema well. This includes well-named schemas and properties, but also appropriate use of JSON Schema constraints and annotations as declarations of what data is valid in a request, and what data to expect in responses.
The simplest example of such a problem is using strings with"Y"
or"N"
(or other string values) instead ofboolean
values, but it also includes exposing data taken directly from packed/encoded raw database fields, such asCHAR(1)
codes or integer codes instead of self-describingenum
values (See Amundsen’s Maxim). Here are a couple examples from a real-world API:I don’t know about you, but I have no way to know how to use those single character
code
in thematches
property… and thepattern: \w{1}
constraint is certainly more obtuse thanminLength: 1, maxLength: 1.
A good API team will anticipate and answer the questions developers will have about your API. This is another reason to use the ADDR Process — and not skip the Refine phase, where you improve the API after feedback from real users.Don’t be afraid to refine and revise your API - instead, plan for it!
— David Biesack
Any design aspect which violates basic and widely adopted conventions or developer expectations for how APIs work is a problem. Just as a good User Experience (UX) should be intentionally designed, a good Developer Experience (DX) should be intentionally designed,, with the goal of enabling the desired feature as intuitively as possible, without surprises.
An incomplete API is one example of violating these expectations. Normally, if your API supports creating a resource, it should also provide a way to update/patch that resource, fetch the most recent representation of that resource, and ultimately delete it. Omitting one or more leads to a frustratingly incomplete API that violates basic expectations.
Inconsistency
can beis another caustic API problem. A consistent API design is easier to learn and use because it adheres to those expectations; an inconsistent design adds frustration. (Recommended: The 5 dimensions of API consistency by Arnaud Lauret)
An API that is not designed for evolution will not evolve gracefully when it needs to change… that’s a problem. An no, changing the API URL from
/v1/…
to/v2/…
is not graceful API evolution.An API that is not designed with error handling from the start will have problems when consumers start using the API — developers make mistakes; apps have bugs, and not every request is perfect. Oh, and hackers or bad actors will use invalid requests to launch Denial of Service Attacks or worse. (Pro Tip: use application/problem+json to describe the problems you detect)
A poor or fragmentary Developer Experience can add to the growing list of API problems:
Onerous registration process
Unclear license and terms of use
Unclear or unpredictable rate plans
Hard to navigate documentation; documentation that one can’t bookmark or reference or search… Oh, the plethora of potential API documentation problems!
No easily downloaded OpenAPI documents, or OpenAPI documents based on OpenAPI 2.0 instead of 3.x, or “Swagger” documents (Again, see those favorite API memes!)
API success is certainly more than a lack of problems. Identifying and removing problems is a necessary but insufficient element of building a successful API or API program. “Zero problems” is analogous to the definition of the HTTP 200 status code…. you go to all the bother of assembling a API request, getting the authorization correct, pushing your API call over the wire, capturing the response… and you end up with the less-than-satisfactory
200 OK
It's almost a let down! “Meh, your API call was, well, just OK.”
Instead, I prefer: “200 is Not (just) OK. It’s Success! Hooray! Hooray!”
By reducing the common problems and pitfalls when designing and delivering APIs, you can help your consumers insucceed… If you do it really well and focus not only on removing problems and roadblocks to success, but focus on enabling innovative solutions, you APIs may even be a joy to work with. You have my permission to be more than just OK; you may use “200 Success! Happy Happy Joy Joy!” in your API documentation.
I saw this on Fosstodon (Mastodon) after I shared this article there; I wish I had seen it earlier so I could have quoted it:
A good API is not just easy to use but also hard to misuse.
— JBD
(I also wish I knew who JBD is!)
https://fosstodon.org/@programming_quotes@mastodon.social/114384345475940521