Skip to content

Pagination Metadata

DodaTech 3 min read

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.

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

  1. What fields should pagination metadata include?
  2. Where should pagination metadata be in the response?
  3. Why is has_next useful for clients?
  4. How do you handle null links (no prev or next)?
  5. What field names are most commonly used?

Answers:

  1. page, per_page, total, has_next, has_prev, links.
  2. Consistently in the same location, typically at the response root alongside data.
  3. It tells clients whether to show a "Load More" button.
  4. Return null for absent links instead of omitting them.
  5. 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

Should pagination metadata be in headers or body?

: Body is more accessible; headers are more standard. Many use both.

What is the most common pagination field name?

: page, limit, and total are the most widely used.

How do I handle cursor pagination metadata differently?

: Use next_cursor and has_more instead of page-based fields.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro