You realize it's hard to make significant changes to your API once it's released and want to get as much right as possible up front. Now, the Internet has no shortage on opinions on API design.
But because there's no one widely adopted standard that works in all cases, you're left with a bunch of choices: What formats should you accept? How should you authenticate? Should your API be versioned?
Let's first start with the basic guidelines...
What Is REST?
Representational State Transfer (REST) is a technical description of how the World Wide Web works. Imagine if the web was a device. If it could have an operating system, its architectural style would be REST. A REST Application Programming Interface (REST API) is a type of web server that enables a user-operated or automated clients to access resources that model a system’s data and functions. A well-designed REST API entices developers to use the web service and is today a must-have feature. But how to clearly define whether the API is actually REST? Such architecture describes six constraints, and we are going to describe them below in this article.
The uniform interface that any REST services must provide is fundamental to its design.
Its constraint defines the interface between clients and servers. The four guiding principles of the uniform interface are:
- Resource-based: Individual resources are defined in requests using URIs as resource identifiers and are separate from the responses that are returned to the client.
- Actions on resources through representations: When a client gets a representation of a resource, including any metadata attached, it has enough information to customize or delete the resource on the server, if it has permission to do so.
- Self-descriptive messages: Each message includes a precise information that describes how to process it. The responses also clearly indicate their cache-ability.
- Hypermedia as the Engine of Application State (HATEOAS): Clients deliver the state via body contents, query-string parameters, request headers, and the requested URI. Services deliver state to clients via body content, response codes, and response headers.
The uniform interface divides clients from servers. This means that, for instance, clients are not concerned with data storage, which remains internal to each server, so that the portability of client code is improved. Servers are not engaged with the user interface or user state so they can be simpler and more scalable. Servers and clients may also be replaced and developed independently, as long as the interface is not modified. Most importantly here is to have the interface intact — one may also give your clients an online REST API documentation or mocking your REST APIs to help the clients to start connecting.
The necessary state to operate the request is contained within it as a part of the URI, query-string parameters, body, or headers. The URI identifies the resource, and the body contains the state of it. Therefore, after the server does its processing, the appropriate state, or the pieces of it, communicates back to the client via headers, status, and response body.
As the clients can cache responses, they need to be implicitly or explicitly defined as cacheable or not to prevent clients from reusing state or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some client–server interactions and improves the performance.
Microservices or layered systems are where the client cannot ordinarily tell whether it is connected directly to the end server or to an intermediary along the way. Mediate servers or API Gateways may improve system scalability by enabling load-balancing and by providing shared caches. Layers also enforce security policies.
Code on Demand
Getting RESTful API versioning right can have a major impact on the how your API is perceived by your API consumers internally or externally and can also make the management of your API estate more difficult if it’s ill conceived.
Versioning is therefore an important part of a style guide, and it’s probably more important to create a policy exhaustively across your organization; if all teams took different approaches, as they might in an autonomous model, managing dependencies between APIs across your organization will become very difficult indeed.
A versioning policy should therefore be defined top-down, with clear guidelines on when and why to version your APIs. Any flexibility should be granted to teams in the how, allowing them to implement version requests as they see fit (in custom headers, the Accept header or as part of the URI).
REST API Building Blocks:
Here are probably the most important the fundamental building blocks of an API:
- Resources (URIs)
- HTTP methods
- HTTP headers
- Query parameters
- Return codes
Anyone who looks at these five areas and is an expert in HTTP and REST APIs would argue that all of these are designed for specific purposes and clearly should only be used with those purposes in mind.
However, it’s quite possible that many developers creating your API won’t know (and in some cases won’t really care) about the distinctions or the fundamental principles of REST.
The job of the style guide or RESTful API documentation both for developers and your customers (but mainly guidelines for the developers) is to detail when and how to use each of these: It limits interpretation where limits need to be set. An example set of guidelines might be:
- Resources should describe the “objects” that your API describes, with an identifier that uniquely identifies each object.
- HTTP methods are used to “change” the state of the object, with a mandated list of supported methods.
- HTTP headers are used for passing mandatory arguments such as for authentication, accepted content types, etc.
- Query parameters are used for optional arguments or filtering (searching) and can be omitted as required.
- Return codes should mirror the meaning and semantics of the core HTTP specification, ensuring the code is informative and embellished with extra information in the payload where required.
The idea of such guidelines is to clearly lay out for developers how to treat each of these types of constructs: To define what it is for and how to implement it.
The more authoritarian style guides will dive into areas such as exact resource constructs and allowed HTTP headers, therefore leaving little doubt in the developer’s mind.
The conclusion is that violating any constraint other than Code on Demand means that service is not strictly RESTful. Complying with all constraints, and thus conforming to the REST architectural style, will enable any kind of distributed hypermedia system to have desirable emergent properties, such as performance, scalability, simplicity, modifiability, visibility, portability, and reliability.