The ideal API is not RESTful, gRPC, or GraphQL
As the title says, I believe the ideal API is not RESTful, gRPC, or GraphQL; those are just implementation details. Forget the beauty of high-performance binary serialization and Roy Fielding’s dissertation for now - let’s move up a level and talk about what it means to really deliver a useful API.
Unsure of what an API is? Check out What is an API? for a brief introduction.
At the end of the day, an API is a kind of product. So let’s apply Clayton Christensen’s Jobs-to-be-Done theory: People “hire” products to perform particular “jobs”. For example, people don’t necessarily care about buying a power drill. They want to buy the hole it creates. If you can get them the hole directly, who cares about the drill?
In an example from the tech world, Uber started as a way to hail gig-worker-driven taxis by smartphone app. But that’s not the core problem they’re solving. Uber has learned this, and the Jobs To Be Done are clear from their current offerings.
Just trying to call a car right now? The standard Uber ride will do.
Want to lock down your ride to the airport tomorrow? Now you can reserve future rides.
Want to get somewhere but not picky on how? Uber will rent you a car or a bike, and recommend transit routes as well.
If you’re in NYC and it’s urgent, you can even take a helicopter.
And on the flip-side, many Uber drivers are just looking to make money from their time and car; they’re totally happy to deliver food (Uber Eats) or packages (Uber Package) instead of humans.
With the JTBD framing in mind, the ideal API for any situation is a clearly a one-liner:
do_what_I_want()
Why should it be anything more?
If the job is flying, why should your customer need to do anything beyond “import antigravity”? The product should Do What I Want (DWIW).
I used to work at Twilio, which is best known for its API for sending text messages (SMS). But their business customers were not just trying to send text messages. The communication and channel are the means to an end. They were trying to reach their own customers through any channel (voice calls, email, WhatsApp, and more). They were trying to add 2FA and prevent fake accounts from being created. They ultimately wanted to drive engagement for their customers, meet their customer service requests, and market to them. And along the way, the APIs tightened up to address more specific jobs.
The DWIW API is ideal. The main challenge is figuring out how to precisely specify exactly what your customer wants, and let them supply it. For example, consider text messages (SMS) - at a minimum, you need a recipient and a message body. For practical SMS-ing reasons, it’s also required to have a sender “from” number. That leads us to this beautiful minimal API for the Python SDK:
client.messages.create({ from: "+15557122661", body: "Ahoy, world!", to: "+15558675310", })
That one-liner is the porcelain - you can have as much plumbing underneath it as you want (this particular SDK uses a REST-style JSON-over-HTTP API under the hood), but ultimately you want your users to interact with the porcelain.
Here’s my challenge: your DWIW API invocation should be shorter and more precise than describing what you want done in natural language. Can you do it?