Skip to main content

Mock Pagination API

MOCK DATA

Deterministic offset and opaque-cursor pagination fixtures with exact totals, stable sorting and no duplicated or skipped records.

Generated test data for fixtures and development

Base URL
/api/pagination
Capabilities
2 routes
Last updated
July 29, 2026

GET /api/pagination/offset

Live requestRuns against the public API
No key required
GET/api/pagination/offset?total=137&page=3&pageSize=20

Request parameters

Total size of the deterministic fixture dataset (0–10,000).

Stable ordering key. name and rank are independent deterministic permutations of id.

Ascending or descending order for the selected sort key.

Stable dataset namespace. Changing it changes the id/name/rank relationships and invalidates old cursors.

One-based page number. Pages beyond the end return an honest empty items array.

Maximum records in this page (1–100).

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/pagination/offset?total=137&page=3&pageSize=20"
const res = await fetch("https://randomapi.dev/api/pagination/offset?total=137&page=3&pageSize=20");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/pagination/offset?total=137&page=3&pageSize=20").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/pagination/offset?total=137&page=3&pageSize=20"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 6
total int

Total size of the deterministic fixture dataset (0–10,000).

default: 137
allowed: 0 – 10000
example: total=137
sort enum

Stable ordering key. name and rank are independent deterministic permutations of id.

default: id
allowed: id | name | rank
example: sort=rank
order enum

Ascending or descending order for the selected sort key.

default: asc
allowed: asc | desc
example: order=desc
datasetKey string

Stable dataset namespace. Changing it changes the id/name/rank relationships and invalidates old cursors.

default: demo
allowed: 1 – 64
example: datasetKey=catalog-demo
page int

One-based page number. Pages beyond the end return an honest empty items array.

default: 1
allowed: 1 – 10000
example: page=3
pageSize int

Maximum records in this page (1–100).

default: 20
allowed: 1 – 100
example: pageSize=20
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=items,total
exclude list

Return all fields except these (comma-separated).

example: exclude=pageInfo
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 6
items object[]

Current ordered slice; each item has stable id, name and rank fields.

example: [{"id":"item_000041","name":"Item 000087","rank":12}]

total integer

Exact fixture dataset size.

example: 137

sort string

Resolved sort key.

example: id

order string

Resolved ordering direction.

example: asc

datasetKey string

Resolved fixture dataset namespace.

example: demo

pageInfo object

Exact route-specific pagination metadata and navigation cursors/pages.

example: {"page":3,"pageSize":20,"totalPages":7,"hasNextPage":true}

Documented examples

