Collection
A collection resource is a server-managed list of document resources.
Rule: Collection name [col-name]
A plural noun SHOULD be used for collection names, for example 'employers' or 'children'.
https://api.example.org/demo/v1/employers - a collection of employers
https://api.example.org/demo/v1/employers/{employerId}/subsidiaries - a collection of subsidiaries as a child resource of an employer.
Search
Rule: API operation to search a collection [col-get]
An operation to search a collection resource SHOULD be provided as a GET method on the collection resource URI.
When searching requires input parameters with a complex structure (e.g. extensive filter or sorting parameters), a POST operation on a /search controller MAY be used instead of GET. This allows to represent the input parameters in a structured manner in a JSON request body without the limitations of query parameters.
Any pagination input parameters SHOULD still be included as query parameters, allowing to re-send the same payload to retrieve the next page of results.
The recently introduced HTTP method QUERY, providing an alternative to a /search controller, SHOULD NOT be used yet ([meth-http]).
Rule: Representation of a collection [col-repres]
The representation of a collection MUST contain a list of links to child resources:
-
A collection result MUST contain an
itemsproperty with an array of objects, each one representing an item in the collection. -
In these objects, a
hrefproperty MUST be present with a link to the resource. -
The unique business identifier SHOULD be present for each item.
-
Each item object MAY be extended with some key business properties, needed for display in a master view.
-
In case the collection is empty, the
itemsproperty MUST have an empty array as value. -
The
titleproperty MAY be used to provide a human-readable description for an item, usable as display text for the link. -
The number of items in the collection result set MAY be included in the response using the
totalproperty. If the response is paginated, its value MUST correspond to the number of items regardless of pagination, rather than only the number of items in the current page.
| A collection resource, like other resources, SHOULD always return a JSON object as top-level data structure to support extensibility ([evo-object]). Do not return a JSON array, because the moment you like to add paging, links, etc. your API will break. |
GET https://api.example.org/demo/v1/employers?title=P* HTTP/1.1
Request |
||
/employers/{employerId} |
List employers |
|
parameters |
sorting, filtering or pagination parameters |
see Sorting, Filtering and Pagination |
Response |
||
body |
|
|
Most used response codes |
||
OK |
Default response code, also when the collection is empty. |
|
Bad Request |
Generic error on client side. For example, the syntax of the request is invalid. |
|
Not found |
The URI provided cannot be mapped to a resource. |
|
| 204 No content should not be used when consulting a collection. |
OpenAPI schemas for the response payload:
EmployersCollection:
type: object
properties:
items:
type: array
items:
$ref: "#/components/schemas/EmployerLink"
total:
type: integer
required:
- items
- total
EmployerLink:
allOf:
- $ref: common/v1/common-v1.yaml#/components/schemas/HttpLink
- type: object
properties:
employerId:
$ref: "./employer/identifier/v1/employer-identifier-v1.yaml#/components/schemas/EmployerId"
enterpriseNumber:
$ref: "./organization/identifier/v1/organization-identifier-v1.yaml#/components/schemas/EnterpriseNumber"
If input with a complex structure is needed, a /search controller with POST may be used.
POST https://api.example.org/demo/v1/employers/search
{
"title": [
{
"excludeIfMatching": false,
"expression": "P*"
},
{
"excludeIfMatching": true,
"expression": "B*"
}
]
}
The response is the same as for the GET alternative.
Rule: Getting full representations of collection items [col-embed]
When the collection items contain few data, you may want to retrieve them in full when getting the collection. In this case, the full representations MUST be included in an 'embedded' property as described in Embedding resources.
GET https://api.example.org/demo/v1/appendices/employerclasses?embed=items HTTP/1.1
{
"items": [
{
"value": "0",
"href": "https://api.example.org/demo/v1/appendices/employerclasses/0"
}, {
"value": "2",
"href": "https://api.example.org/demo/v1/appendices/employerclasses/2"
}
],
"total":2,
"embedded": {
"https://api.example.org/demo/v1/appendices/employerclasses/2": {
"value": "2",
"description": {
"nl": "Bijzondere categorie voor werkgevers die voor hun arbeiders een speciale bijdrage verschuldigd zijn.",
"fr": "Catégorie particulière pour les employeurs redevables pour les ouvriers d'une cotisation spéciale."
}
},
"https://api.example.org/demo/v1/appendices/employerclasses/0": {
"value": "0",
"description": {
"nl": "Algemene categorie voor werkgevers van commerciële of niet-commerciële aard.",
"fr": "Catégorie générale pour les employeurs, de type commercial ou non-commercial."
}
}
}
}
AppendixCodesCollection:
description: A collection of appendix codes
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/AppendixCodeLink'
total:
type: integer
embedded:
type: object
additionalProperties:
$ref: 'appendixCode.yaml#/components/schemas/AppendixCode'
required:
- items
- total
AppendixCodeLink:
allOf:
- $ref: 'common/v1/common-v1.yaml#/components/schemas/HttpLink'
- type: object
properties:
value:
$ref: 'appendixCode.yaml#/components/schemas/AppendixCodeValue'
Sorting
Rule: Sorting a collection [col-sort]
A sort multi-value query parameter MAY be provided to allow a client to sort the items of a collection resource on one or more specified properties.
Descending sorting order can be indicated by prefixing the property name with -.
The API SHOULD document which properties can be used for sorting, and whether descending order is allowed.
In case a /search controller is used, the sorting parameters should be represented in a structured manner in the request body, instead of using query parameters. Separate parameters for sorting properties and sorting order can be used then.
sort |
Multi-value query param with list of properties to sort on.
Direction is ascending by default. To indicate descending, prefix property with |
|
Filtering
Rule: Filtering items in a collection [col-filter]
A collection may support query parameters to filter its items:
-
a query parameter with the name of a document property, filters items on the specified value
-
the query parameter
qis reserved for a full text search on all the document’s content -
other filter parameters may be supported, e.g. to look up items within a search period
Unless the API documentation explicitly states otherwise, returned collection items:
-
should satisfy ALL filter query parameters (AND-logic)
-
have to match ANY of the values of a multi-valued filter query parameter (OR-logic).
For example, the query
GET /cars?doors=5&color=black&color=blue should be interpreted by default as: "search for all cars that have 5 doors AND are of color blue OR black".
GET https://api.example.org/demo/v1/enterprises?title=P* HTTP/1.1
/organizations |
get all the organization documents in the collection |
|
Parameters |
||
name |
query-param |
Only match organizations that have a specific name. |
Response |
||
body |
|
|
Most used response codes |
||
OK |
Default response code, also when filtered collection is empty. |
|
Bad Request |
Generic error on client side. For example, the syntax of the request is invalid. |
|
Not found |
The URI provided cannot be mapped to a resource. |
|
| 204 No content should not be used with GET. |
Pagination
Rule: Paging over a large collection [col-paging]
Collection with too many items MUST support pagination. There are two pagination techniques:
-
offset-based pagination: numeric offset identifies a page
-
cursor-based (aka key-based or luke index): a unique key element identifies a page
Cursor-based pagination has some advantages, especially for high volumes. Take into account the considerations listed in the Zalando API guidelines before choosing a pagination technique.
next |
MANDATORY (except for the last page) | hyperlink to the next page |
|---|---|---|
|
REQUIRED (except for the last page) |
hyperlink to the next page |
|
OPTIONAL |
hyperlink to the previous page |
|
RECOMMENDED |
Maximum number of items per page. For the last page, its value should be independent of the number of actually returned items. |
|
REQUIRED (offset-based); N/A (cursor-based) |
index of the current page of items, should be 1-based (the default and first page is 1) |
|
OPTIONAL |
hyperlink to the first page |
|
OPTIONAL |
hyperlink to the last page |
|
OPTIONAL |
Total number of items across all pages. If filter parameters are used, this is the total of the result set after filtering, not of the entire collection. |
The names of the properties with hyperlink values and the items property are derived from the IANA registered link relations.
|
OPTIONAL |
maximum number of items per page desired by client; must have a default value if absent. |
|
REQUIRED with default value 1 (offset-based); N/A (cursor-based) |
the index of page to be retrieved |
A reusable PageQueryParameter OpenAPI component is defined in common-v1.yaml. Examples of other OpenAPI components for pagination can be found here, but should be modified according to which pagination parameters, size limits and default values are supported by your API.
GET https://api.example.org/demo/v1/organizations?page=2&pageSize=2 HTTP/1.1
{
"items": [
{
"href": "https://api.example.org/demo/v1/organizations/0202239951",
"title": "Proximus",
"enterpriseNumber": "0202239951"
},
{
"href": "https://api.example.org/demo/v1/organizations/0212165526",
"title": "CPAS de Silly",
"enterpriseNumber": "0212165526"
}
],
"pageSize": 2,
"page": 2,
"total": 7,
"first": "https://api.example.org/demo/v1/organizations?pageSize=2",
"last": "https://api.example.org/demo/v1/organizations?page=4&pageSize=2",
"prev": "https://api.example.org/demo/v1/organizations?page=1&pageSize=2",
"next": "https://api.example.org/demo/v1/organizations?page=3&pageSize=2"
}
GET https://api.example.org/demo/v1/organizations?after=0244640631 HTTP/1.1
{
"items": [
{
"href": "https://api.example.org/demo/v1/organizations/0202239951",
"title": "Proximus"
},
{
"href": "https://api.example.org/demo/v1/organizations/0212165526",
"title": "CPAS de Silly"
}
],
"pageSize": 2,
"total": 7,
"first": "https://api.example.org/demo/v1/organizations?pageSize=2",
"next": "https://api.example.org/demo/v1/organizations?after=0212165526&pageSize=2"
}
Create a new resource
The collection resource can be used to create new document resources from the POST request body.
Absent optional values are set to their default value if one is specified in the OpenAPI description.
/employers |
create a new employer in the collection |
|
Request |
||
body |
The data of the resource to create. |
|
Response headers |
||
Location |
http-header |
The URI of the newly created resource e.g. /employers/93017373 |
Response |
||
body |
The API should specify for each creation operation, if it returns:
|
|
Most used response codes |
||
Created |
Default response code if the resource is created. |
|
Conflict |
The resource could not be created because the request is in conflict with data on the server. E.g. the resource already exists (duplicate key violation). |
|
See Other |
The resource already exists.
May be returned instead of |
|
| 200 OK should not be used with POST for creating resources. |
POST /employers HTTP/1.1
HTTP/1.1 201 Created
Location: /employers/93017373
Content-Length: 0
Date: Wed, 06 Jan 2016 15:37:16 GMT
Remove
A selection of items can be removed from a collection using the DELETE method. In fact, the collection itself cannot be removed, but it can be emptied if all its items are removed. By using query parameters, the items to be removed can be filtered. In order to remove a single specific item from a collection, use DELETE on the document resource.
/employers |
Delete all the employers documents in the collection. |
|
Parameters |
||
name |
query-param |
Remove only employers that have a specific name. |
Response |
||
body |
Empty or a message indicating success. |
|
Most used response codes |
||
OK |
The items are successfully removed from the collection and returned. |
|
No content |
The items are successfully removed from the collection but no additional content is included in the response body. |
|
Bad Request |
Generic error on client side. For example, the syntax of the request is invalid. |
|
Not found |
The collection resource does not exist and thus cannot be deleted. |
|