What Is a REST API?

Every API is designed to share some information with its customers. But why is REST special?

An API is an application programming interface. APIs allow software applications to talk to each other through calls and responses.

REST stands for REpresentational State Transfer and is a representation of how resources get manipulated in the API. 

REST brings some standards to the way in which APIs are built. However, there are no strict rules of how an API should be structured to make it RESTful. One of the main points with REST is that the API’s structure should be consistent.

There are many specifications on how to build a RESTful API. At ExaVault, we’ve decided to follow the JSON API specification. It provides the schema design for RESTful API using a JSON format.

On a high level, we’ll go over some concepts that a RESTful API would use.

Concepts for REST API

Resource

Resources usually are the entities the system operates. This is a key notion in REST API, since all operations are performed on resources via API endpoints. For example, there might be a User entity in the system, which can be considered a resource in REST API. That means users can be manipulated using URLs starting with /users.

Resource methods

After resources have been defined, the next step is to identify what operations can be performed on resources (or so-called resource methods.) In the User example, there can be multiple operations on that resource: read, create, update, delete. In previous API versions, we appended operation name to each endpoint (e.g. getUser, createUser, etc.) In REST API this can be done using HTTP methods along with resource URLs.

For example, sending a GET request with a user ID will return the user object.

GET /users/123

Creating a user request should be sent via the POST method to the /users endpoint with some user information in the request body.

POST /users

{“username”: “Bob”, “phoneNumber”: “+1987654321”}

There are two more useful HTTP methods: PATCH (for updating resources) and DELETE (for deleting resources.)

Relationships

Very often, resources are linked together with relationships. For example, a user uploads some files, then those files are related to the user. One resource (such as a user) can have one or more related resources. For example, besides uploaded files, a user can be related to an account. As we know, each resource type has its own URL. Therefore if we want to retrieve an uploaded file’s owner information, we need to make multiple requests (first get file object and then user object.) The most obvious solution is always including related resources in responses.

{
    "id": 4321,
    "path": "/Customers Data.pdf",
    "created": "2020-02-07 18:31:00",
    "owner": {
   	 "id": 123,
   	 "name": "Bod Smith",
   	 "phone": "+1234567890"
    }
}

But that can massively increase the amount of transferred data over the network, whereas we don’t need related data all the time.

The JSON API suggests a solution that allows you to request related resources on demand. Request related resources by using an additional query parameter called include. For example, GET /files?include=owner — will return files along with owner objects (as shown in the example above.) Multiple relationships can be requested as a comma separated list in the include parameter (e.g. GET /files?include=owner,folder). 

The one problem with the schema is that when all the files are owned by the same user, it includes the same user object many times, which again massively increases the amount of data transferring.

Notice how the owner object repeated every time.

[
   {
     "id": 4321,
     "path": "/Customers Data.pdf",
     "created": "2020-02-07 18:31:00",
     "owner": {
       "id": 123,
       "name": "Bod Smith",
       "phone": "+1234567890"
     }
   },   
   {
     "id": 4322,
     "path": "/Customers Data1.pdf",
     "created": "2020-02-07 18:31:05",
     "owner": {
       "id": 123,
       "name": "Bod Smith",
       "phone": "+1234567890"
     }
   },   
   {
     "id": 4323,
     "path": "/Customers Data2.pdf",
     "created": "2020-02-07 18:31:10",
     "owner": {
       "id": 123,
       "name": "Bod Smith",
       "phone": "+1234567890"
     }
   }
]

A suggestion to reduce duplication would be separating the main resource objects and related objects. The main resources should have relationship definitions.

Using the suggestion, now a file object looks like this:

{
 "id": 4321,
 "path": "/Customers Data.pdf",
 "created": "2020-02-07 18:31:00",
 "relationships": {
   "owner": {
     "id": 123,
     "type": "user"
   },
   "folder": {
     "id": 321,
     "type": "folder"
   }
 }
}

There is now a relationships object that defines all the resources related to the file object. A relationship definition is an object with two properties: id and type. The id is a unique identifier for the related object, and type is the type of related object.

The actual separation of related objects from main objects is implemented by a more advanced response structure.

{
 "data": [
   {
     "id": 4321,
     "path": "/Customers Data.pdf",
     "created": "2020-02-07 18:31:00",
     "relationships": {
       "owner": {
         "id": 123,
         "type": "user"
       },
       "folder": {
         "id": 321,
         "type": "folder"
       }
     }
   },
   {
     "id": 4322,
     "path": "/Customers Data1.pdf",
     "created": "2020-02-07 18:31:00",
     "relationships": {
       "owner": {
         "id": 123,
         "type": "user"
       },
       "folder": {
         "id": 321,
         "type": "folder"
       }
     }
   },
   {
     "id": 4323,
     "path": "/Customers Data2.pdf",
     "created": "2020-02-07 18:31:00",
     "relationships": {
       "owner": {
         "id": 123,
         "type": "user"
       },
       "folder": {
         "id": 321,
         "type": "folder"
       }
     }
   }
 ],
 "included": [
   {
     "id": 321,
     "type": "folder",
     "name": "Company Data",
     "created": "2020-01-30 17:45:21"
   },
   {
     "id": 123,
     "type": "user",
     "name": "Bob Smith",
     "phone": "+1234567890"
   }
 ]
}

At the top level there are two parts: data and included. The data part has objects of the resources we requested. Included contains all the related objects (if we requested them using included URL parameter) to the main ones. Main resources still have a relationships definition, so they are linked with related resources via type and id (related objects can be retrieved from the included section.)

Authorization

It’s natural to hide parts of a system from some users and show them to others. To differentiate users in REST API, we can use authorization mechanisms. Nowadays, the most popular and quite powerful authorization mechanism is OAuth. The REST API OAuth provides a special endpoint for obtaining an access token and then using it for authenticated requests to API. One good implementation of OAuth in PHP was done by the Laravel Passport package.

So, Why Is REST Special?

Having a consistent API structure is important. REST is an efficient standard when creating your API and is often considered the standard protocol for web APIs. As you have seen with our code samples, REST API is easier to understand than other options. Because it is more user-friendly, companies and developers like the RESTful way of approaching their APIs.

With a set of request methods that is standardized, the REST architecture provides an excellent base for developing. And a modern, RESTful API like ExaVault’s is easy to use with any number of languages from Ruby to Javascript/Node or PHP and more.


Integration is easy with ExaVault’s powerful API – Get Started Today!