Pagination, Filtering, and Sorting

The Merchant Data API uses cursor-based pagination for all list queries (payins, payouts, claims). This guide explains how to paginate through results, apply filters, and understand the response structure.

Most list queries return results in pages using forward-only cursor pagination. This
guide explains how to page through results, filter them, and understand the fixed sort
order.

Pagination

The payins, payouts, claims, and movementBalances queries are paginated. You
control paging with two arguments:

ArgumentTypeDescription
firstIntThe maximum number of items to return. Defaults to 1000, capped at 5000.
afterStringAn opaque cursor from a previous page. Returns items after that cursor.

Each paginated response contains:

  • edges — a list of { cursor, node } pairs. The node holds the record.
  • pageInfo.hasNextPagetrue if more items exist after this page.
  • pageInfo.endCursor — the cursor of the last edge. Pass it as after to fetch the
    next page.
  • summary.rowCount — the number of rows in this page.
  • summary.pageSizeLimit — the effective page size applied.
  • summary.totalCount — the total number of matching rows, when available.

First page

Request

curl -X POST https://api.payretailers.com/data-api/graphql \
  -u "YOUR_SHOP_ID:YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query Payins($first: Int, $after: String, $filter: PayinFilterInput) { payins(first: $first, after: $after, filter: $filter) { edges { cursor node { transactionId amount currency createdTs } } pageInfo { hasNextPage endCursor } summary { rowCount pageSizeLimit totalCount } } }",
    "variables": {
      "first": 100,
      "after": null,
      "filter": { "createdDateFrom": "2026-06-01", "createdDateTo": "2026-06-30" }
    },
    "operationName": "Payins"
  }'

Response (truncated)

{
  "data": {
    "payins": {
      "edges": [
        {
          "cursor": "eyJ0IjoiMjAyNi0wNi0wMSJ9",
          "node": {
            "transactionId": "PI-9000001",
            "amount": "125.50",
            "currency": "BRL",
            "createdTs": "2026-06-01T09:12:00Z"
          }
        }
      ],
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "eyJ0IjoiMjAyNi0wNi0wMiJ9"
      },
      "summary": {
        "rowCount": 100,
        "pageSizeLimit": 100,
        "totalCount": 1284
      }
    }
  }
}

Next page

Pass the previous page's endCursor as after, keeping the same filter:

{
  "variables": {
    "first": 100,
    "after": "eyJ0IjoiMjAyNi0wNi0wMiJ9",
    "filter": { "createdDateFrom": "2026-06-01", "createdDateTo": "2026-06-30" }
  }
}

Repeat until pageInfo.hasNextPage is false.

Cursor rules

  • Cursors are opaque. Do not parse, modify, truncate, or construct them yourself.
  • Cursors expire after 4 hours. An expired cursor returns CURSOR_EXPIRED; start
    again from the first page.
  • A malformed cursor returns INVALID_CURSOR. Pass the exact endCursor value you
    received.
  • Pagination is forward-only. There is no backward paging (last / before).

Non-paginated queries

  • reportBalances is not paginated. It returns { items } only, with no pageInfo
    or summary. Bound the result with createdDateFrom / createdDateTo (default and
    maximum 90 days).
  • aggregations returns a single result object, not a page.

Filtering

Each list query accepts a filter input. All filter fields are optional. Ranges use
...From / ...To pairs; identifiers are exact-match.

Common filter patterns

Filter typeFieldsBehaviour
Date rangecreatedDateFrom, createdDateToBounds the governed date window.
Amount rangeamountFrom, amountToInclusive numeric range.
StatusstatusExact match on the status label.
Exact identifiertransactionId, trackingId, claimId, operationIdPinpoint lookup (see below).

Available filter inputs per query:

  • PayinFilterInput: transactionId, trackingId, shopId, status, personId,
    customerEmail, countryName, paymentMethodName, amountFrom, amountTo,
    createdDateFrom, createdDateTo, editedDateFrom, editedDateTo.
  • PayoutFilterInput: the payin fields (minus paymentMethodName) plus
    settlementAmountFrom, settlementAmountTo.
  • ClaimFilterInput: claimId, transactionId, shopId, status, claimReason,
    amountFrom, amountTo, refundedAmountFrom, refundedAmountTo, createdDateFrom,
    createdDateTo, processedDateFrom, processedDateTo.
  • MovementBalanceFilterInput: shopId, movementType, operationId,
    createdDateFrom, createdDateTo.
  • ReportBalanceFilterInput: shopId, createdDateFrom, createdDateTo.
  • AggregationFilterInput: transactionId, shopId, status, personId,
    createdDateFrom, createdDateTo.

Pinpoint filters

Filtering by a unique identifier is a pinpoint filter: it fetches a specific record
and bypasses the default date-window requirement. Pinpoint fields are transactionId,
trackingId, claimId, operationId, and personId.

For example, to fetch a single claim by ID, combine a pinpoint filter with first: 1:

curl -X POST https://api.payretailers.com/data-api/graphql \
  -u "YOUR_SHOP_ID:YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query ClaimById($filter: ClaimFilterInput) { claims(first: 1, filter: $filter) { edges { node { claimId transactionId amount status claimReason refundedAmount } } } }",
    "variables": { "filter": { "claimId": "CLM-100045" } },
    "operationName": "ClaimById"
  }'

Date windows

Date filters are governed to protect the platform:

DatasetDefault windowMaximum window
Payins, payouts, claims90 days90 days
Report balances90 days90 days
Movement balances1 day31 days

If you omit a date filter on a governed query, the default window is applied
automatically (unless you use a pinpoint filter). Requesting a wider window returns
DATE_WINDOW_EXCEEDED; a range where "from" is after "to" returns INVALID_DATE_RANGE.
Split longer ranges into several queries.

Sorting

Sort order is fixed and not configurable. Results are returned in a stable order
keyed on each dataset's cursor key plus its creation timestamp:

DatasetCursor key
Payins, payoutstransactionId
ClaimsclaimId
Movement balancesoperationId

This fixed order is what makes cursor pagination stable across pages.

Next steps



Did this page help you?