PayZuDocs
Best practices

Explains how to walk long lists with page and limit, and when to swap the listing for the CSV report.

Endpoints that list resources paginate with page + limit, but the response envelope differs per route. None of the three returns hasNextPage at the top level of the response.

EndpointResponse envelopeStop condition
GET /user/transactions{ total, pages, transactions }page >= pages
GET /user/callbacks{ pagination: { page, limit, hasNextPage }, callbacks }pagination.hasNextPage is false
GET /user/infractions{ pagination: { page, limit, totalItems, totalPages }, infractions }page >= pagination.totalPages

Loop pattern for /user/transactions

PAGE=1
LIMIT=100

while : ; do
  RESP=$(curl -s "https://api.payzu.processamento.com/v1/user/transactions?dateFrom=2025-11-01&page=$PAGE&limit=$LIMIT" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json")

  echo "$RESP" | jq -c '.transactions[]'

  PAGES=$(echo "$RESP" | jq -r '.pages')
  [ "$PAGE" -ge "$PAGES" ] && break
  PAGE=$((PAGE+1))
done
async function* iterateTransactions(filters: Record<string, string>) {
  let page = 1;
  const limit = 100;
  while (true) {
    const params = new URLSearchParams({ ...filters, page: String(page), limit: String(limit) });
    const res = await fetch(`https://api.payzu.processamento.com/v1/user/transactions?${params}`, {
      headers: {
        Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
        'Content-Type': 'application/json',
      },
    });
    const { pages, transactions } = await res.json();
    for (const tx of transactions) yield tx;
    if (page >= pages) return;
    page++;
  }
}

for await (const tx of iterateTransactions({ dateFrom: '2025-11-01' })) {
  await process(tx);
}

On /user/callbacks, iterate over callbacks and stop when pagination.hasNextPage is false. On /user/infractions, iterate over infractions and stop when page reaches pagination.totalPages.

Available filters

FilterWhen to use
dateFrom / dateToTime window (ISO 8601).
clientReferenceFinds the transaction matching your order.
virtualAccountFilter by tenant (multi-store).
statusCSV: COMPLETED,PENDING. Accepts multiple values.
typeCSV: DEPOSIT,WITHDRAW,COMMISSION.
endToEndIdUnique Bacen identifier.
document, namePayer filters. document digits only (11 or 14).
amountFilter by exact amount.

Page size and limit

Endpointlimit maxDefault
GET /user/transactions100010
GET /user/callbacks10010
GET /user/infractions10010

Above the route maximum, the request is rejected with 400 and errorCode PZV001. Oversized pages degrade latency. If you need a long period (month, year) or to export everything, prefer the asynchronous report.

When to use the asynchronous report instead of paginating

ScenarioRecommendation
On-screen listing (dashboard)GET /user/transactions with pagination.
Single lookupGET /user/transactions?clientReference=order-1234.
Daily reconciliation (< 10k transactions)GET /user/transactions paginated.
Monthly/yearly reconciliationPOST /user/report (asynchronous CSV).
BI/Data WarehousePOST /user/report run daily, ingested via ETL.

The asynchronous report generates a CSV file with a signed download URL. It has no row limit and runs in the background. See the Reconciliation tutorial.

Common pitfalls

PitfallSymptom
Fetching everything without dateFrom on a high-volume accountSlow response, possible timeout
limit above the route maximum (1000 on /user/callbacks)400 error with errorCode PZV001
Reading hasNextPage at the top level of the responseValue is absent, the loop stops on page one
Reusing one stop condition across the three routesPages dropped silently
Fixed page (page=1 always)Only reads the first page, misses the rest
Passing document with punctuation (123.456.789-00)400 error, regex accepts digits only

On this page