Introduction to REST APIs - What is a REST API? How to use or build a REST API?

Introduction to REST APIs - What is a REST API? How to use or build a REST API?

What is a REST API?

A REST API is a way of designing and implementing web services that follow the principles of REpresentational State Transfer (REST). REST is an architectural style that was proposed by Roy Fielding in his doctoral dissertation in 2000. REST is not a standard or a protocol, but a set of guidelines and best practices for creating scalable, interoperable, and maintainable web services.

A REST API is based on the idea of resources, which are any entities or concepts that can be identified by a Uniform Resource Identifier (URI). A resource can be anything from a document, an image, a user, a product, or a collection of other resources. A REST API exposes these resources to clients through a uniform interface, which consists of a set of HTTP methods and media types. A REST API also follows the principle of statelessness, which means that each request from a client to a server must contain all the information necessary to understand and process the request, and that the server does not store any client-specific state.

A REST API allows clients to perform four basic operations on resources: CreateReadUpdate, and Delete (CRUD). These operations correspond to the HTTP methods of POSTGETPUT, and DELETE, respectively. For example, a client can create a new user resource by sending a POST request to the URI /users, read an existing user resource by sending a GET request to the URI /users/{id}, update an existing user resource by sending a PUT request to the URI /users/{id}, and delete an existing user resource by sending a DELETE request to the URI /users/{id}.

A REST API also supports the concept of hypermedia, which means that the responses from the server can contain links to other related resources, allowing the client to discover and navigate the API dynamically. This is also known as the HATEOAS principle, which stands for Hypermedia As The Engine Of Application State. For example, a response from the server for a GET request to the URI /users/{id} can include a link to the user’s profile resource, such as "profile": "/users/{id}/profile".

Why is REST API so dominant nowadays?

REST API has become the dominant style of web service design and implementation for several reasons. Some of the main advantages of REST API are:

  • Simplicity: REST API is based on the existing and widely used standards of HTTP and URI, which makes it easy to understand and implement. REST API does not require any additional tools or libraries, and can be used with any programming language or platform that supports HTTP.
  • Scalability: REST API is stateless, which means that the server does not need to store any client-specific state or session information. This reduces the server’s memory and processing load, and allows the server to handle more concurrent requests. REST API also supports caching, which means that the server can store and reuse the responses for frequently requested resources, reducing the network traffic and improving the performance.
  • Interoperability: REST API is based on a uniform interface, which means that the clients and servers only need to agree on the HTTP methods and media types, and do not need to know any details about each other’s implementation or logic. This makes REST API compatible with any type of client, such as web browsers, mobile apps, or other web services. REST API also supports multiple media types, such as JSON, XML, HTML, or plain text, which allows the clients and servers to exchange data in different formats according to their preferences and capabilities.
  • Maintainability: REST API is based on the principle of resource identification, which means that the URIs are meaningful and descriptive, and do not expose any implementation details or parameters. This makes REST API easy to document and test, and also allows the server to evolve and change its implementation without affecting the clients, as long as the URIs and the uniform interface remain consistent.

How to design and implement a REST API?

There is no definitive or authoritative way to design and implement a REST API, as different scenarios and requirements may call for different approaches and trade-offs. However, there are some general guidelines and best practices that can help to create a good and consistent REST API. Some of the main aspects to consider are:

  • Resource identification: The first step in designing a REST API is to identify the resources that the API will expose, and assign them meaningful and descriptive URIs. The URIs should follow a hierarchical and logical structure, and use nouns rather than verbs to represent the resources. For example, /users is a better URI than /getAllUsers, and /users/{id}/profile is a better URI than /getUserProfile?id={id}. The URIs should also use lower case letters, hyphens to separate words, and plural forms to represent collections of resources. For example, /users/{id}/profile-pictures is a better URI than /Users/{id}/ProfilePictures.
  • Resource representation: The next step in designing a REST API is to decide how the resources will be represented and exchanged between the clients and servers. The most common and recommended media type for REST API is JSON, which is a lightweight, human-readable, and widely supported format for data serialization. JSON can represent different types of data, such as strings, numbers, booleans, arrays, and objects, and can also include links to other resources using the JSON Hyper-Schema specification. A good JSON representation should be consistent, concise, and self-explanatory, and follow the naming conventions and formatting rules of the JSON standard. For example, a JSON representation of a user resource could look like this:
{
  "id": 123,
  "name": "Alice",
  "email": "[email protected]",
  "profile": "/users/123/profile",
  "friends": [
    {
      "id": 456,
      "name": "Bob",
      "profile": "/users/456/profile"
    },
    {
      "id": 789,
      "name": "Charlie",
      "profile": "/users/789/profile"
    }
  ]
}

