Opinionated web service APIs are quickly going out of style and not without good reason. Before uncovering the reasons for this change, it's important to understand what opinionated APIs are, and why the alternative is better.

Opinions are like...

Opinionated APIs require formatting and sending of data in a specific way. Thinking of web service APIs, the Simple Object Access Protocol (SOAP) interface or the Remote Procedure Call (RPC) which inspired it - may come to mind. The SOAP protocol is standard for sending messages across networks in XML format. SOAP XML requests must be wrapped in envelope containers which define their structure and follow specific data encoding rules. In practice these requests are quite verbose.

Suppose a user wants a list of dogs, with name and age, from a dog shelter's server. Using SOAP, the user request may look like this:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
   <ns1:getDogs soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="https://localhost:9031/ssodir/services/SSODirectoryService"/>
 </soapenv:Body>
</soapenv:Envelope>

And the response containing the list of dogs:

<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
   <getDogsResponse
       soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
     <getDogsReturn
         soapenc:arrayType="ns1:dog[2]"
         xmlns:ns1="urn:BeanService"
         xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding"
         xsi:type="soapenc:Array">
       <getDogsReturn href="#id0"/>
       <getDogsReturn href="#id1"/>
     </getDogsReturn>
   </getDogsResponse>
   <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:BeanService" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:dog">
     <name xsi:type="xsd:string">Rusty</name>
     <breed xsi:type="xsd:string">mix</breed>
     <age xsi:type="xsd:int">4</age>
   </multiRef>
   <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns3="urn:BeanService" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:dog">
     <name xsi:type="xsd:string">Callie</name>
     <entityId xsi:type="xsd:string">pitbull</entityId>
     <age xsi:type="xsd:int">3</age>
   </multiRef>
 </soapenv:Body>
</soapenv:Envelope>

In this example, the user asked for a list of dogs. The response contained only two dogs, and already the XML seems to be exploding. Imagine using SOAP for all these requests...the extra data will slow anybody down - from both development and network traffic perspectives.

Leave Opinions Behind

Representational State Transfer (REST) is a style of architecture for web services that defines a set of rules that can be applied to systems resources and how they are handled. REST is based on the concept of performing actions on resources and usually used over HTTP. When implementing REST, developers follow a set of guidelines while designing their API, but there aren’t any specific data types or structures to implement. Only the freedom to model data in any chosen format.

Implementing the same dog list from the SOAP example, it's possible to define ‘/dogs’ as a resource and use the HTTP verb GET to ask for the same list of dogs.

Request:

GET /dogs HTTP/1.1
Accept: application/json


Response:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 165
[
    {
        "age": 4,
        "breed": "mix",
        "name": "Rusty"
    },
    {
        "age": 3,
        "breed": "pitbull",
        "name": "Callie"
    }
]

How easy was that? No worrying about envelopes, headers, data types, or XML schemas. Just ask for the data and get it back in a clear, human-readable way.

Design

Comparing different API styles, it's easy to see that the SOAP approach is based on actions, making it verb based. Using XML the user calls a method named ‘getDogs’. In the REST example, the data was modeled based on a resource, or noun. Using the standard HTTP GET verb on the resource becomes necessary in order to retrieve it.

One of the main goals of REST? To standardize client server interactions in a simplified and predictable way. REST accomplishes this goal by standardizing the interface used to make requests. By only using the standard HTTP verbs GET, POST, PUT and DELETE on a list of defined resources, it greatly reduces the complexity of using the API. Loosely speaking, these verbs can be mapped to standard CRUD operations.

HTTP                  CRUD
----                  ----
GET                   Read
POST                  Create
PUT                   Update
DELETE                Delete

This interface contract allows modifications to the client and server code as long as both sides still adhere to the contract. Suppose the /dogs resource is exposed to a client, but now has a new requirement to support dog lists filtered by breed. Using REST resources, optional filter params are easily added to any resource without requiring clients to change existing code. The resource for dogs, filtered by breed, would look like ‘/dogs?breed=pitbull’ leaving support for the original unfiltered ‘/dogs’ resource fully intact.

Converting Actions to Resources

Wondering how to model existing actions as REST resources instead? Resource design really deserves a blog post of its own - be on the look out for one in the follow up post REST Easier - but to offer an idea of how it works, here are some examples:

createDog         POST       /dogs
getDogs           GET        /dogs
getDogById        GET        /dogs/rusty
getBreed          GET        /dogs/rusty?attributes=breed
boardDog          PUT        /kennels/atlboarding/dogs/rusty
adoptDog          DELETE     /rescues/atlpitbullrescue/dogs/callie

Another advantage of REST is its clean data format. In the example above, the response for a collection of dogs was a simple JSON document containing only the requested data - without extra headers, data types, or schema validation. REST APIs can support other data types such as XML and even allow the client to specify their preferred data type, if needed.

Stateless

A requirement of REST APIs: they must be stateless. This means that every request from the client must contain all the information needed to process the request, as the server is not responsible for tracking the clients state or previous requests. The benefit of statelessness? It promotes scalability. When the time comes to scale up the number of servers, life is simplified by not needing to worry about managing client state across servers.

Modern Architecture

Its not good enough to have just a website. To remain relevant, companies need apps that work across an increasing number of platforms - web, mobile, wearables, etc. It’s a common need to provide data access to third parties as well. Building a REST API can consolidate data access to a single code base. Far easier to maintain than writing custom services for each different application. No matter how many different platforms are used, they can all send/receive data from the same REST API.

Summary

We’ve taken a look at REST and why it continues to gain traction in the age of multiple app platforms. Simplicity, human-readable format, and ability to scale make a very compelling case, even though this blog barely scratched the surface of how to actually design such an API. With some of the main advantages made clear there's hope that all developers consider giving it a chance if they haven’t done so already.