Part 5 — Pagination, ordination and filters in RESTful APIs
Hey hacker friends! It’s time for a new APIs article.
Now we will talk about pagination, ordination and filters, something crucial when designing an API.
We’ll be using our same gastronomy API example, shown on our previous articles. If you haven’t read those, check them out:
-  An API RESTful’s anatomy
-  What you need to know about methods and status codes from HTTP Protocol
-  Security in RESTful APIs
-  Versioning RESTful APIs
Let’s suppose our API already has a great amount of data, and when you GET wines, it returns with more than 10.000 registers, and this is making clients wait too long before they get their response.
That’s exactly what pagination, ordination, and filters solve.
In sum, it’s the implementation that makes your API work with data in a more efficient way, using only what’s necessary.
To make that vision clearer, I’ll show you some examples of why you should implement these concepts.
As you are breaking your result into smaller pieces on your server, the response will get shorter too. Because of that, the client can get its result in a faster and more pleasant way, making the whole experience better for the developer consuming that API.
Infrastructure smart usage
As data consumption works by request, that helps horizontal and vertical scalability of an API. This model makes use of infrastructure resources in a smarter way.
Well, enough with the theory and let’s check what are the most used ones:
Cursor based pagination works with a unique and sequential key, that indicates the register base where data will return from.
In other words, let’s suppose you want wine registers from ID 156 to ID 200. To do it, your request would be:
Note that parameters since_id and max_id were added, and in this case, they are the browsing cursors that delimit results that will be returned.
Usually, APIs with cursor-based pagination return the result of the requests with parameters to browse through the previous and the next page.
Note: the parameters cursors name can change accordingly to the API implementation.
Page and PageSize
Pagination based on page and pagesize, as the name says, is used through parameters related to the number of the page and its size (in register numbers).
Let’s suppose you want to see data from 10 wines on the third page. Your request would be:
Note: The parameters name can change accordingly to the API’s implementation.
Offset and Limit
Pagination based on offset and limit is used from a register displacement.
In other words, in offset, you specify which register you want to be the starting point, and in limit, the number of registers that will be returned.
Let’s suppose you want to see 30 wines, starting from the tenth register. That’s how your request will look like:
Filters and Ordination
There’s not much to say about them, you can use query string parameters to make your API more intelligent, besides giving your client more capacity to work with data on demand.
Practical filter example:
In the example above, I’m requesting all of Brazil’s wine, in the state of Rio Grande do Sul, with prices between 100 and 200, and available to buy.
We also have the possibility to use alias to filters that are very used, for instance:
In this case, I use sub-resource “available”, that contains a pre-structured filter, and makes the developer consume easier.
Practical ordination example:
In the above example, note that I included a sort parameter, that contains the key field for ordination, followed by “:”, to specify if I want data in ascending or descending orders, besides the comma that will separate fields.
This is not the only pattern for this technique, but, in my opinion, it’s pretty clean.
Offset and limit with “range” filters
My recommendation is using offset and limit technique for pagination, because, besides being the most used one, it provides the best experience for who is consuming the API.
Page and page size browsing requires recalculation of pages when there’s some change to page size. This makes things more complex and it’s bad for the developer experience.
If you’re going to use page and page size, please, on your documentation, specify which page is the starting point for looking for data. I have seen many cases that pages 0 and 1 return the same registers.
Set default values
Set default values in pagination parameters, for instance, the default limit of 500 objects and a maximum limit of 1000 objects. This way, if your client doesn’t send the parameter, your API’s performance and scalability are protected.
Don’t go too far on Query String parameters
My recommendation here is not exaggerating on your query string parameters. This means — analyze and find out what really makes sense. On the contrary, you’ll be “polluting” your URL, making everything more complex to the developer who’ll use your API.
Another important topic is not setting parameters as mandatory in cases that they are not, for instance:
Imagine that, in this request, the status parameter is mandatory. That wouldn’t make any sense, because if I wanted all of the wines, regardless of their status, I would need to concatenate many requests.
In other words, make parameters mandatory may result in a poor consuming experience.
Lastly, always have new use cases in mind when creating new resources. This will make parameters and metadata definitions way easier.
That’s it, folks. Another article from our series about APIs.
Stay tuned on our social media, I’ll be back with more soon!