Easy Labs
SDKsNode.jsResources

Disputes

Disputes — methods, parameters, and examples for @easylabs/node.

A dispute is opened by the cardholder's bank to challenge a charge. The SDK lets you list and read disputes, attach tags, accept the chargeback, upload evidence files, and submit the response back to the network.

Methods

easy.getDisputes(params?);                          // GET    /disputes
easy.getDispute(disputeId);                         // GET    /disputes/:id
easy.updateDispute(disputeId, tags);                // PATCH  /disputes/:id (tags only)
easy.acceptDispute(disputeId);                      // POST   /disputes/:id/accept
easy.uploadDisputeEvidence(disputeId, file);        // POST   /disputes/:id/evidence (multipart)
easy.listDisputeEvidence(disputeId);                // GET    /disputes/:id/evidence
easy.submitDisputeEvidence(disputeId);              // POST   /disputes/:id/submit

Read

const disputes = await easy.getDisputes({ limit: 50 });
const { data: dispute } = await easy.getDispute(disputes.data[0].id);

Tag for triage

updateDispute only writes tags. The body shape is the new tag bag (server replaces, does not merge):

await easy.updateDispute(disputeId, {
  triage_owner: "agent_42",
  intended_response: "challenge",
});

Accept the chargeback

Forfeits the disputed funds and closes the case in the bank's favor — no evidence is sent.

await easy.acceptDispute(disputeId);

Upload + submit evidence

uploadDisputeEvidence sends multipart/form-data and bypasses the SDK's JSON content-type. Each file must be a Blob or File (Node 22's global File works), max 1 MB, allowed types image/jpeg, image/png, application/pdf.

import { readFile } from "node:fs/promises";

const bytes = await readFile("./receipt.pdf");
await easy.uploadDisputeEvidence(
  disputeId,
  new File([bytes], "receipt.pdf", { type: "application/pdf" }),
);

await easy.uploadDisputeEvidence(disputeId, /* … another file … */);

const evidence = await easy.listDisputeEvidence(disputeId);
console.log(`Attached ${evidence.data.length} files.`);

// When ready, submit the bundle:
await easy.submitDisputeEvidence(disputeId);

Once submitted, the response is locked in — uploads after submitDisputeEvidence are rejected.

Object shape

DisputeData mirrors the underlying processor record (snake_case identifiers, state, amounts, network reason codes, deadlines). Refer to the API reference for the canonical schema; the SDK re-exports it as DisputeData from @easylabs/node. DisputeEvidenceData is currently typed as { id: string; [key: string]: unknown } — refer to the API reference for the file metadata fields.

Examples

Webhook-driven response workflow

import { EasyWebhooks } from "@easylabs/node";

if (event.type === "dispute.created") {
  const dispute = event.data as { id: string; amount: number };
  if (dispute.amount < 1000) {
    await easy.acceptDispute(dispute.id); // not worth fighting
  } else {
    await easy.updateDispute(dispute.id, { triage_owner: "queue:dispute_team" });
  }
}

Bulk-list open disputes

let offset = 0;
const open = [];
while (true) {
  const page = await easy.getDisputes({ limit: 100, offset });
  open.push(...page.data);
  if (page.data.length < 100) break;
  offset += 100;
}

On this page