A JSON resource from a REST API

  • Resource manipulation: The final step in designing a REST API is to define how the resources will be manipulated and accessed by the clients using the HTTP methods and status codes. The HTTP methods should follow the CRUD operations, and the status codes should indicate the outcome and the state of the resources. For example, a POST request to the URI /users should create a new user resource and return a status code of 201 Created. Some API's also return the URI of the newly created resource in the Location header.

    A GET request to the URI /users/{id} should retrieve an existing user resource and return a status code of 200 OK, along with the JSON representation of the resource in the response body. A PUT request to the URI /users/{id} should update an existing user resource and return a status code of 200 OK or 204 No Content, depending on whether the response body contains the updated resource or not. A DELETE request to the URI /users/{id} should delete an existing user resource and return a status code of 200 OK or 204 No Content, depending on whether the response body contains the deleted resource or not.

There are also some other aspects to consider when designing and implementing a REST API, such as:

  • Authentication and authorization: A REST API should provide a secure and reliable way of verifying the identity and the permissions of the clients who access the resources. There are different methods and protocols for implementing authentication and authorization, such as Basic Authentication, OAuth, JWT, or API keys. The choice of the method depends on the level of security and complexity required by the API. A REST API should also use HTTPS to encrypt the communication between the clients and servers, and prevent any unauthorized or malicious access or modification of the resources.
  • Pagination and filtering: A REST API should provide a way of handling large collections of resources, and allowing the clients to specify the amount and the criteria of the resources they want to retrieve. Pagination is a technique of dividing a large collection into smaller subsets, and providing the clients with links to navigate between them. Filtering is a technique of applying some conditions or parameters to a collection, and returning only the resources that match them.

    There are different ways of implementing pagination and filtering, such as using query parameters, headers, or custom media types. For example, a GET request to the URI /users?limit=10&offset=20 could return a subset of 10 users starting from the 21st user in the collection, and a GET request to the URI /users?name=Alice could return only the users whose name is Alice.
  • Documentation and testing: A REST API can provide a way of describing and explaining the resources, the interface, and the behavior of the API, and allowing the clients and the developers to verify and validate the functionality and the quality of the API. Documentation is a technique of creating and maintaining a clear and comprehensive guide or reference for the API, which can be either human-readable or machine-readable, or both.

    There are different tools and formats for creating documentation, such as Swagger, RAML, API Blueprint, or OpenAPI Specification. Testing is a technique of applying different scenarios and cases to the API, and checking the expected and the actual outcomes and responses. There are different tools and frameworks for testing, such as Postman, SoapUI, RestAssured, or Mocha.
  • Versioning: A REST API can provide a way of managing the changes and the evolution of the resources and the interface, and informing the clients about them. Versioning is a technique of assigning a unique identifier to each version of the API, and allowing the clients to specify the version they want to use.

    There are different ways of implementing versioning, such as using URI segments, query parameters, headers, or media types. For example, a GET request to the URI /v1/users could use the first version of the API, and a GET request to the URI /v2/users could use the second version of the API.

Examples of REST API

There are many examples of REST API in the real world, as many popular and widely used web services and platforms use REST API to expose their resources and functionality to their clients and users. Some of the well-known examples of REST API are:

  • Twitter API: Twitter is a social media platform that allows users to post and interact with short messages called tweets. Twitter API is a REST API that allows developers to access and manipulate the Twitter resources, such as users, tweets, followers, trends, and more. Twitter API uses JSON as the media type, OAuth as the authentication method, and supports multiple versions and endpoints. For example, a GET request to the URI https://api.twitter.com/1.1/users/show.json?screen_name=bing could return the JSON representation of the user resource with the screen name “bing”.
  • Google Maps API: Google Maps is a web mapping service that provides various features and functions, such as geocoding, directions, distance matrix, places, and more. Google Maps API is a REST API that allows developers to access and integrate the Google Maps resources and functionality into their applications and websites. Google Maps API uses JSON or XML as the media type, API keys as the authentication method, and supports multiple versions and services. For example, a GET request to the URI https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY could return the JSON representation of the geocoding result for the given address.
  • Spotify API: Spotify is a music streaming service that offers various features and functions, such as playlists, tracks, albums, artists, and more. Spotify API is a REST API that allows developers to access and manipulate the Spotify resources and functionality into their applications and websites. Spotify API uses JSON as the media type, OAuth as the authentication method, and supports multiple versions and endpoints. For example, a GET request to the URI https://api.spotify.com/v1/artists/3TVXtAsR1Inumwj472S9r4 could return the JSON representation of the artist resource with the id “3TVXtAsR1Inumwj472S9r4”, which is Drake.