Build-generated requests and complete responses
3
Third page of 137 records
GET /api/pagination/offset?total=137&page=3&pageSize=20
{
  "data": {
    "items": [
      {
        "id": "item_000041",
        "name": "Item 000002",
        "rank": 52
      },
      {
        "id": "item_000042",
        "name": "Item 000057",
        "rank": 109
      },
      {
        "id": "item_000043",
        "name": "Item 000112",
        "rank": 29
      },
      {
        "id": "item_000044",
        "name": "Item 000030",
        "rank": 86
      },
      {
        "id": "item_000045",
        "name": "Item 000085",
        "rank": 6
      },
      {
        "id": "item_000046",
        "name": "Item 000003",
        "rank": 63
      },
      {
        "id": "item_000047",
        "name": "Item 000058",
        "rank": 120
      },
      {
        "id": "item_000048",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Last partial page by descending rank
GET /api/pagination/offset?total=53&page=6&pageSize=10&sort=rank&order=desc&datasetKey=leaderboard
{
  "data": {
    "items": [
      {
        "id": "item_000008",
        "name": "Item 000016",
        "rank": 3
      },
      {
        "id": "item_000028",
        "name": "Item 000041",
        "rank": 2
      },
      {
        "id": "item_000048",
        "name": "Item 000013",
        "rank": 1
      }
    ],
    "total": 53,
    "sort": "rank",
    "order": "desc",
    "datasetKey": "leaderboard",
    "pageInfo": {
      "page": 6,
      "pageSize": 10,
      "totalPages": 6,
      "from": 51,
      "to": 53,
      "hasPreviousPage": true,
      "hasNextPage": false,
      "previousPage": 5,
      "nextPage": null
    }
  },
  "meta": {
    "endpoint": "pagination",
    "route": "/offset",
    "params": {
      "total": 53,
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
An empty dataset
GET /api/pagination/offset?total=0&page=1&pageSize=25
{
  "data": {
    "items": [],
    "total": 0,
    "sort": "id",
    "order": "asc",
    "datasetKey": "demo",
    "pageInfo": {
      "page": 1,
      "pageSize": 25,
      "totalPages": 0,
      "from": 0,
      "to": 0,
      "hasPreviousPage": false,
      "hasNextPage": false,
      "previousPage": null,
      "nextPage": null
    }
  },
  "meta": {
    "endpoint": "pagination",
    "route": "/offset",
    "params": {
      "total": 0,
      "sort": "id",
      "order": "asc",
      "datasetKey": "demo",
      "page": 1,
      "pageSize": 25
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/pagination/cursor

Live requestRuns against the public API
No key required
GET/api/pagination/cursor?total=137&sort=id&datasetKey=feed&first=20

Request parameters

Total size of the deterministic fixture dataset (0–10,000).

Stable ordering key. name and rank are independent deterministic permutations of id.

Ascending or descending order for the selected sort key.

Stable dataset namespace. Changing it changes the id/name/rank relationships and invalidates old cursors.

Maximum records after the supplied cursor (1–100).

Canonical opaque endCursor from the previous page. Omit to start at the beginning; pass it back unchanged. The bound covers every cursor emitted for a valid 64-character Unicode datasetKey.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/pagination/cursor?total=137&first=20&sort=id&datasetKey=feed"
const res = await fetch("https://randomapi.dev/api/pagination/cursor?total=137&first=20&sort=id&datasetKey=feed");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/pagination/cursor?total=137&first=20&sort=id&datasetKey=feed").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/pagination/cursor?total=137&first=20&sort=id&datasetKey=feed"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 6
total int

Total size of the deterministic fixture dataset (0–10,000).

default: 137
allowed: 0 – 10000
example: total=137
sort enum

Stable ordering key. name and rank are independent deterministic permutations of id.

default: id
allowed: id | name | rank
example: sort=rank
order enum

Ascending or descending order for the selected sort key.

default: asc
allowed: asc | desc
example: order=desc
datasetKey string

Stable dataset namespace. Changing it changes the id/name/rank relationships and invalidates old cursors.

default: demo
allowed: 1 – 64
example: datasetKey=catalog-demo
first int

Maximum records after the supplied cursor (1–100).

default: 20
allowed: 1 – 100
example: first=20
after string

Canonical opaque endCursor from the previous page. Omit to start at the beginning; pass it back unchanged. The bound covers every cursor emitted for a valid 64-character Unicode datasetKey.

allowed: 1 – 1024
example: after=eyJ2IjoxLCJwIjoxOSwidCI6MTM3LCJzIjoiaWQiLCJvIjoiYXNjIiwiayI6ImRlbW8ifQ
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=items,total
exclude list

Return all fields except these (comma-separated).

example: exclude=pageInfo
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 6
items object[]

Current ordered slice; each item has stable id, name and rank fields.

example: [{"id":"item_000041","name":"Item 000087","rank":12}]

total integer

Exact fixture dataset size.

example: 137

sort string

Resolved sort key.

example: id

order string

Resolved ordering direction.

example: asc

datasetKey string

Resolved fixture dataset namespace.

example: demo

pageInfo object

Exact route-specific pagination metadata and navigation cursors/pages.

example: {"page":3,"pageSize":20,"totalPages":7,"hasNextPage":true}

Documented examples

Build-generated requests and complete responses
2
First cursor page
GET /api/pagination/cursor?total=137&first=20&sort=id&datasetKey=feed
{
  "data": {
    "items": [
      {
        "id": "item_000001",
        "name": "Item 000018",
        "rank": 99
      },
      {
        "id": "item_000002",
        "name": "Item 000060",
        "rank": 1
      },
      {
        "id": "item_000003",
        "name": "Item 000102",
        "rank": 40
      },
      {
        "id": "item_000004",
        "name": "Item 000007",
        "rank": 79
      },
      {
        "id": "item_000005",
        "name": "Item 000049",
        "rank": 118
      },
      {
        "id": "item_000006",
        "name": "Item 000091",
        "rank": 20
      },
      {
        "id": "item_000007",
        "name": "Item 000133",
        "rank": 59
      },
      {
        "id": "item_000008",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
A compact descending leaderboard page
GET /api/pagination/cursor?total=40&first=8&sort=rank&order=desc&datasetKey=leaderboard
{
  "data": {
    "items": [
      {
        "id": "item_000009",
        "name": "Item 000035",
        "rank": 40
      },
      {
        "id": "item_000036",
        "name": "Item 000022",
        "rank": 39
      },
      {
        "id": "item_000023",
        "name": "Item 000009",
        "rank": 38
      },
      {
        "id": "item_000010",
        "name": "Item 000036",
        "rank": 37
      },
      {
        "id": "item_000037",
        "name": "Item 000023",
        "rank": 36
      },
      {
        "id": "item_000024",
        "name": "Item 000010",
        "rank": 35
      },
      {
        "id": "item_000011",
        "name": "Item 000037",
        "rank": 34
      },
      {
        "id": "item_000038",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

About this API

Coverage & behavior

A small, state-free pagination backend for client tests. Both routes expose slices of the same deterministic fixture dataset: each item has a stable id, an independently ordered name, and an independently ordered integer rank.

Use /offset for page-number UIs and /cursor for infinite scroll or Relay-style navigation. Totals, empty pages, first/last boundaries and next/previous metadata are exact. Walking every cursor page returns every item once — no gaps and no duplicates.

Cursors are canonical base64url transport tokens that carry and bind the exact total, sort, order and datasetKey settings. Reusing one with different settings is a 400 rather than silently moving through a different dataset. They are deliberately not signed authorization tokens: clients should treat them as opaque and pass them back unchanged, while servers must keep access control separate. This endpoint uses no clock or hidden state: identical resolved inputs always return identical output, and datasetKey is the explicit replay control.

Use it for

  • Exercise page-number tables against exact first, last, empty and out-of-range pages
  • Test infinite scroll by following opaque cursors without running a fixture server
  • Verify sort changes invalidate cursors instead of mixing two result orders

Frequently asked questions

Can I test both offset and cursor pagination?

Yes. /offset returns page-number metadata, while /cursor returns opaque start/end cursors and exact next/previous flags over the same fixture dataset.

Can a cursor be reused after changing the sort order?

No. Cursors are bound to total, sort, order and datasetKey; a mismatch returns 400 so two result orders can never be mixed silently.

Are the opaque cursors signed security tokens?

No. They canonically carry pagination state and must be passed back unchanged, but authorization belongs in your application and must never depend on a cursor being secret or unforgeable.

Are pagination results repeatable?

Yes. There is no hidden state or clock. The same resolved parameters return the same items and cursors; change datasetKey to create a different stable fixture dataset.