Example 10

API pagination and malformed records

Cursor pagination breaks on page boundaries, empty pages and records with missing fields.

Status
illustrative
Industry
Cross-industry
Language
JSON
Framework
Postman / Newman
CI
any
Fulfilment
BUILD_DATASET
Profile
edge-cases-core

About this example

All data is synthetic. DataNivra provisions approved test data into a customer-controlled target; it does not run these tests. Credentials for the target are never returned by DataNivra — your runner holds its own.

Why test data matters

Cursor pagination breaks on page boundaries, empty pages and records with missing fields.

What is requested

1,000 normal, 100 null-heavy and 50 invalid records.

Policy gates

Within the profile; synthetic-only.

What is provisioned

A certified synthetic dataset behind your API.

Expected output

Collection step 1 receives 201, step 2 polls until READY, the last step releases.

Cleanup

The collection's final request releases the test-data request.

Files

  • request.yaml
  • pagination.postman_collection.json

Run

  1. A tenant administrator defines and a second person approves the profile (datanivra test-data define ../../profiles/edge-cases-core.yaml --submit, then datanivra policies approve).
  2. datanivra test-data validate request.yaml && datanivra test-data plan request.yaml
  3. Run the example with DATANIVRA_BASE_URL and a session or workload token.

Files

Exactly as they are in the examples repository. Every value is a synthetic placeholder; nothing here is a credential.

request.yaml

# yaml-language-server: $schema=../../../../packages/contracts/schemas/v1/manifests/test-data-request.schema.json
# DataNivra test-data-request manifest (apiVersion datanivra.io/v1alpha1). Validate: datanivra test-data validate <file>
apiVersion: datanivra.io/v1alpha1
kind: TestDataRequest
metadata:
  name: pagination-edges
spec:
  profile: { name: edge-cases-core, version: 1 }
  scenarios:
    - { scenario_code: CORE_NORMAL, count: 1000 }
    - { scenario_code: CORE_NULL_HEAVY, count: 100 }
    - { scenario_code: CORE_INVALID, count: 50 }

examples/test-data-api/scenarios/10-api-pagination-edge-cases/request.yaml

pagination.postman_collection.json

{
  "info": {
    "name": "DataNivra test data: pagination edge cases",
    "description": "Acquire approved synthetic data, test your API's pagination, release. Set the collection variables baseUrl and token (never commit a token).",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.example.test"
    },
    {
      "key": "token",
      "value": ""
    }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{token}}",
        "type": "string"
      }
    ]
  },
  "item": [
    {
      "name": "1. Request test data",
      "event": [
        {
          "listen": "test",
          "script": {
            "exec": [
              "pm.test('created', () => pm.response.to.have.status(201));",
              "pm.collectionVariables.set('requestId', pm.response.json().id);"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": "{{baseUrl}}/v1/test-data/requests",
        "body": {
          "mode": "raw",
          "raw": "{\"profile\": {\"name\": \"edge-cases-core\", \"version\": 1}, \"scenarios\": [{\"scenario_code\": \"CORE_NORMAL\", \"count\": 1000}, {\"scenario_code\": \"CORE_NULL_HEAVY\", \"count\": 100}, {\"scenario_code\": \"CORE_INVALID\", \"count\": 50}]}"
        }
      }
    },
    {
      "name": "2. Wait until READY",
      "event": [
        {
          "listen": "test",
          "script": {
            "exec": [
              "if (pm.response.json().state !== 'READY') { setTimeout(() => {}, 5000); postman.setNextRequest('2. Wait until READY'); }"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "url": "{{baseUrl}}/v1/test-data/requests/{{requestId}}"
      }
    },
    {
      "name": "3. Your API: first page",
      "request": {
        "method": "GET",
        "url": "{{appUrl}}/orders?limit=100"
      }
    },
    {
      "name": "4. Release",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": "{{baseUrl}}/v1/test-data/requests/{{requestId}}/release",
        "body": {
          "mode": "raw",
          "raw": "{\"reason_code\": \"TEST_RUN_FINISHED\"}"
        }
      }
    }
  ]
}

examples/test-data-api/scenarios/10-api-pagination-edge-cases/pagination.postman_collection.json

The profile it uses: edge-cases-core

A tenant administrator defines this profile and a second person approves it; requests can only ask for what it allows. All profiles

edge-cases-core.yaml

# yaml-language-server: $schema=../../../packages/contracts/schemas/v1/manifests/test-data-profile.schema.json
# DataNivra test-data-profile manifest (apiVersion datanivra.io/v1alpha1). Validate: datanivra test-data validate <file>
# Placeholder ids (00000000-0000-4000-8000-0000000000NN): replace with your ids.
# 01 = approved target environment, 11 = certified dataset, 21 = customer agent,
# 99 = workload identity trust (datanivra workload-identities list).
apiVersion: datanivra.io/v1alpha1
kind: TestDataProfile
metadata:
  name: edge-cases-core
  description: Core synthetic edge cases (no industry pack)
spec:
  fulfilment: BUILD_DATASET
  build:
    business_domain: generic records
    dataset_kind: SYNTHETIC_ONLY
    target_environment_id: 00000000-0000-4000-8000-000000000001
    retention_days: 1
    max_total_records: 50000
    scenarios:
      - { scenario_code: CORE_NORMAL, kind: NORMAL, default_count: 200, max_count: 1000 }
      - { scenario_code: CORE_BOUNDARY, kind: BOUNDARY, default_count: 100, max_count: 500 }
      - {
          scenario_code: CORE_TEMPORAL_SEQUENCE,
          kind: TEMPORAL_SEQUENCE,
          default_count: 100,
          max_count: 500,
          included_by_default: false,
        }
      - {
          scenario_code: CORE_NULL_HEAVY,
          kind: NULL_HEAVY,
          default_count: 50,
          max_count: 200,
          included_by_default: false,
        }
      - {
          scenario_code: CORE_INVALID,
          kind: INVALID,
          default_count: 50,
          max_count: 200,
          included_by_default: false,
        }
      - {
          scenario_code: CORE_DUPLICATE,
          kind: DUPLICATE,
          default_count: 50,
          max_count: 200,
          included_by_default: false,
        }
      - {
          scenario_code: CORE_HIGH_VOLUME,
          kind: HIGH_VOLUME,
          default_count: 1000,
          max_count: 50000,
          included_by_default: false,
        }

examples/test-data-api/profiles/edge-cases-core.yaml