The Do’s and don’ts

To create a good and consistent REST API, there are some do’s and don’ts that should be followed and avoided, respectively. Some of the main do’s and don’ts of REST API are:

  • Do use meaningful and descriptive URIs for the resources, and follow the naming conventions and the hierarchical structure.
  • Don’t use verbs or actions in the URIs, and avoid using unnecessary or redundant parameters or segments.
  • Do use JSON as the default media type for the resource representation, and follow the JSON standard and the naming conventions.
  • Don’t use XML or other media types unless they are explicitly requested or supported by the clients or the servers.
  • Do use the HTTP methods and status codes according to the CRUD operations and the outcome of the requests, and follow the HTTP standard and the semantics.
  • Don’t use custom or non-standard methods or status codes, and avoid returning ambiguous or misleading responses.
  • Do use hypermedia and links to enable the clients to discover and navigate the API dynamically, and follow the HATEOAS principle and the JSON Hyper-Schema specification.
  • Don’t use hard-coded or absolute URIs, and avoid creating dependencies or assumptions between the clients and the servers.
  • Do use authentication and authorization methods to secure and protect the resources, and follow the best practices and the protocols.
  • Don’t use plain text or insecure methods to transmit or store the credentials or the data, and avoid exposing or compromising the resources.
  • Do use pagination and filtering methods to handle large collections of resources, and follow the best practices and the techniques.
  • Don’t return all or none of the resources, and avoid creating performance or usability issues.
  • Do use versioning and documentation methods to manage the changes and the evolution of the API, and follow the best practices and the tools.
  • Don’t make breaking or incompatible changes to the API, and avoid creating confusion or frustration for the clients and the developers.
  • Do use testing and validation methods to verify and improve the functionality and the quality of the API, and follow the best practices and the frameworks.
  • Don’t assume or ignore the errors or the bugs in the API, and avoid creating unreliable or faulty services.

Naming convention and structure of REST API

One of the important aspects of designing a REST API is to choose a consistent and logical naming convention and structure for the resources and the URIs. A good naming convention and structure can improve the readability, usability, and maintainability of the API, and also convey the meaning and the relationship of the resources. There is no definitive or authoritative way to choose a naming convention and structure for a REST API, as different scenarios and requirements may call for different approaches and solutions. However, there are some general guidelines and best practices that can help to create a good naming convention and structure for a REST API. Some of the main guidelines and best practices are:

  • Use nouns rather than verbs: A REST API is based on the idea of resources, which are entities or concepts that can be identified by URIs. Therefore, the URIs should use nouns to represent the resources, rather than verbs to represent the actions or operations on the resources. For example, /users is a better URI than /getAllUsers, and /users/{id}/profile is a better URI than /getUserProfile?id={id}. The actions or operations on the resources should be indicated by the HTTP methods, such as POST, GET, PUT, and DELETE, rather than by the URIs.
  • Use lower case letters: A REST API should use lower case letters for the URIs, as they are case-sensitive and can cause confusion or errors if mixed with upper case letters. For example, /users is a better URI than /Users, and /users/{id}/profile is a better URI than /Users/{id}/Profile.
  • Use hyphens to separate words: A REST API should use hyphens to separate words in the URIs, as they are more readable and user-friendly than other separators, such as underscores, spaces, or camel case. For example, /users/{id}/profile-pictures is a better URI than /users/{id}/profile_pictures/users/{id}/profile pictures, or /users/{id}/profilePictures.
  • Use plural forms to represent collections: A REST API should use plural forms to represent collections of resources, as they are more intuitive and consistent than singular forms. For example, /users is a better URI than /user, and /users/{id}/profile-pictures is a better URI than /users/{id}/profile-picture. The singular forms should be used to represent individual resources, such as /users/{id} or /users/{id}/profile.
  • Use query parameters to filter or sort collections: A REST API should use query parameters to filter or sort collections of resources, as they are more flexible and convenient than using URI segments or headers. For example, a GET request to the URI /users?name=Alice&age=25&sort=asc could return only the users whose name is Alice and age is 25, sorted in ascending order. The query parameters should be meaningful and descriptive, and follow the naming conventions and the formatting rules. For example, name=Alice is a better query parameter than n=Alice, and age=25 is a better query parameter than a=25.
  • Use sub-resources to represent relationships: A REST API should use sub-resources to represent relationships between resources, as they are more expressive and hierarchical than using query parameters or headers. For example, /users/{id}/profile is a better URI than /profile?user={id}, and /users/{id}/profile-pictures/{pid} is a better URI than /profile-pictures?user={id}&pid={pid}. The sub-resources should be meaningful and descriptive, and follow the naming conventions and the hierarchical structure. For example, /users/{id}/profile-pictures is a better URI than /users/{id}/pictures, and /users/{id}/profile-pictures/{pid} is a better URI than /users/{id}/pictures/{pid}.

