Testing Guide

This guide helps you validate your integration against the Merchant Data API, from a first connectivity check to exercising pagination and error handling

1. Verify connectivity and credentials

Start with ping, which requires valid credentials but touches no data:

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 Ping { ping }"}'

Expected:

{ "data": { "ping": "pong" } }

If you receive UNAUTHORIZED (HTTP 401), your Shop ID or API token is wrong or missing.

2. Confirm your merchant scope

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 { currentMerchantId }"}'

The returned currentMerchantId confirms which merchant account your credentials
resolve to. All subsequent queries are scoped to it.

3. Retrieve a small, well-scoped result set

Use a narrow date window and a small page size so the query returns quickly:

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, $filter: PayinFilterInput) { payins(first: $first, filter: $filter) { edges { node { transactionId amount currency transactionStatusName createdTs } } summary { rowCount totalCount } } }",
    "variables": { "first": 5, "filter": { "createdDateFrom": "2026-06-01", "createdDateTo": "2026-06-07" } },
    "operationName": "Payins"
  }'

Check that summary.rowCount and the number of edges match, and that amounts are
returned as 2-decimal strings (for example "250.00") with an ISO 4217 currency.

4. Exercise pagination

  1. Request page one with a small first and a filter that returns more rows than the
    page size.
  2. Read pageInfo.endCursor and pageInfo.hasNextPage.
  3. Request page two with the same filter and after set to the previous endCursor.
  4. Repeat until hasNextPage is false.

Verify that no record appears twice across pages and that the run completes within the
4-hour cursor lifetime. See
Pagination, filtering, and sorting.

5. Test your error handling

Deliberately trigger errors and confirm your client branches correctly on
extensions.code and honours extensions.retryable. See Error handling.

To triggerDo thisExpected code
Invalid credentialsSend a wrong API tokenUNAUTHORIZED (HTTP 401)
Page size too largeSet first above 5000PAGE_SIZE_EXCEEDED
Date window too wideRequest a range wider than 90 daysDATE_WINDOW_EXCEEDED
Reversed date rangeSet createdDateFrom after createdDateToINVALID_DATE_RANGE
Invalid cursorPass a garbage after valueINVALID_CURSOR
Non-aggregatable datasetCall aggregations(dataset: MOVEMENTBALANCES, ...)INVALID_FILTER

Example: page-size violation.

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($f: Int) { payins(first: $f) { summary { rowCount } } }",
    "variables": { "f": 6000 }
  }'
{
  "errors": [
    {
      "message": "The page size you requested is larger than the maximum allowed (5000).",
      "extensions": { "code": "PAGE_SIZE_EXCEEDED", "retryable": false }
    }
  ]
}

6. Verify retry behaviour

Confirm that your client retries only when extensions.retryable is true (for example
QUERY_TIMEOUT, MERCHANT_CONCURRENCY_LIMIT_EXCEEDED, SERVICE_UNAVAILABLE) and uses
exponential backoff. Do not retry non-retryable errors; fix the request instead.

A note on test data

  • The isTest field on payins and payouts indicates test transactions where present.
  • There is no destructive operation to guard against: the API is read-only, so tests
    cannot alter your data.

_review_needed: No public sandbox environment is confirmed in the source material.
If you must test against production, keep queries low-volume and well-scoped. Confirm
whether a sandbox exists (see Environments).

Next steps



Did this page help you?