Square API Pagination Skips Transactions When Retrieving Large Sets of Payments Across Multiple Pages

Hi members,

I am experiencing an intermittent data retrieval problem while using the Square Payments API in a native application that collects transaction records for internal reconciliation and reporting. The application requests payment information over a selected time period and processes the returned records to build a complete list of transactions for that period. When the number of payments is relatively small, the process generally works as expected, and the application can retrieve and organize the records without any obvious inconsistencies. However, when the same process runs against a period containing a much larger number of transactions, the final collection occasionally appears to be missing some payments that I can locate through other transaction records. The API requests themselves often return successful responses, so the application does not always recognize that the resulting dataset may be incomplete. This is creating a problem for reconciliation because the application relies on the retrieved records to calculate totals and compare transaction activity across a defined period.

The issue seems to occur during pagination rather than when retrieving an individual payment by its ID. My implementation follows the pagination information returned by the API, using the continuation cursor when another page of results is available and continuing until the response no longer provides a cursor. I have reviewed the loop responsible for making successive requests and added logging to record the number of payments returned on each page, the presence of a cursor, and the number of unique payment IDs collected. Despite these checks, there are occasions when the final number of unique records appears lower than expected. The missing transactions are not necessarily grouped together in one obvious section of the results, and I have not yet identified a consistent pattern based on payment amount or transaction timing. Because each individual response appears structurally valid, I am unsure whether the issue is caused by how the pagination sequence is being handled in my application or by an assumption I am making about the completeness of the results returned across multiple requests.

I have tried running the same retrieval process again for the same time period and comparing the resulting payment IDs. In some cases, the second run produces a slightly different collection, although I have not established whether this is because transactions are being created or updated while the requests are running or because my pagination logic is not consistently processing every page. The application currently gathers the records over several sequential API requests, so the underlying transaction data could potentially change during the retrieval window. I want to understand how Square expects developers to handle pagination when the dataset is large and payment activity is ongoing. In particular, I am uncertain whether a cursor should be treated as a continuation point for a changing collection or whether the API provides guarantees that the sequence remains consistent throughout a multi-page retrieval. I do not want to assume that a different result on a subsequent run proves that the API has skipped records, because I recognize that changes to the underlying dataset could also affect what the application observes.

Another part of the investigation involves the filters applied to the payment retrieval requests. The application uses a date range and other supported query parameters to limit the records to the period needed for reconciliation. I have checked that the same intended filters are supplied to subsequent requests, and I am reviewing whether any request parameters are accidentally omitted or changed as the pagination loop advances. I am also comparing the timestamps and IDs of transactions near the boundaries of the selected period to see whether records are being excluded because of how the time range is interpreted. So far, I have not found one specific filter that consistently explains the missing entries. I would appreciate advice on which request parameters must remain unchanged when following a pagination cursor and whether there are documented limitations or considerations when retrieving payments over a time interval during which new transactions may continue to arrive. Understanding these details would help me distinguish a filtering mistake from a pagination problem without changing the query conditions unnecessarily.

I would also like to know what the recommended verification strategy is for ensuring that a paginated collection is complete before using it in reconciliation calculations. At present, the application records the cursor sequence and accumulates the returned payment IDs, but it does not have an independent way to prove that every eligible payment was included. I am considering comparing the retrieved records against a separate set of known payment IDs and running a follow-up retrieval for the same time range, but I am unsure how to account for transactions that become available or change while the collection is being processed. I want to avoid repeatedly downloading the entire payment history because that would increase API usage and processing time as the dataset grows. If Square provides a recommended approach for reconciling paginated results, detecting incomplete retrievals, or safely processing transactions that arrive during a long-running collection operation, I would be interested in learning how other developers handle this situation.

Has anyone encountered missing or inconsistent payment records when using cursor-based pagination with the Square Payments API, particularly when retrieving a large number of transactions over a date range? I would appreciate suggestions for checking the pagination implementation, validating cursor handling, and designing a retrieval process that remains dependable while new payments are being created. I can provide sanitized request parameters, the number of records returned on each page, cursor-presence logs, and examples of payment IDs that were missing from one run but appeared in another. My goal is to ensure that the application can build a complete and reproducible transaction collection for reconciliation without relying on assumptions about page sizes or making unnecessary repeated requests. I would prefer to resolve this single data retrieval issue before changing the wider reporting workflow or introducing additional processing mechanisms that may not be necessary. Please assist!

When you follow a cursor, send the exact same query parameters as the first request (begin_time, end_time, location_id, sort_order, sort_field, limit, plus any other filters) and add only cursor. If a parameter changes between pages, the results are undefined. See Pagination and ListPayments.

Check these before you assume pagination skipped records:

  • begin_time/end_time filter on created_at. A payment updated inside your window but created outside it won’t be returned. To capture changes, use updated_at_begin_time/updated_at_end_time with sort_field=UPDATED_AT.
  • If you leave out location_id, results come only from the seller’s default location. Run one query for each location.
  • If you leave out end_time, it defaults to the current time, so the window keeps growing while the loop runs. For reconciliation, set an explicit end_time that is already in the past.
  • Responses don’t include a total count, so a complete page sequence is the only completeness signal you get.

For reconciliation, pull a fixed closed window once. After that, run incremental pulls on updated_at that overlap the previous run slightly, and dedupe by payment ID. You can also subscribe to payment.created/payment.updated webhooks and use them to cross-check. If you still see a payment that’s missing from a closed window with identical parameters, post the sanitized request parameters, the page-by-page counts and a missing payment ID with its created_at, and we’ll look into it.