PayZuPayZu Docs
Boas práticas

Paginação

Endpoints que listam recursos (/user/transactions, /user/callbacks, /user/infractions) usam paginação clássica por page + limit com flag hasNextPage.

Padrão de loop

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 '.data[]'

  HAS_NEXT=$(echo "$RESP" | jq -r '.hasNextPage')
  [ "$HAS_NEXT" != "true" ] && 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 { data, hasNextPage } = await res.json();
    for (const tx of data) yield tx;
    if (!hasNextPage) return;
    page++;
  }
}

for await (const tx of iterateTransactions({ dateFrom: '2025-11-01' })) {
  await process(tx);
}
def iterate_transactions(**filters):
    page = 1
    limit = 100
    while True:
        res = requests.get(
            'https://api.payzu.processamento.com/v1/user/transactions',
            params={**filters, 'page': page, 'limit': limit},
            headers={
                'Authorization': f'Bearer {os.environ["PAYZU_TOKEN"]}',
                'Content-Type': 'application/json',
            },
        )
        body = res.json()
        for tx in body['data']:
            yield tx
        if not body.get('hasNextPage'):
            return
        page += 1
func IterateTransactions(filters url.Values, fn func(tx Transaction) error) error {
    page := 1
    for {
        filters.Set("page", strconv.Itoa(page))
        filters.Set("limit", "100")

        req, _ := http.NewRequest("GET",
            "https://api.payzu.processamento.com/v1/user/transactions?"+filters.Encode(), nil)
        req.Header.Set("Authorization", "Bearer "+os.Getenv("PAYZU_TOKEN"))
        req.Header.Set("Content-Type", "application/json")

        res, err := http.DefaultClient.Do(req)
        if err != nil { return err }

        var body struct {
            Data        []Transaction `json:"data"`
            HasNextPage bool          `json:"hasNextPage"`
        }
        if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
            res.Body.Close()
            return err
        }
        res.Body.Close()

        for _, tx := range body.Data {
            if err := fn(tx); err != nil { return err }
        }
        if !body.HasNextPage { return nil }
        page++
    }
}

Filtros disponíveis

FiltroQuando usar
dateFrom / dateToJanela temporal (ISO 8601).
clientReferenceEncontra a transação correspondente ao seu pedido.
virtualAccountFiltro por tenant (multi-loja).
statusCSV: COMPLETED,PENDING. Aceita múltiplos.
typeCSV: DEPOSIT,WITHDRAW,COMMISSION.
endToEndIdIdentificador único Bacen.
document, nameFiltros por pagador. document apenas dígitos (11 ou 14).
amountFiltro por valor exato.

Limite e tamanho da página

ItemValor
limit max100 por página
Default20

Páginas grandes demais degradam latência. Se precisa de período longo (mês, ano) ou exportar tudo, prefira o relatório assíncrono.

Quando usar relatório assíncrono em vez de paginar

CenárioRecomendação
Listagem em tela (dashboard)GET /user/transactions com paginação.
Verificação pontualGET /user/transactions?clientReference=order-1234.
Conciliação diária (< 10k transações)GET /user/transactions paginado.
Conciliação mensal/anualPOST /user/report (CSV assíncrono).
BI/Data WarehousePOST /user/report rodado diariamente, ingestão por ETL.

O relatório assíncrono gera arquivo CSV com URL assinada de download. Não tem limite de linhas e roda em background. Veja o tutorial de Conciliação.

Armadilhas comuns

ArmadilhaSintoma
Pegar tudo sem dateFrom em conta com volumeResposta lenta, possível timeout
limit=1000 (acima do permitido)API rejeita ou trunca
Iterar até data.length === 0 em vez de hasNextPageLoop infinito em página vazia da última iteração
Página fixa (page=1 sempre)Só lê o primeiro 100, perde o resto
Passar document com pontuação (123.456.789-00)Erro 400, regex aceita só dígitos

On this page