Skip to content

Instantly share code, notes, and snippets.

@zxdcm
Created March 15, 2023 18:18
Show Gist options
  • Save zxdcm/54053f6b1fdaafb7f4112de694a295f9 to your computer and use it in GitHub Desktop.
Save zxdcm/54053f6b1fdaafb7f4112de694a295f9 to your computer and use it in GitHub Desktop.
Mark Massé - REST API Design Rulebook

Mark Massé - REST API Design Rulebook

CHAPTER 1. Introduction

REST API Design

For many of us, designing a REST API can sometimes feel more like an art than a science. Some best practices for REST API design are implicit in the HTTP standard, while other pseudo-standard approaches have emerged over the past few years. Yet today, we must continue to seek out answers to a slew of questions, such as:

  • When should URI path segments be named with plural nouns?
  • Which request method should be used to update resource state?
  • How do I map non-CRUD operations to my URIs?
  • What is the appropriate HTTP response status code for a given scenario?
  • How can I manage the versions of a resource’s state representations?
  • How should I structure a hyperlink in JSON?

CHAPTER 2. Identifier Design with URIs

URI Format

Rule: Forward slash separator (/) must be used to indicate a hierarchical relationship

The forward slash (/) character is used in the path portion of the URI to indicate a hierarchical relationship between resources. For example:

http://api.canvas.restapi.org/shapes/polygons/quadrilaterals/squares

Rule: A trailing forward slash (/) should not be included in URIs

As the last character within a URI’s path, a forward slash (/) adds no semantic value and may cause confusion. REST APIs should not expect a trailing slash and should not include them in the links that they provide to clients.

Rule: Hyphens (-) should be used to improve the readability of URIs

To make your URIs easy for people to scan and interpret, use the hyphen (-) character to improve the readability of names in long path segments. Anywhere you would use a space or hyphen in English, you should use a hyphen in a URI. For example:

http://api.example.restapi.org/blogs/mark-masse/entries/this-is-my-first-post

Rule: Underscores (_) should not be used in URIs

Rule: Lowercase letters should be preferred in URI paths

Rule: File extensions should not be included in URIs

On the Web, the period (.) character is commonly used to separate the file name and extension portions of a URI. A REST API should not include artificial file extensions in URIs to indicate the format of a message’s entity body. Instead, they should rely on the media type, as communicated through the Content-Type header, to determine how to process the body’s content.

URI Authority Design

Rule: Consistent subdomain names should be used for your API

The top-level domain and first subdomain names (e.g., soccer.restapi.org) of an API should identify its service owner. The full domain name of an API should add a sub- domain named api. For example:

http://api.soccer.restapi.org

Rule: Consistent subdomain names should be used for your client developer portal

Many REST APIs have an associated website, known as a developer portal, to help on- board new clients with documentation, forums, and self-service provisioning of secure API access keys. If an API provides a developer portal, by convention it should have a subdomain labeled developer. For example:

http://developer.soccer.restapi.org

Resource Modeling

The URI path conveys a REST API’s resource model, with each forward slash separated path segment corresponding to a unique resource within the model’s hierarchy. For example, this URI design:

http://api.soccer.restapi.org/leagues/seattle/teams/trebuchet

indicates that each of these URIs should also identify an addressable resource:

http://api.soccer.restapi.org/leagues/seattle/teams

http://api.soccer.restapi.org/leagues/seattle

http://api.soccer.restapi.org/leagues

http://api.soccer.restapi.org

Resource modeling is an exercise that establishes your API’s key concepts. This process is similar to the data modeling for a relational database schema or the classical modeling of an object-oriented system.

Before diving directly into the design of URI paths, it may be helpful to first think about the REST API’s resource model.

Resource Archetypes

Document

A document resource is a singular concept that is akin to an object instance or database record. A document’s state representation typically includes both fields with values and links to other related resources. With its fundamental field and link-based structure, the document type is the conceptual base archetype of the other resource archetypes. In other words, the three other resource archetypes can be viewed as specializations of the document archetype.

Each URI below identifies a document resource:

http://api.soccer.restapi.org/leagues/seattle

http://api.soccer.restapi.org/leagues/seattle/teams/trebuchet

http://api.soccer.restapi.org/leagues/seattle/teams/trebuchet/players/mike

Collection

A collection resource is a server-managed directory of resources. Clients may propose new resources to be added to a collection. However, it is up to the collection to choose to create a new resource, or not. A collection resource chooses what it wants to contain and also decides the URIs of each contained resource.

Each URI below identifies a collection resource:

http://api.soccer.restapi.org/leagues

http://api.soccer.restapi.org/leagues/seattle/teams

http://api.soccer.restapi.org/leagues/seattle/teams/trebuchet/players

Store

A store is a client-managed resource repository. A store resource lets an API client put resources in, get them back out, and decide when to delete them. On their own, stores do not create new resources; therefore a store never generates new URIs. Instead, each stored resource has a URI that was chosen by a client when it was initially put into the store.

The example interaction below shows a user (with ID 1234) of a client program using a fictional Soccer REST API to insert a document resource named alonso in his or her store of favorites:

PUT /users/1234/favorites/alonso

Controller

A controller resource models a procedural concept. Controller resources are like exe- cutable functions, with parameters and return values; inputs and outputs.

Like a traditional web application’s use of HTML forms, a REST API relies on controller resources to perform application-specific actions that cannot be logically mapped to one of the standard methods (create, retrieve, update, and delete, also known as CRUD).

