8 Tips For Designing Quality REST APIs

Adriano Mota, Solution Architect at Ford Motor Company, shares well-treaded tips for designing automotive-grade APIs

There are many significant aspects of building APIs and REST services that API practitioners must consider. For example, there are industry-standard conventions on structuring the URL for each service, similar to patterns used for naming Java variables or classes.

In this article, we’ll dive into 8 design tips inspired from the internal style guide used to build robust APIs at Ford. From understanding REST to applying the correct HTTP methods, URI formatting, versioning, and other cues, we’ll give the average API developer a great overview of how to observe API style within their designs.

With these best practices in mind, you’ll be able to design highly performant APIs that developers will find easy-to-use since they fit with industry conventions.

1: Understand The REST Standard

First up, though other API standards like SOAP, gRPC, GraphQL, or Apache Kafka exist, Representational State Transfer or REST is still a dependable design standard to apply to develop robust web API services. When using REST, we must keep HTTP methods, JSON formatting, and status codes in mind when designing our APIs.

Within the next topics, we will try to cover the main aspects to follow when you are developing your APIs and REST Services.

2: Use the Right HTTP Method

At Ford, we rely on four HTTP Methods to develop our services — GET, POST, DELETE, and PUT. Similarly, these four methods can cover the bulk of most operations for other REST API developers.

In the table below, you can find a mapping of them and the purpose of each one. We’ve included an example of how each method could interact with a vehicle :

HTTP METHOD CRUD RELATED OPERATION PATH EXAMPLE DESCRIPTION COMMENT
GET Read /vehicles To get a list of information from a determinate resource (in this case, vehicle). If you need to get specific vehicle information, you need to use get parameters on the URI (example: /vehicle/{id}). Never use a JSON Body to request information. Always use GET parameters on the URI.
POST Create /vehicles To create a record or table or information for the resource. If you need to get specific vehicle information, you need to use get parameters on the URI (example: /vehicle/{id}). Never use a JSON Body to request information. Always use GET parameters on the URI.
DELETE Delete /vehicles/{id} To exclude from the database the information of this resource. Always use get parameter to identify the resource to be excluded. Never use JSON Body for this type of Request.
PUT Update /vehicles/{id} To update information of the resource. This is the only case where we can use a GET parameter, like an ID to identify the resource to update such as a JSON Body with the information to be updated on the database.

3: Know How to Define Resources

A resource is the entity you need to work with (aka domain). If your domain is vehicle, then we must use /vehicles and point to the right resource to be accessed in the URI.

See the examples below:

URL Comment
https://www.veihclebrand.test.com/api/vehicles In this example you should be able using the GET HTTP Method to get a list of vehicles
https://www.veihclebrand.test.com/api/vehicles/{code}/versions For this example, by using a GET parameter, request a list of a version from a specific vehicle code.

It’s good to establish helpful naming conventions to help standardize URIs. For example, at Ford, domain entity/resource names must be set on plural (in this example, “vehicles” not “vehicle”). This rule is applicable for sub levels or sub-resources.

4: Use Sub-resources

In some cases, you need a specific attribute for your resource, but the URI is not enough to represent it. In these cases, you will need to work with a sub-level, called sub-resources to represent this attribute.

For example, suppose you have the URI /api/vehicle, but need to retrieve parts information for this vehicle. In this case we can create a sub-resource, and generate a URI like this: /api/vehicle/{id}/parts.

Notice how we have added the {id} parameter to specify which vehicle we want to retrieve the list of parts from. For the other CRUD operations, the mapping should be something like this:

HTTP METHOD CRUD RELATED OPERATION PATH EXAMPLE
GET READ /vehicles/{id}/parts
POST CREATE /vehicles/{id}/parts
DELETE DELETE /vehicles/{id}/parts/{code}
PUT UPDATE /vehicles/{id}/parts/{code}

5: Do not Use Java Method Name Patterns

APIs have their own patterns to be followed, so, if you use URIs similar to “/vehicles/listParts” or “/vehicles/getComboData” you have something out of the worldwide conventions for APIs.

API developers should always use resources, sub-resources, and query parameters to format your API URIs. In addition, any other pattern from other Oriented Object Language should not be used. We need always to use the REST standards.

Thus, a URI structure for retrieving a list of parts from a specific vehicle, for example, would be /vehicles/{vin}/parts. Alternatively, if you need to load a list for a combo box on your HTML page, the URI should be something like /vehicles/orders or /orders/vins.

6: If You Do Version Your REST Service, Do So Consistently