Handling errors in a REST API

Errors are inevitable in any web service, and a REST API should provide a way of handling and reporting errors in a consistent and informative manner. Errors can occur for various reasons, such as invalid requests, server failures, network issues, or business logic errors. A good error handling strategy can improve the user experience and the reliability of the API, and also help the developers to debug and fix the errors.

There are different types and levels of errors in a REST API, and they can be classified according to the HTTP status codes. The HTTP status codes are divided into five categories, based on the first digit of the code:

  • 1xx: Informational responses, indicating that the request has been received and is being processed.
  • 2xx: Success responses, indicating that the request has been successfully completed and the expected result has been returned.
  • 3xx: Redirection responses, indicating that the request needs to be redirected to another URI or resource.
  • 4xx: Client error responses, indicating that the request is invalid or cannot be fulfilled due to some error on the client side.
  • 5xx: Server error responses, indicating that the request cannot be completed due to some error on the server side.

A REST API should use the appropriate HTTP status code to indicate the outcome and the state of the request, and follow the HTTP standard and the semantics. For example, a GET request to the URI /users/{id} should return a status code of 200 OK if the user resource exists and is retrieved, a status code of 404 Not Found if the user resource does not exist or is not found, and a status code of 500 Internal Server Error if the server encounters an unexpected error while processing the request.

In addition to the HTTP status code, a REST API should also return a meaningful and descriptive error message in the response body, using the same media type as the normal response, such as JSON. The error message should contain some information and details about the error, such as the error code, the error message, the error type, and the error description. The error message should also follow a consistent and logical format and structure, and use the naming conventions and the formatting rules. For example, a JSON error message for a GET request to the URI /users/{id} could look like this:

{
  "error": {
    "code": 404,
    "message": "User not found",
    "type": "ResourceNotFoundError",
    "description": "The user with the id {id} does not exist or is not available"
  }
}

Logging and monitoring

A REST API could provide a way of logging and monitoring the errors that occur in the API, and storing and analyzing the error data. This can help to identify and diagnose the root causes and the patterns of the errors, and to improve and optimize the API performance and quality. There are different tools and frameworks for logging and monitoring, such as Logstash, Kibana, Grafana, or Prometheus.

A very simple example is recording a client-side error. If an error occurs, you can utilize the browser's global error handler to send a POST request to, for example, /js-error and include:

  • The time of the error
  • The error message
  • The stack trace
  • The client browser/operating system (for troubleshooting and debugging - perhaps the bug only happens in Safari?)

Versioning a REST API

Versioning a REST API is a way of managing changes in the API without breaking the existing clients. Versioning allows the API to evolve and improve over time, while maintaining backward compatibility and avoiding confusion.

There are different strategies for versioning a REST API, each with its own advantages and disadvantages. Some of the common strategies are:

  • URI versioning: This strategy involves adding a version identifier to the URI of the API, such as /v1/users or /v2/users. This makes the version explicit and easy to understand.
  • Media type versioning: This strategy involves using the Accept and Content-Type headers to specify the version of the API, such as application/vnd.example.v1+json or application/vnd.example.v2+json. This preserves the URIs of the resources, but it also adds complexity to the content negotiation and requires the clients to know the media types in advance.
  • Custom header versioning: This strategy involves using a custom header to indicate the version of the API, such as X-API-Version: v1 or X-API-Version: v2. This is similar to media type versioning, but it avoids the need to define custom media types.
  • No versioning: This strategy involves not using any version identifier for the API, and instead relying on backward compatibility and graceful degradation. This simplifies the API design and usage, but it also limits the ability to introduce breaking changes.

There is no definitive answer to which strategy is the best for versioning a REST API. The choice depends on the context and the trade-offs involved.

Conclusion

A REST API is not a standard or a protocol, but a set of guidelines and best practices, and there is no definitive or authoritative way to design and implement a REST API, as different scenarios and requirements may call for different approaches and solutions. However, as described here, there are some general guidelines and best practices that can help to create a good and consistent REST API

By following these guidelines and best practices, and by using the appropriate tools and frameworks, developers can create and implement a REST API that is simple, scalable, interoperable, and maintainable!