Controller names typically appear as the last segment in a URI path, with no child resources to follow them in the hierarchy. The example below shows a controller re- source that allows a client to resend an alert to a user:

POST /alerts/245743/resend

URI Path Design

Rule: A singular noun should be used for document names

A URI representing a document resource should be named with a singular noun or noun phrase path segment.

For example, the URI for a single player document would have the singular form:

http://api.soccer.restapi.org/leagues/seattle/teams/trebuchet/players/claudio

Rule: A plural noun should be used for collection names

A URI identifying a collection should be named with a plural noun, or noun phrase, path segment. A collection’s name should be chosen to reflect what it uniformly con- tains.

For example, the URI for a collection of player documents uses the plural noun form of its contained resources:

http://api.soccer.restapi.org/leagues/seattle/teams/trebuchet/players

Rule: A plural noun should be used for store names

A URI identifying a store of resources should be named with a plural noun, or noun phrase, as its path segment. The URI for a store of music playlists may use the plural noun form as follows:

http://api.music.restapi.org/artists/mikemassedotcom/playlists

Rule: A verb or verb phrase should be used for controller names

Like a computer program’s function, a URI identifying a controller resource should be named to indicate its action. For example:

http://api.college.restapi.org/students/morgan/register

http://api.example.restapi.org/lists/4324/dedupe

http://api.ognom.restapi.org/dbs/reindex

http://api.build.restapi.org/qa/nightly/runTestSuite

Rule: Variable path segments may be substituted with identity-based values

Some URI path segments are static; meaning they have fixed names that may be chosen by the REST API’s designer. Other URI path segments are variable, which means that they are automatically filled in with some identifier that may help provide the URI with its uniqueness. The URI Template syntax‡ allows designers to clearly name both the static and variable segments. A URI template includes variables that must be substituted before resolution. The URI template example below has three variables (leagueId, teamId, and playerId):

http://api.soccer.restapi.org/leagues/{leagueId}/teams/{teamId}/players/{playerId}

The substitution of a URI template’s variables may be done by a REST API or its clients. Each substitution may use a numeric or alphanumeric identifier, as shown in the ex- amples below:

http://api.soccer.restapi.org/leagues/seattle/teams/trebuchet/players/21

http://api.soccer.restapi.org/games/3fd65a60-cb8b-11e0-9572-0800200c9a66

Rule: CRUD function names should not be used in URIs

URIs should not be used to indicate that a CRUD§ function is performed. URIs should be used to uniquely identify resources, and they should be named as described in the rules above. As discussed in “Request Methods” on page 23, HTTP request methods should be used to indicate which CRUD function is performed.

For example, this API interaction design is preferred:

DELETE /users/1234

The following anti-patterns exemplify what not to do:

GET /deleteUser?id=1234

GET /deleteUser/1234

DELETE /deleteUser/1234

POST /users/1234/delete

URI Query Design

This section provides rules relating to the design of URI queries. Recall from RFC 3986 that a URI’s optional query comes after the path and before the optional fragment:

URI = scheme "://" authority "/" path [ "?" query ] [ "#" fragment ]

As a component of a URI, the query contributes to the unique identification of a re- source. Consider the following example:

http://api.college.restapi.org/students/morgan/send-sms (1)

http://api.college.restapi.org/students/morgan/send-sms?text=hello (2)

(1) The URI of a controller resource that sends an sms message.

(2) The URI of a controller resource that sends an sms message with a text value of hello.

The query component of a URI contains a set of parameters to be interpreted as a variation or derivative of the resource that is hierarchically identified by the path com- ponent. So, while these two resources are not the same, they are very closely related.

The query component can provide clients with additional interaction capabilities such as ad hoc searching and filtering. Therefore, unlike the other elements of a URI, the query part may be transparent to a REST API’s client.

The entirety of a resource’s URI should be treated opaquely by basic network-based intermediaries such as HTTP caches. Caches must not vary their behavior based on the presence or absence of a query in a given URI. Specifically, response messages must not be excluded from caches based solely upon the presence of a query in the requested URI. As discussed later in Chapter 4, HTTP headers, not queries, must be used to direct a cache intermediary’s behavior.

Rule: The query component of a URI may be used to filter collections or stores

A URI’s query component is a natural fit for supplying search criteria to a collection or store. Let’s take a look at an example:

GET /users (1)

GET /users?role=admin (2)

(1) The response message’s state representation contains a listing of all the users in the collection.

(2) The response message’s state representation contains a filtered list of all the users in the collection with a “role” value of admin.

Rule: The query component of a URI should be used to paginate collection or store results

A REST API client should use the query component to paginate collection and store results with the pageSize and pageStartIndex parameters. The pageSize parameter specifies the maximum number of contained elements to return in the response. The pageStartIndex parameter specifies the zero-based index of the first element to return in the response. For example:

GET /users?pageSize=25&pageStartIndex=50

When the complexity of a client’s pagination (or filtering) requirements exceeds the simple formatting capabilities of the query part, consider designing a special controller resource that partners with a collection or store. For example, the following controller may accept more complex inputs via a request’s entity body instead of the URI’s query part:

POST /users/search

This design allows for custom range types and special sort orders to be easily specified in the client request message body. However, as detailed in Chapter 4, care must be taken to ensure that the controller’s cacheable results are marked accordingly.

CHAPTER 3. Interaction Design with HTTP

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment