Collections
Collections should always be plural
/people
/agencies
/roles
/agencies
/roles
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/collection/[itemId]
Or, as a real world example:
/people/56e21c83e4b055afc5ee1705
However, it is permissible to alias the unique key to a human readable id such as
/people/bisselaltor@gmail.com
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.