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
- Request page one with a small
firstand a filter that returns more rows than the
page size. - Read
pageInfo.endCursorandpageInfo.hasNextPage. - Request page two with the same filter and
afterset to the previousendCursor. - Repeat until
hasNextPageisfalse.
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 trigger | Do this | Expected code |
|---|---|---|
| Invalid credentials | Send a wrong API token | UNAUTHORIZED (HTTP 401) |
| Page size too large | Set first above 5000 | PAGE_SIZE_EXCEEDED |
| Date window too wide | Request a range wider than 90 days | DATE_WINDOW_EXCEEDED |
| Reversed date range | Set createdDateFrom after createdDateTo | INVALID_DATE_RANGE |
| Invalid cursor | Pass a garbage after value | INVALID_CURSOR |
| Non-aggregatable dataset | Call 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
isTestfield 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
- Quickstart recipes — copy-paste examples.
- Troubleshooting — symptom-based debugging.
Updated about 3 hours ago