Skip to main content

Filing a Dispute

You can only file disputes for transactions that:
  • Have a postedAt timestamp (settled transactions). You can’t dispute pending or unsettled transactions.
  • Have a non-zero amount. You can’t dispute zero-amount transactions, such as authorization holds the merchant never captured.
If a transaction doesn’t meet these requirements, the API returns a 400 Bad Request error.

Card Network Deadline

Card networks (Visa, Mastercard) require you to file a dispute within a set window that counts from the transaction date. The window is 120 days for most disputes, but a shorter 75-day window applies when either of these is true:
  • The transaction was force-posted, meaning it settled without a prior authorization. In this case, the spend.isForcePosted field on the transaction is true.
  • You file the dispute under one of these Visa reason codes: cardRecoveryBulletin (11.1), declinedAuthorization (11.2), noAuthorization (11.3), or invalidData (12.7). See the reason code table for their descriptions.
If you file after the window that applies, the card network may decline the dispute.
Submit disputes as early as possible. A dispute filed close to its deadline (75 or 120 days from the transaction date) has a higher risk of rejection.
To file a dispute, use Rain’s Dispute API.

Dispute Reason Codes

When you file a dispute, you can optionally set a disputeReasonCode to classify it precisely using a Visa Claims Resolution (VCR) reason code. Reason codes give you finer-grained classification than the broad disputeType categories, which reduces back-and-forth during review. The disputeReasonCode field is optional. Here is how it interacts with disputeType when you create a dispute:
  • If you send only disputeReasonCode, Rain derives the disputeType from it automatically.
  • If you send only disputeType, Rain files the dispute with that type and no reason code, exactly as before.
  • If you send both, they must agree. If the reason code implies a different disputeType than the one you sent, the API returns a 400 Bad Request naming the expected type.
  • If you send a reason code that is not one of the supported values, the API returns a 400 Bad Request.
Rain returns the reason code on the dispute wherever you read it, including the get, list, and update responses. Rain omits the field when you file the dispute without one. Each reason code maps to a coarse disputeType, as shown in the table below.

Dispute Thresholds and Fees

Rain files a dispute with the card network only when the disputed amount meets a minimum threshold. Nothing changes in how or what you submit. Keep submitting every dispute regardless of size: reporting a dispute costs you nothing, and it helps Rain track fraud patterns even when Rain doesn’t file a formal dispute. The date you submit a dispute determines which threshold applies: Your MSA defines these thresholds. Refer to your MSA for the full terms, and reach out to your account manager with any questions.

Informational-Only Disputes

Set informationalOnly to true when you create a dispute to record it without submitting it to the card network. Use it when a merchant is already resolving the issue directly, such as refunding a $40 charge. The field defaults to false, and you cannot change it after creation. An informational-only dispute still counts toward the one active dispute allowed per transaction and still gets a filing deadline. The dispute.created and dispute.updated webhooks fire as usual but don’t include informationalOnly, so retrieve the dispute to check it.

Webhooks

Rain sends webhook notifications to track dispute lifecycle events in real-time. These webhooks are informational and do not require a response.

created

Dispute created webhook:Rain sends this webhook when you create a new dispute for a transaction.
See the dispute.created webhook reference for the full payload schema, field descriptions, and version history.

updated

Dispute status update webhook:Rain triggers this webhook when a dispute’s status changes or you change textEvidence.
Provides real-time updates on dispute resolution progress. Handle both status transitions and evidence updates in your webhook handler. See the dispute.updated webhook reference for the full payload schema, field descriptions, and version history. Possible status values: "pending", "inReview", "accepted", "rejected", "canceled", "resolvedByMerchant"
Key fields:There are two different id fields. The one in the root is the webhookId, while the one in the body is the disputeId.

Dispute Reimbursement Process

Rain automatically processes reimbursements when the card network accepts a dispute. Tenants with onchain refunds or Real Time Funding get the reimbursement on-chain instead of as an account credit. Network investigations and chargebacks typically resolve within 30-60 business days.

Reimbursement timeline

  1. Create a dispute using the Dispute API
  2. Rain reviews the dispute (status: "inReview", reviewedBy: "rain")
  3. When the card network reviews it, the status stays "inReview" and reviewedBy changes to "network"
  4. If the network accepts (status: "accepted"), Rain processes the reimbursement
  5. You receive a transaction.completed webhook for the credit transaction
  6. Rain applies the credit amount

What happens during reimbursement

When the card network accepts a dispute, Rain processes the reimbursement:
  • Rain creates a new transaction with a negative amount (a credit)
  • The credit amount is what the card network accepts, which can be less than the disputeAmount you filed. If you don’t send a disputeAmount, the full transaction amount is disputed.
  • The transaction appears in transaction history as type "spend" with a negative amount
  • You receive a transaction.completed webhook for the credit

Webhook notifications

You receive webhook notifications during the dispute lifecycle:
  1. dispute.updated - Rain sends this when the dispute status changes (including "accepted", "rejected", "canceled", "resolvedByMerchant", or "inReview") and when textEvidence changes.
  2. transaction.completed - Rain sends this when it processes the reimbursement for an accepted dispute. It includes the negative transaction amount.
The transaction.completed webhook follows the same format as other transaction webhooks, with a negative amount field indicating a credit.

Unauthorized transactions

When a user reports a transaction they didn’t make:
  1. Cancel the affected card immediately by setting its status to canceled.
  2. Issue a new card to the user.
  3. File a dispute for the unauthorized transaction.
Rain’s team manages the dispute through the card network from there.

Pending and reversed transactions

A pending transaction is waiting for the merchant to finalize or cancel it. Most clear within days, but a transaction can stay pending for up to 30 business days; until it resolves, the funds are neither fully debited nor refunded.
  • Terminal declined, but funds are held. Confirm with the merchant that their system declined the transaction. If the merchant never finalized the authorization, the hold returns to the account automatically when the authorization expires.
  • No transaction ID for an attempted payment. Rain never received the authorization request. Check with the merchant for issues on their side, and have the cardholder try another payment method if the problem persists.
  • A transaction reversed. Reversals typically come from a merchant decline or a terminal error. If an expected reversal hasn’t posted within 30 days, escalate to Rain support.
For refund timing, including canceled orders and merchant-declined refunds, see Refund timing.

What’s next

Transaction events

See the full webhook payload and field reference for every transaction event.

Disputes

See the dispute lifecycle events and their trigger conditions.