For MerchantsAutomation

Backfill the last 90 days

Page through GET /disputes to pull every dispute from the last 90 days into your own system.

When you first connect to Chargeflow, your webhook only fires for disputes that arrive after setup. To catch up on disputes that predate it, page through the Disputes list endpoint and keep the ones created in the last 90 days. This recipe is a full, copy-paste-runnable backfill.

Before you start

  • Get your API Access Key. Every request sends it in the x-api-key header. See Authentication.
  • All requests go to https://api.chargeflow.io under the /public/2025-04-01/ path.

How pagination works

The Disputes list endpoint uses offset-based pagination. See Pagination for the offset and limit parameters and the shared pattern.

For this recipe, the key detail is that offset is a page index, not a row count (covered in the note below).

The response wraps the results in disputes and a pagination object:

Response
{
  "disputes": [
    {
      "id": "66e6ea9ecd94925a9f8060d9",
      "source": "stripe",
      "source_id": "du_123456789",
      "created_at": "2024-02-10T12:00:00Z",
      "reason": "fraud",
      "due_by": "2024-02-20T12:00:00Z",
      "amount": 100,
      "currency": "USD",
      "status": "needs_response",
      "stage": "Chargeback"
    }
  ],
  "pagination": {
    "totalCount": 5400,
    "offset": 0,
    "limit": 100,
    "totalPages": 54
  }
}
FieldDescription
pagination.totalCountTotal number of disputes available.
pagination.offsetThe current page offset.
pagination.limitNumber of disputes returned in this page.
pagination.totalPagesTotal number of pages available.

Steps

Fetch a single page

Set limit=100 to minimize the number of requests. Start at offset=0.

Terminal
curl -X GET "https://api.chargeflow.io/public/2025-04-01/disputes?offset=0&limit=100" \
  -H "x-api-key: YOUR_API_KEY"

Page until you reach 90 days

Disputes come back newest first, so walk pages in order and stop once you cross the 90-day cutoff. Filter each page by created_at and break out as soon as a dispute is older than the window. Use pagination.totalPages as a hard stop so you never loop past the end.

Node.js
async function backfillLast90Days() {
  const limit = 100;
  const cutoff = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000);
  const recent = [];

  let offset = 0;
  let totalPages = 1;

  while (offset < totalPages) {
    const page = await fetchPage(offset, limit);
    totalPages = page.pagination.totalPages;

    let crossedCutoff = false;
    for (const dispute of page.disputes) {
      if (new Date(dispute.created_at) >= cutoff) {
        recent.push(dispute);
      } else {
        // Older than 90 days. Since results are newest first, we can stop.
        crossedCutoff = true;
        break;
      }
    }

    if (crossedCutoff) break;
    offset += 1;
  }

  return recent;
}

Note

offset is a page number, not a row count. Increment it by 1 per page, not by limit.

Process each dispute

With the 90-day list in hand, write each dispute to your own store and trigger whatever follow-up you need. For example, enrich any open dispute that is still in needs_response.

Node.js
const recent = await backfillLast90Days();
console.log(`Backfilled ${recent.length} disputes from the last 90 days`);

for (const dispute of recent) {
  // Persist the dispute in your system
  await upsertDispute(dispute);

  // Optionally act on disputes that still need a response
  if (dispute.status === 'needs_response') {
    // See the "Automate a chargeback dispute" recipe for the response flow
  }
}

Be a good API citizen

  • Use limit=100 so a 90-day backfill takes the fewest possible requests.
  • Run the backfill once at setup. After that, rely on the dispute.created webhook for new disputes rather than polling.
  • If you need to re-run the backfill, space out the requests instead of firing all pages at once.

Next steps

Was this page helpful?

On this page