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 thex-api-keyheader. See Authentication. - All requests go to
https://api.chargeflow.iounder 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:
{
"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
}
}| Field | Description |
|---|---|
pagination.totalCount | Total number of disputes available. |
pagination.offset | The current page offset. |
pagination.limit | Number of disputes returned in this page. |
pagination.totalPages | Total number of pages available. |
Steps
Fetch a single page
Set limit=100 to minimize the number of requests. Start at offset=0.
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.
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.
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=100so a 90-day backfill takes the fewest possible requests. - Run the backfill once at setup. After that, rely on the
dispute.createdwebhook 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.