Follow @bissell
Michael's blog
Michael's resume

The API Contract
Default Formats
General API Management
Error Standards
Response Codes
Cherry Picking
Change Logs


Collections are like a big file folder -- you all objects in a collection should use the same fields and, therefore, be easily filtered and sorted.

Collections should always be plural


Collections should list the items (not be the contents)
This is a tricky balance: you want to include enough information in the response from a collection to be meaningful, but you don’t need to return the complete detail of the actual object in that collection.

For example, the /people collection may return this:

{ "content": [ { "id": "0f52e80c-4fc5-11e8-9c2d-fa7ae01bbebc", "userName": "somebody@somewhere.ext", "firstName": "", "lastName": "", "agencyCode": [ "10301", "8765" ], "created": 1289664881, "modified": 1475142772 }, { "id": "1f52e80e-efc5-a1e6-0c2d-ea7ae01bbc098", "userName": "john.doe@tic.ext", "firstName": "John", "lastName": "Doe", "agencyCode": [ "5217", "1234" ], "created": 1389664892, "modified": 1575142792 }

but the detail of a person may contain a great deal more information

{ "id": "a795b4c2-2dd6-4004-8ecd-daa772bb78e9", "userName": "somebody@somewhere.ext", "firstName": "", "lastName": "", "emailAddress": [ { "email": "somebody@somewhere.ext", "verified": "no", "source": "from userName", "roles": [ { "email": "somebody@somewhere.ext", "roleType": "Company Roles", "role": "Company Coordinator", "source": "Salesforce", "created": 1389664892, "modified": 1575142792, "agencyCode": "10301", "accountId": "8a1d7aca-8e2f-4dbc-88d5-bd0c3fec0833" } ] } ], "agencyCode": [ "10301", "8765" ], "groups": [ { "agencyCode": "8765", "agencyName": "Thee Initial Corporation", "groups": [ "Company Roles Company Coordinator", "A - Company (Web-based)", "Partner" ] }, { "agencyCode": "10301", "agencyName": "Some Co.", "groups": [ "Company Roles Company Coordinator", "A - Company (Web-based)", "Partner" ] } ], "created": 1289664881, "modified": 1475142772 }

Informative footers

The bottom of the collection should return information about the collection that can be used to paginate and to understand the way the data was returned:

"last": false, "totalPages": 1488, "totalElements": 29754, "first": false, "sort": [ { "direction": "ASC", "property": "accountName", "ignoreCase": false, "nullHandling": "NATIVE", "ascending": true } ], "numberOfElements": 20, "size": 20, "number": 5

Or, a more old-school comparison of data and descriptions:
"totalElements": 29754,
"size": 20,
"totalPages": 1488,
"numberOfElements": 20,
"first": false,
"last": false,
"number": 5,
"sort": null
There are 29,754 items in this collection
We're returning 20 elements per page
There are 1,488 pages in this response (20/page)
There are 20 items on this page
This isn't the first page of the collection
This isn't the last page of the collection
We're on page 5
The results aren't sorted (asc|desc) (see below for sort array)

Because we allow sorting multiple ways, the sort block is an array of JSON elements that describe the different elements and the direction they are sorted on

"sort": [ { "direction": "ASC", "property": "accountName", "ignoreCase": false, "nullHandling": "NATIVE", "ascending": true }, { "direction": "DESC", "property": "agencyCode", "ignoreCase": false, "nullHandling": "NATIVE", "ascending": false } ],

Accessing Items in Collections

Generally, individual items inside a collection should be accessible by a unique key like


Or, as a real world example:


However, it is permissible to alias the unique key to a human readable id such as


This human readable also provides us with the ability to add path-variable security based on OAuth scopes (for example, if I have a scope that restricts access to my own company record based on /agencies/$agencyCode/* and my agecnyCode is returned as 1234, I would able to access /agencies/1234/agreeements but not /agencies/4567/agreements.

Collections within collections

When there is a sub collection (say all the products for an agency) you should be able to reference the sub-collection by a unique name.

Be sure to see my blog over at Cloudenity. This week's topic: The Physical Impossibility of Migrating to the Cloud