UX on a Team with no Front-End?

When I started as a dev on a delivery team, I was excited to discover that I would have the opportunity to work directly with talented UX experts. This would have been a luxury at other places where I had developed software, as we never had easy access to these masters of design, layout, font, colors, and human-computer interaction. In reality, many of our UI decisions ended up being based on discussions that included comments like, "I think I may remember reading about how this form should behave in that Don't Make me Think book". As a result being able to consult with the UX professionals here, the single page apps and mobile apps (and Apple TV apps!) we build offer a far greater user experience, allowing our users to effectively and efficiently accomplish tasks and get the information they need. However, I am now working as a dev on Han Shot First — a team that creates HTTP services as a backend for mobile and web apps. Although we do not have a traditional front-end, does our API-oriented team need to be concerned with UX? As it turns out, the answer is "yes"!

Who are our API Users?

One might argue that without the typical user interface, there is no need to consider the user experience. However, although a large part of REST API design is focused around enabling computer-to-computer interoperability among components in a distributed system, there is also an important element of human-computer interaction. A user interface (UI) is not limited to a web UI or mobile UI, but also includes the application programming interface (API). The users of an API are not the employees at the customer site, nor are they the people using their mobile device to browse for shoes or order a pizza. For our API team, the users are devs from other teams (such as the mobile devs of Team of the Future and the desktop client and web devs of the team called Leviathan), QAs that test our API, the customer's QA team, and the group of people responsible for deploying the API into production at the customer site. As we design and implement our API, we must think in terms of how these individuals will use the API and also anticipate potential constraints, in order to ensure a positive user experience.

Let's Improve the UX!

We can improve the UX of our API by adhering to the HTTP spec, by following REST conventions and best-practices that client devs are familiar with, and by working to enable effective communication with our users.

Follow the Spec

REST APIs are built upon the Hypertext Transfer Protocol (HTTP), so to improve the user experience we should strive to follow the spec. HTTP provides a "uniform interface", where the verbs (GET, PUT, POST, DELETE, HEAD, PATCH, etc.) are intended to be used for very specific actions. For example, GET and PUT should be idempotent, which means the dev or QA using the API will assume that whether he or she makes the following request once or 300,000 times, the end state of the resource will be the same:

PUT /api/v1/orders/7

In other words, PUT'ing to this endpoint 300,000 times should never result in 300,000 new resources being created! In order to improve the UX, we should also be in the habit of leveraging the diverse range of status codes provided by HTTP, and return the appropriate HTTP status code for each specific scenario. On Han Shot First, we recently completed a story to ensure that if a dev or QA makes an HTTP request that includes an invalid Content-Type header (such as providing "text/plain" instead of "application/json"), our API will not return a 500 Internal Server Error, but instead point the user in the right troubleshooting direction by returning a 415 Unsupported Media Type. Because the 415 error code is in the "client error" range of 400-499, the user is empowered to tackle the issue because he or she immediately knows there is a client-side mistake that can be fixed, instead of being mislead into believing that an error occurred on a server that is out of his or her control. Finally, because HTTP is a protocol between clients and resources, each URI we expose should look more like a resource (a noun) and less like an action (a verb). For example, we should expose the URI /api/v1/cars instead of using a URI that encourages a remote procedure call (RPC) style of client experience, like /api/v1/addNewCar.

Follow RESTful Patterns

We joke on our team that I am Robin in this meme!

Another technique to enhance the user experience is to follow the Principle of Least Astonishment by adhering to REST best practices and patterns. Specifically, we must be cautious to avoid creating a REST API that is so different from what our users expect that it is no longer intuitive. One pattern we follow on Han Shot First is the collection resource. In a collection resource, we use a URI to represent an entire collection of HTTP resources. For example, to create a new order, an API supports the following endpoint:

POST api/v1/orders

(Notice that "orders" is plural, as it represents a collection of orders.) The user sends a JSON representation of an order as the HTTP request body to this URI, and the API then returns an HTTP status code of 201 Created to let the user know the resource was successfully created. The API would also include the URI of the newly-created order resource in the Location response header:

Location: http://<host>/api/v1/orders/66

The user can immediately retrieve the newly-created order by performing a GET request on that returned URL:

GET http://<host>/api/v1/orders/66

The user can also perform a GET on the collection resource itself to retrieve all existing orders:

GET http://<host>/api/v1/orders

Finally, the user can perform query filtering by appending specific parameters onto the collection resource URL:

GET http://<host>/api/v1/orders?term=nachos&region=stl

Here, the user is requesting only orders from St. Louis that contain the word "nachos." In addition, when creating APIs, we must be careful to avoid the trap of assuming that just because a specific HTTP/REST library allows us to create a specific type of URL or payload, and supports using the HTTP verbs in specific scenarios, that this automatically translates to a well-designed interface that offers a great UX to our devs and QAs. It is important to rise up to the next-higher abstraction level to ensure that the API doesn't provide any unexpected surprises. We should ask:

  • Does the endpoint provide valid status codes?
  • Does it follow best practices with respect to headers?
  • Does the API exhibit a stateless nature that allows the deployment team to easily run it on multiple nodes?

For example, when using the Express framework in JavaScript, a route can quickly be added using the following syntax:

app.get('/api/v1/addNewOrder', function (req, res) {

// Code to persist the new order to a data store

});

However, from an HTTP perspective, this GET request would be neither safe (it modifies resource state) nor idempotent (replaying the request would cause an order to be created each time). Just because we can do it, doesn't mean we should do it.

Continuous Improvement of Communication

A great way to ensure a good UX is to continuously improve communication between the API team and the API users. On Han Shot First, we have the luxury of being co-located with our users, so the devs and QAs of our team can easily meet face-to-face with the devs and QAs from the other teams that utilize our API. For example, earlier this week, a pair of Leviathan devs requested that we restructure the JSON response payload of one of our endpoints in order to reduce confusion and improve ease-of-use. As a result, we immediately went to our Kanban board and added a story to improve that payload! We should also provide our user with clear (and easy-to-find) API documentation. Our API docs should communicate the HTTP verb, the URI and any URI parameters, and give a clear description of the payload. Han Shot First, and several other WWT API teams, have successfully utilized Swagger to automatically generate well-structured API docs that are exposed as another endpoint of the API.

It is important to consider UX for our APIs. By following the HTTP spec, learning and applying RESTful best practices and patterns, and working to continually improving the communication with our users, we can dramatically improve the user experience of the devs, QAs, and the other people that use our API!