I’ve had a lot of great discussions at API Strat this year and it has inspired me to get back into writing. In the near future I’m going to convert my API World talk into a blog post and discuss some of my upcoming projects. For now, I want to lay out my thoughts on encouraging public API consumers to use hypermedia. To do that, I need to walk through three quick questions.
1. What is the goal of hypermedia?
There are many different reasons to use hypermedia but I think the most immediate goal is to reduce an API consumers dependence on hard coding their API actions. By allowing your API consumer to find these actions in an API response the server can manipulate the availability and implementation of these actions on the fly.
2. How do developers discover new features on your developer portal?
Do they come to a developer site looking for the “/me/likes/{video_id}” endpoint or are they looking for “how to like a video”?
I see a lot of reference docs falling into this pattern and use a URL path as the title of a segment of documentation
PUT /me/likes/{video_id}
This endpoint likes a video
- Video_id: int, the id of a video
I think the documentation can be quickly improved with some organization and copy improvements.
Like a video
PUT /me/likes/{video_id}
- Video_id: int, the id of a video
New users don’t know if your API is GraphQL, REST, GRPC or so on. New users have a problem they need to solve and the documentation explains how to solve that problem. We shouldn’t assume they have any knowledge of your URLs.
(Quick shout out to Keen.io who does this well: https://keen.io/docs/api/?shell#get-project)
3. If an API feature is not documented, does it exist?
I would argue no. A new user finds a feature by searching through documentation, they are not randomly testing URLs. If someone does find a hidden URL I don’t believe they should have any expectations of reliability or stability. If you want to treat these random-url-finders with a little more respect you can consider stricter access control protections such as URL signatures.
The Theory
Let’s recap
- Hypermedia is about encouraging users to use in-response actions instead of hard-coded URLs
- New developers learn about an API by researching the problem they are trying to solve and the actions they might take to solve that problem. These users do not go to your documentation and start looking for a specific URL
- Undocumented features don’t exist
If we believe all of these ideas, let’s stop documenting any URL associated with a hypermedia control. Let’s treat those URLs like they don’t exist. Following this theory, what do our docs look like?
Like a video
1. First you need a Video representation. You can retrieve this representation from any of our video endpoints, e.g. “My uploaded videos”, “Get all of a channels videos”, “Video Search” and so on.
2. Once you have the video representation look in the JSON for the key “likes”. This key will either contain an object or "null".
a. If the value of "like" is null, you are not able to like this video and you should not allow your users to attempt to like this video.
{...
"like": null
...}
b. If the value of "like" is an object, that object is a hypermedia control. A like hypermedia control describes how you can make an HTTP request to like this video.
{...
"like": {"uri":"/me/likes/12345"}
...}
If you want to learn more about how to use hypermedia controls, read our guide here!
Or if we want the content to be a little lighter and focused on a quick reference it might look like this…
Like a video
The hypermedia control to like a video is located in the video representation under the key "like".
Read more about video representations here.
Read more about hypermedia controls here.
Real world examples
Vimeo has one (accidental) example of success with this strategy. Video uploads are documented here.
TL;DR:
- POST /me/videos, grab the upload_link and complete_uri from the response
- Send your video data to the upload_url
- When the upload is complete, make a DELETE request to to the complete_uri
By leaving the URLs associated with the upload_url or complete_uri completely undefined, we have been able to encourage this link driven workflow for all API consumers.
Has anyone attempted this? I would love to hear any thoughts or experiences in the comments or on Twitter.