API Design

Pagination Response JSON Example

A JSON example of a paginated API response — includes cursor-based and offset-based pagination fields, total count, and navigation links. Copy-ready for REST and GraphQL APIs.

{
  "data": [
    {
      "id": "ord_7TnVqRx2kL",
      "status": "delivered",
      "grandTotal": 3151.2,
      "createdAt": "2025-05-01T10:30:00Z"
    },
    {
      "id": "ord_2SmPwBv9nJ",
      "status": "shipped",
      "grandTotal": 805.82,
      "createdAt": "2025-05-10T09:00:00Z"
    },
    {
      "id": "ord_8KqZxLrN5m",
      "status": "processing",
      "grandTotal": 4280,
      "createdAt": "2025-05-15T14:00:00Z"
    }
  ],
  "pagination": {
    "total": 127,
    "page": 2,
    "perPage": 3,
    "totalPages": 43,
    "hasNextPage": true,
    "hasPrevPage": true,
    "nextCursor": "eyJpZCI6Im9yZF84S3FaeExyTjVtIn0=",
    "prevCursor": "eyJpZCI6Im9yZF9mMW5Hd1BxMnQifQ=="
  },
  "links": {
    "self": "https://api.example.com/v1/orders?page=2&perPage=3",
    "next": "https://api.example.com/v1/orders?page=3&perPage=3",
    "prev": "https://api.example.com/v1/orders?page=1&perPage=3",
    "first": "https://api.example.com/v1/orders?page=1&perPage=3",
    "last": "https://api.example.com/v1/orders?page=43&perPage=3"
  },
  "meta": {
    "query": {
      "status": "all",
      "sortBy": "createdAt",
      "sortOrder": "desc"
    },
    "responseTime": 42
  },
  "requestId": "req_Lp7nQxKmTv",
  "timestamp": "2025-05-20T08:00:00Z"
}

Field Reference

dataarray<object>requiredThe current page of records
pagination.totalintegerrequiredTotal number of records matching the query across all pages
pagination.pageintegerrequiredCurrent page number (1-based)
pagination.perPageintegerrequiredNumber of records per page
pagination.hasNextPagebooleanrequiredWhether a subsequent page of results exists
pagination.nextCursorstring | nulloptionalOpaque Base64 cursor for cursor-based pagination
linksobjectoptionalHATEOAS navigation URLs for first, prev, self, next, and last pages
meta.responseTimeintegeroptionalServer-side query duration in milliseconds

Variants

MinimalOffset pagination with only page, perPage, and total — no cursors or links.
{
  "data": [
    {
      "id": "usr_9k2mXpQr4t",
      "fullName": "Ravi Mehta",
      "email": "ravi.mehta@example.com"
    },
    {
      "id": "usr_3hFwLmNz8q",
      "fullName": "Priya Sharma",
      "email": "priya.sharma@example.com"
    }
  ],
  "pagination": {
    "total": 84,
    "page": 1,
    "perPage": 20,
    "totalPages": 5,
    "hasNextPage": true,
    "hasPrevPage": false
  },
  "timestamp": "2025-05-20T08:00:00Z"
}
ExtendedCursor-based infinite scroll response with seek metadata and sort info.
Extended
{
  "data": [
    {
      "id": "ord_7TnVqRx2kL",
      "status": "delivered",
      "grandTotal": 3151.2,
      "createdAt": "2025-05-01T10:30:00Z"
    },
    {
      "id": "ord_2SmPwBv9nJ",
      "status": "shipped",
      "grandTotal": 805.82,
      "createdAt": "2025-05-10T09:00:00Z"
    },
    {
      "id": "ord_8KqZxLrN5m",
      "status": "processing",
      "grandTotal": 4280,
      "createdAt": "2025-05-15T14:00:00Z"
    }
  ],
  "pagination": {
    "total": 127,
    "page": 2,
    "perPage": 3,
    "totalPages": 43,
    "hasNextPage": true,
    "hasPrevPage": true,
    "nextCursor": "eyJpZCI6Im9yZF84S3FaeExyTjVtIn0=",
    "prevCursor": "eyJpZCI6Im9yZF9mMW5Hd1BxMnQifQ=="
  },
  "links": {
    "self": "https://api.example.com/v1/orders?page=2&perPage=3",
    "next": "https://api.example.com/v1/orders?page=3&perPage=3",
    "prev": "https://api.example.com/v1/orders?page=1&perPage=3",
    "first": "https://api.example.com/v1/orders?page=1&perPage=3",
    "last": "https://api.example.com/v1/orders?page=43&perPage=3"
  },
  "meta": {
    "query": {
      "status": "all",
      "sortBy": "createdAt",
      "sortOrder": "desc"
    },
    "responseTime": 42
  },
  "requestId": "req_Lp7nQxKmTv",
  "timestamp": "2025-05-20T08:00:00Z"
}

Common Use Cases

  • Implementing infinite scroll or load-more UI patterns in mobile and web apps
  • Designing consistent pagination across all list endpoints in a REST API
  • Building admin dashboards that display large datasets in paginated tables
paginationcursoroffsetREST APIlist

Validate or format this JSON

Paste the example above into JSONKit's tools to validate, minify, or explore the structure interactively.

Frequently Asked Questions

Offset pagination uses page and perPage numbers — simple but can show duplicate or missing records if data changes between requests. Cursor pagination uses an opaque pointer to a specific record, making it stable for real-time or frequently updated datasets.

Returning a total is expensive on large tables because it requires a COUNT query. For performance, consider omitting it and relying on hasNextPage instead, especially for cursor-based APIs.

20–50 items per page is common. Set a maximum (e.g. 100) to prevent clients from requesting huge payloads. Document the default and maximum in your API spec.

Related JSON Examples