When you are evolving your service over time, one practice is to version it. Everybody knows that we are always improving our code and at sometime, we need to refactor it due to scope changes or other reasons.

If you are exposing APIs for external partners there is a potential risk of breaking the client side by updating your service, so releasing completely new versions is a practice to avoid some headaches. But how I do it? Simple. In your API URI you can add the version. Let’s walk through an example.

This URI https://www.site.teste.com/api/v1/vehicles/ means that this is my first exposed version of the API to get information from Vehicles. It can return JSON with lots of data in a specific format. However, as we know, the world is not perfect and you receive a scope change, and you need to improve your code to update the return of this server. How can I do it without break with clients and external customers that are already using it? You will need to create a new version of your service, and convince clients to adopt it.

You can consider using https://www.site.teste.com/api/v2/vehicles/ as your new service. In general, it’s a good practice to document your API using one of many OpenAPI documentation tools. Using this approach, you can increase your services, but you can maintain your previous customers compatible with previous versions of your APIs.

Nevertheless, pay attention. If you must continually develop new versions of your API, ensure your design work is effective. Scope changes are acceptable to a certain point, but if you have five versions of your service, you need to pay more attention when defining it.

7: JSON Over XML For Most Cases

Depending on your programming language or the framework you are using to develop your API, it’s possible to return data in JSON, XML, or other formats too. However, is there any standard format to use?

In many ways, JSON format is the standard for APIs and REST services. However, if you need to return in XML, it’s permissible. Once again, you need to check the specifications of your business scope. We always recommend JSON for this approach, especially for public-facing interfaces.

8: Return the Right Status Code

Unfortunately, not all APIs live in a beautiful world of 200 HTTP Status Codes. If you are really engaged with your API design, you will pay attention to the right status code to return your service. Check the list of status codes list below, and use the one that fits with your needs. These status codes listed are HTTP standards, very commonly used for API design.

CATEGORY STATUS CODE NAME DESCRIPTION
SUCCESSFUL 200 OK Generic status of success. Can be used when the URI works fine and it’s returning GET information properly.
SUCCESSFUL 201 CREATED Indicates when the resource was created. Most used as a POST return.
SUCCESSFUL 202 ACCEPTED It’s used when the requisition was accepted. Most used on asynchronous services.
SUCCESSFUL 204 NO CONTENT Indicates that the URL worked fine, but there was no return for this requisition. Normally used for PUT and DELETE operations.
CLIENT ERROR 400 Bad Request Generic status for error. Most used to requisition with media type wrongly informed.
CLIENT ERROR 401 Unauthorized The server returns this status when the requisition fails due to a lack of credentials or fail in authorization.
CLIENT ERROR 403 Forbidden When you authorization works, but your credentials have no grant to access this resource. That is when we use this code.
CLIENT ERROR 404 Not Found The URI informed does not exists.
CLIENT ERROR 405 Method not Allowed The HTTP method used to process this URI is not supported. For example, your API only work with GET, but you try a PUT or POST. This error should be raised.
CLIENT ERROR 412 Precondition Fail Something in the requisition is not cohesive with it’s expected by the service.
CLIENT ERROR 413 Entity Too Large The requisition exceeds the limit that the server can process.
CLIENT ERROR 415 Unsupported Media Type The payload sent to the service is not in a format that it can recognize. Sometimes can be fixed by using attributes like Content-Type or Content-Encoding.
CLIENT ERROR 422 Unprocessed Entity A Semantic error happened on your requisition.
CLIENT ERROR 429 Too Many Requests The server is limiting your requests. For some reason, you reached the limit of requisitions for this service.
SERVER ERROR 500 Internal Server Error When a requisition is ok, but for some unexpected reason, the server does not respond.
SERVER ERROR 502 Bad Gateway The API does not recognize the exact error reported by the Backend.
SERVER ERROR 503 Service Unavailable Server is not able to process the requisition due an overload or maintenance.

How Do You Approach API Style?

In this post, we’ve covered foundational principles to help first-time API developers understand HTTP methods, URI construction, versioning, error codes, and more. The 8 simple tips above are simply must-haves web API construction.

By following quality style conventions, you can maintain pace with developers already accustomed to web APIs and the RESTful standard. Of course, a full REST adoption would include hypermedia. For a deeper investigation into API styles, developers can peruse the API Style Book, a compilation of API design style guides maintained by Arnaud Lauret.

Going beyond these simple tips, there are certainly plenty of other theories for governance or management solutions to enforce such style. However, we’d love to hear your ideas. How is your organization handling API style?