From 34a45b58f0915ebe27b1b5f37dac771b2032038c Mon Sep 17 00:00:00 2001 From: Rafal Artych <121048129+rartych@users.noreply.github.com> Date: Thu, 2 Apr 2026 13:14:01 +0200 Subject: [PATCH] Changed 4.1 Pagination and Headers --- documentation/CAMARA-API-Design-Guide.md | 147 +++++++++++++++++++---- 1 file changed, 122 insertions(+), 25 deletions(-) diff --git a/documentation/CAMARA-API-Design-Guide.md b/documentation/CAMARA-API-Design-Guide.md index 83f9ff44..2fcd1924 100644 --- a/documentation/CAMARA-API-Design-Guide.md +++ b/documentation/CAMARA-API-Design-Guide.md @@ -407,11 +407,11 @@ The `ErrorInfo` object is provided within the HTTP body of the HTTP response mes In the following, we elaborate on the existing errors. In particular, we identify the different error codes and cluster them into separate tables, depending on their nature: - i) syntax exceptions - The API Consumer has made a request with invalid syntax, and re-sending the same request will always result in the same exception. The API Provider should indicate to the client what modification is required for the request to be resubmitted. - + Examples: `400 - INVALID_ARGUMENT`, `405 - METHOD_NOT_ALLOWED`, etc. - ii) service exceptions - The API Consumer has made a request but the API Provider is currently unable to fulfil it. This can be due to a technical reason (e.g. server or backend failure) or a policy reason (e.g. business quota exceeded). The API Provider should indicate to the client if/when the request can be resubmitted and whether any modification is required. - + Examples: `403 - PERMISSION_DENIED`, `422 - SERVICE_NOT_APPLICABLE`, `429 - QUOTA_EXCEEDED`, `5xx` range, etc. Syntax Exceptions @@ -575,27 +575,99 @@ To alleviate the above-mentioned issues and concerns, Pagination, Sorting and Fi ### 4.1. Pagination -Services can answer with a resource or article collections. Sometimes these collections MAY be a partial set due to performance or security reasons. Elements MUST be identified and arranged consistently on all pages. Paging can be enabled by default on the server side to mitigate denial of service or similar attack. -Services MUST accept and use these query parameters when paging is supported: -- `perPage`: number of resources requested to be provided in the response -- `page`: requested page number to indicate the start of the resources to be provided in the response (considering perPage page size) -- `seek`: index of last result read, to create the next/previous number of results. This query parameter is used for pagination in systems with more than 1000 records. `seek` parameter offers finer control than `page` and could be used one or another as an alternative. If both are used in combination (NOT RECOMMENDED) `seek` would mark the index starting from the page number specified by `page` and `perPage` [index = (page * perPage) + seek]. +Services MAY return collections as a partial set due to performance or security constraints. All elements MUST be identified and arranged consistently across all pages — the same query with the same parameters must return the same ordering. Pagination MAY be enabled by default on the server side to mitigate denial-of-service and similar threats. + +#### 4.1.1. Query Parameters +Services MUST accept the following query parameters on all list endpoints where pagination is supported: +- `page` (integer, default: 1, minimum: 1) The requested page number. Pages are 1-indexed. Values below 1 MUST be rejected with `400 INVALID_ARGUMENT` error. +- `perPage` (integer, default: 20, minimum: 1, maximum: 100) Number of resources to return per page. Values outside the allowed range MUST be rejected with `400 INVALID_ARGUMENT` error. Servers MAY enforce a lower maximum for specific endpoints. + +#### 4.1.2. Request Headers +No pagination-specific request headers are required. Pagination is controlled entirely via query parameters. + +#### 4.1.3. Response Body + +When paginated response is returned the `pagination` object SHOULD always be present; `totalCount` and `totalPages` MAY be omitted only where a full count query is prohibitively expensive — this MUST be documented per endpoint. + +```yaml +ResourceList: + type: object + required: + - items + properties: + items: + type: array + items: + $ref: "#/components/schemas/Resource" + pagination: + $ref: "#/components/schemas/Pagination" + +Pagination: + type: object + properties: + page: + type: integer + minimum: 1 + perPage: + type: integer + minimum: 1 + maximum: 100 + totalCount: + type: integer + minimum: 0 + totalPages: + type: integer + minimum: 0 +``` + +#### 4.1.4. Response Headers + +Services MAY return the following headers on all paginated `200` responses: + +**`X-Total-Count`** +Total number of items in the collection matching the current query, after filters are applied. Mirrors `pagination.totalCount` in the body. + +**`X-Total-Pages`** +Total number of pages. Mirrors `pagination.totalPages` in the body. + +**`Link`** +Navigation links per [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288). MUST include only the rels applicable to the current position (`first`, `prev`, `next`, `last`). All original filter and sort query parameters MUST be preserved in Link URLs. +``` +Link: ; rel="first", + ; rel="prev", + ; rel="next", + ; rel="last" +``` + -Services MUST accept and use these headers when paging is supported: -- `Content-Last-Key`: it allows specifying the key of the last resort provided in the response -- `X-Total-Count`: it allows indicating the total number of elements in the collection +#### 4.1.5 HTTP Status Codes -If the server cannot meet any of the required parameters, it SHOULD return an error message. +| Code | When to use | +|---|---| +| `200 OK` | All paginated responses, including empty result sets and out-of-range pages. The response body is always a complete, valid answer to the request. | +| `400 INVALID_ARGUMENT` | Malformed pagination input: `page` or `perPage` violating type or range constraints (`page=-1`, `perPage=abc`, `perPage=999`). | -The HTTP codes that the server will use as a response are: -- `200`: the response includes the complete list of resources -- `206`: the response does not include the complete list of resources -- `400`: request outside the range of the resource list -Petitions examples: -- `page=0 perPage=20`, which returns the first 20 resources -- `page=10 perPage=20`, which returns 20 resources from the 10th page (in terms of absolute index, 10 pages and 20 elements per page, means it will start on the 200th position as 10x20=200) +Both empty result sets and out-of-range page requests MUST return `200` with an empty `items` array. The `pagination` object MUST still be present and accurate so the API Client can self-correct. + +```json +// Request: GET /resources?page=50&perPage=20 (totalPages = 5) +// HTTP 200 OK +{ + "items": [], + "pagination": { + "page": 50, + "perPage": 20, + "totalCount": 87, + "totalPages": 5, + + } +} +``` + +NOTE: The client receives all information needed to detect the out-of-range condition (`page > totalPages`) and redirect to the last valid page + ### 4.2. Sorting @@ -623,7 +695,7 @@ Filtering consists of restricting the number of resources queried by specifying Next, it is specified how it should be used according to the filtering based on the type of data being searched for: a number or a date and the type of operation. -Note: Services MAY not support all attributes for filtering. In case a query includes an attribute for which filtering is not supported, it MAY be ignored by the service. +NOTE: Services MAY not support all attributes for filtering. In case a query includes an attribute for which filtering is not supported, it MAY be ignored by the service. #### 4.3.1. Filtering Security Considerations @@ -1046,6 +1118,33 @@ When an API client provides an `x-correlator` value not matching the pattern, er NOTE: HTTP headers are case-insensitive. The use of the naming `x-correlator` is a guideline to align the format across CAMARA APIs. + +##### Pagination Headers +As documented in [4.1.4. Response Headers](#414-response-headers) `X-Total-Count`, `X-Total-Pages` and `Link` MAY be added to paginated response + +```yaml +headers: + X-Total-Count: + required: false + schema: + $ref: "#/components/schemas/TotalCount" + X-Total-Pages: + required: false + schema: + $ref: "#/components/schemas/TotalPages" + Link: + required: false + description: | + Navigation links following RFC 8288. + Example: + Link: ; rel="first", + ; rel="prev", + ; rel="next", + ; rel="last" + schema: + type: string +``` + ##### Content-Type Header - clarification The character set supported MUST only be UTF-8. The [JSON Data Interchange Format (RFC 8259)](https://datatracker.ietf.org/doc/html/rfc8259#section-8.1) states the following @@ -1290,8 +1389,8 @@ This allows for both test and commercial usage of initial API versions as they a ### 7.3. API Versions Throughout the Release Process A given API will go through various intermediate and public versions during its life cycle: -* intermediate versions are created during API version development, indicated by alpha and release-candidate version extensions -* various public versions may be created due to updates to a published API +* intermediate versions are created during API version development, indicated by alpha and release-candidate version extensions +* various public versions may be created due to updates to a published API Overall, during its life cycle, an API can have any of the following versions: @@ -1313,9 +1412,9 @@ The following table gives the values of the API version (Info object) and the AP The version in the URL is a shorthand of the API version. However, both v0.y.z-rc.1 and v0.y.z+1-rc.1 would be shortened to v0.yrc1 and, for x>0, both vx.y1.z1.0-rc.2 and vx.y2.z2-rc.2 would be shortened to vxrc2. -To avoid such clashes of the version in the URL, both alpha and release-candidate (rc) version extension numbers need to be numbered consecutively across the whole life cycle of an API, including its PATCH versions. +To avoid such clashes of the version in the URL, both alpha and release-candidate (rc) version extension numbers need to be numbered consecutively across the whole life cycle of an API, including its PATCH versions. -For example, in the life cycle of a (MAJOR) version 1 of an API, alpha and rc extension numbers will evolve as follows: +For example, in the life cycle of a (MAJOR) version 1 of an API, alpha and rc extension numbers will evolve as follows: | API Version | v1.0.0-alpha.1 | v1.0.0-alpha.2 | v1.0.0-rc.1 | v1.0.0-rc.2 | v1.0.0 | v1.1.0-alpha.3 | v1.1.0-rc.3 | v1.1.0 | :---: | :---: | :---: | :--: | :--: | :--: | :--: | :--: | :--: @@ -1447,5 +1546,3 @@ This approach simplifies API usage for API consumers using a three-legged access - If the subject can be identified from the access token and the optional [`device` object | `phoneNumber` field](*) is also included in the request, then the server will return an error with the `422 UNNECESSARY_IDENTIFIER` error code. This will be the case even if the same [ device | phone number ](*) is identified by these two methods, as the server is unable to make this comparison. ``` - -