I'm designing a RESTful API, returns result with pagination and total number. Here is my approach
Endpoint
[GET] /items
Parameters
Parameter | Description |
---|---|
before_cursor | Return results before cursor |
after_cursor | Return results after cursor |
limit | Limit of result |
Response
{
"items": [
...
],
"pagination": {
"prev_cursor": string, // cursor before the range, for backward navigation
"next_cursor": string, // cursor after the range, for forward navigation
"total": number, // total number of items
"total_before": number, // item count before prev_cursor helps client positioning
"total_after": number // item count before next_cursor helps client positioning
}
}
Example
Raw data
Item_0, Item_1, ... Item_99
Get first page
[GET] /items?limit=10
{
"items": [item_0, ..., item_9],
"pagination": {
"next_cursor": "item_10",
"total": 100,
"total_before": 0,
"total_after": 90
}
}
Navigate to next page
[GET] /items?limit=10&after_cursor=item_10
{
"items": [item_10, ..., item_19],
"pagination": {
"before_cursor": "item_9",
"next_cursor": "item_20",
"total": 100,
"total_before": 10,
"total_after": 80
}
}
Navigate back to previous page
[GET] /items?limit=10&before_cursor=item_9
{
"items": [item_0, ..., item_9],
"pagination": {
"next_cursor": "item_10",
"total": 100,
"total_before": 0,
"total_after": 90
}
}
Is it a good approach? Or is there a neater way to design API for this requirement?
CodePudding user response:
There are multiple ways to design this endpoint with a rest approach. I found these 2 the best when you need to deal with collections.
Approach 1
GET /items?page=2 & page_size=10
This should return only 10 elements from your resource items and skip the first page (it is up to you to decide if you start your collection with a 0 or with 1)
A response should look like this
Response 1:
[
item1,
item2,
...
item10
]
Response Header: RecordCount
or X-Total-Count = 530
The total count in this case is included in the headers. Now if the user wants to paginate the next page or the previous they can do the following request:
- next:
GET /items?page=3 & page_size=10
- previous:
GET /items?page=1 & page_size=10
Including this request as part of the payload and trying to comply with Rest for HATEOAS is what I think can be the second approach
Response 2:
{
TotalCount=530,
Result:
[
item1,
item2,
...
item10
],
Next: '/items?page=3 & page_size=10'
Previous: 'GET /items?page=1 & page_size=10'
}
In this case, the total count is included in the response and the items on the result and you build the next and previous URLs