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

datarequiredarray<object>The current page of records
pagination.totalrequiredintegerTotal number of records matching the query across all pages
pagination.pagerequiredintegerCurrent page number (1-based)
pagination.perPagerequiredintegerNumber of records per page
pagination.hasNextPagerequiredbooleanWhether a subsequent page of results exists
pagination.nextCursoroptionalstring | nullOpaque Base64 cursor for cursor-based pagination
linksoptionalobjectHATEOAS navigation URLs for first, prev, self, next, and last pages
meta.responseTimeoptionalintegerServer-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.
{
  "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

One click loads this exact example into the tool — no copy-paste needed. Format it, validate it, explore the tree, or generate TypeScript types instantly.

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