The other day somebody told me about a REST API for some software that I use almost every day. I typically use their SDK but jumped at the opportunity to use a REST-based offering. I could quickly hash out POCs in Postman and verify my ideas in seconds.
I’m a big fan of REST and API design. I’ve been an advocate for API-first development for years. So naturally the first thing I do is try to find the spec. I poke around GitHub for a bit, but no luck. So I ask a maintainer about it and I was given a single curl statement.
curl -d SOMEBLOB https://{{baseurl}}/data/set/KEYNAME?token\=TOKENHERE
Needless to say, I was a bit underwhelmed. It ended up raising more questions than it answered. What should I expect the data to look like in the response? What was the schema of the request body? What about the content type? Can I sub the token
query param as an Authorization
header? That path isn’t very RESTful, are there other endpoints I should be using instead?
I tried hitting the endpoint and it gave me an error. But I didn’t know how to fix it. An example curl statement doesn’t go very far when it comes to troubleshooting.
All of this could have been avoided had there been a publicly available API spec. You can get by for a while without one as you work to churn out features that help determine product-market fit, but eventually that is going to catch up. The user base will grow over time and people will have questions about how it works and what features are available over http.
Let’s talk about what is involved with API specs and why they are so important for long-term success.
An API spec like Open API lists the endpoints, schemas, responses, parameters, security, and base URLs for an API. It takes all the guesswork out of exploring a set of features. Specifications tell you exactly what each endpoint needs, what types of responses you could receive, and why you would receive them.
Take an example from a game I’m building, Acorn Hunt.
/points:
post:
summary: Add or remove points from the caller in their active game
operationId: updatePoints
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- count
properties:
count:
type: integer
minimum: -10
maximum: 10
responses:
200:
description: The points were successfully added to the player score
content:
application/json:
schema:
type: object
required:
- score
properties:
score:
type: integer
409:
$ref: '#/components/responses/Conflict'
500:
$ref: '#/components/responses/UnknownError'
This endpoint definition tells consumers everything they need to know to call it successfully. The path is listed at the top along with the http method. It has a meaningful summary that tells readers exactly what business functionality it provides. We can see the schema of the request body only accepts a count
field ranging from -10 to 10. Finally, we can see a list of all the possible responses. We’d expect a 200 status code with a score
property on success, or a 409 or 500 in an error scenario.
Zooming out a level, a specification will show you every path supported by the API. Your readers aren’t left wondering if there’s an endpoint that does something specific because it’s all listed in the spec. You see not only the paths, but the list of servers for each environment as well.
Consumers can string the server url with the path they want to hit and voila! A clear, concise description of all the available endpoints in your application.
NOTE - the server urls in the image above are made up and will not resolve if you try them yourself.
Back to my story from before, when I wanted information about the API, I had to reach out to the maintainer. That’s fine in a one-off scenario, but what if that happened 20 times a day? What about 50? 1,000?
Tribal knowledge doesn’t scale. What’s worse, you could have external consumers that hear about your API via word-of-mouth and they tell their friends about it. Those friends tell other friends, then those friends tell their friends, so on and so forth. Have you ever played a game of telephone? The message at the end is usually vastly different than at the beginning. Imagine if that happened with your API.
If you don’t have adequate request-level validation, consumers could be pushing wildly different data to your requests than you expect. That could cause your data integrity to falter and result in a potential increase in data storage costs. Nobody wants that.
With an API spec, you have a definitive resource that scales infinitely. It doesn’t matter if you have one or one million developers looking at your spec, a static definition on a webpage will typically handle that amount of scale. No developers necessary.
Beyond the internal benefits of not having your developers caught up teaching others about your API, you have external benefits as well.
Not all developers want to reach out to a person to get their questions answered. Many of us will abandon new software if we have to go through too much trouble to learn about it. A specification lowers the barrier to entry by providing all the information you need.
Think a spec feels too low-level to give consumers? There are many tools that render API specifications in easy-to-use webpages directly from your CI pipeline.
Not only do you get documentation, but depending on your tech stack, you can deploy the back-end implementation directly from it as well!
If you’re using AWS, there are extensions you can add to automatically build schema validation and connect directly to downstream services. I talk with Andres Moreno about automating everything from SDK generation to integration testing to consumer documentation directly from the spec in the Ready, Set, Cloud podcast.
Your API specification is your source of truth. It should drive how your product is designed. Your API is the front door of your application, enabling consumers to use and extend your product to meet their needs. If you leave them with questions and undocumented endpoints, how are they supposed to be successful? SDKs are great and solve a multitude of use cases, but they aren’t a complete solution.
A web API, be it REST or GraphQL, is an enabler. It lowers the barrier to entry for new users by not requiring them to write any code. They simply need to open a tool like Postman or Insomnia, plug in their API key, and test away.
A single source of truth aligns your product team with the dev team. There’s no “coding in the dark” or black boxes involved. A contract is defined and implemented, then your consumers can immediately discover new functionality. When establishing product-market fit, rapid feedback and iteration are key to success. An API spec detailing available features is the fastest way to make your features known and get users to try them out.
You don’t have to be extreme and go API-first today. But taking steps toward treating your API as your product and your spec as its definition will result in almost immediate benefits. Make it a priority and watch as your quality improves and customer engagement increases.
Happy coding!
Thank you for subscribing!
View past issues.