Pagination Metadata
title: "Pagination Metadata — Structuring Paginated API Responses" description: "Pagination metadata in API responses includes total count, page number, page size, and navigation URLs, enabling clients to display and navigate paginated data." date: 2026-06-28 lastmod: 2026-06-28 weight: 21 tags: [apis, pagination] }
Pagination metadata provides clients with the information needed to display and navigate paginated results, including total count, current page, page size, and navigation URLs.
What You'll Learn
- Standard pagination metadata fields
- Response structure patterns
- Navigation link generation
Why It Matters
Consistent pagination metadata across all endpoints lets client developers write one pagination handler that works for the entire API.
Standard Fields
| Field | Type | Description |
|---|---|---|
page |
integer | Current page number |
per_page |
integer | Items per page |
total |
integer | Total matching results |
total_pages |
integer | Total number of pages |
has_next |
boolean | Whether there's a next page |
has_prev |
boolean | Whether there's a previous page |
next_cursor |
string | Cursor for next page (cursor mode) |
links |
object | Navigation URLs |
Code Examples
// Standard pagination metadata
{
"data": [...],
"pagination": {
"page": 2,
"per_page": 20,
"total": 156,
"total_pages": 8,
"has_next": true,
"has_prev": true,
"links": {
"first": "/users?page=1&per_page=20",
"prev": "/users?page=1&per_page=20",
"next": "/users?page=3&per_page=20",
"last": "/users?page=8&per_page=20"
}
}
}
// Cursor-based metadata
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTAwfQ==",
"prev_cursor": "eyJpZCI6MX0=",
"has_more": true
}
}
// Minimal metadata
{
"data": [...],
"total": 156,
"page": 2,
"per_page": 20
}
# Pagination metadata helper
def paginated_response(data, page, per_page, total, base_url, params=None):
total_pages = (total + per_page - 1) // per_page
params = params or {}
def page_url(p):
qs = {**request.args, "page": p}
return f"{base_url}?{urlencode(qs)}"
return jsonify({
"data": data,
"pagination": {
"page": page,
"per_page": per_page,
"total": total,
"total_pages": total_pages,
"has_next": page < total_pages,
"has_prev": page > 1,
"links": {
"first": page_url(1),
"prev": page_url(page - 1) if page > 1 else None,
"next": page_url(page + 1) if page < total_pages else None,
"last": page_url(total_pages)
}
}
})
Common Mistakes
1. Inconsistent Field Names
Use page, not current_page on some endpoints and page_number on others.
2. Missing Navigation Links
Always include first, prev, next, last or cursor links.
3. Inconsistent Data Location
Always put pagination metadata in the same location (root or nested).
4. Mixing Offset and Cursor Fields
If using cursor offset, omit page/page-based metadata fields.
5. No has_next/has_prev
Boolean flags simplify client logic for "load more" buttons.
Practice Questions
- What fields should pagination metadata include?
- Where should pagination metadata be in the response?
- Why is
has_nextuseful for clients? - How do you handle null links (no prev or next)?
- What field names are most commonly used?
Answers:
- page, per_page, total, has_next, has_prev, links.
- Consistently in the same location, typically at the response root alongside
data. - It tells clients whether to show a "Load More" button.
- Return
nullfor absent links instead of omitting them. page,per_page,total,total_pages.
Challenge: Design a pagination metadata schema that supports both offset and cursor modes. The response should include either set of fields based on the active mode.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro