# How disputes work

This page walks through the full dispute lifecycle so you know what to expect, from start to finish.

## Step 1 — Dispute is opened

A debtor opens a dispute in one of three ways the platform actually handles today:

* **In the portal.** After verifying OTP, the debtor posts to `/portal/disputes` with a reason (and optional narrative). A `Dispute` row is created in `open` status, the placement moves to `disputed`, and a `dispute_filed` audit event is written.
* **During a call.** Our agent fires the `capture_dispute` tool (with a `dispute_kind` of `billing`, `quality`, `fraud`, or `other`) and ends the call politely.
* **In an email reply.** The reply-intent classifier flags the reply as `dispute`, pauses the active email sequence, and flips the placement to `disputed`.

Mail handling is not yet automated. This is planned but not yet available.

The moment a dispute is opened, the placement moves to `disputed` status and outreach pauses.

## Step 2 — Evidence packet and creditor notification

For email/portal disputes, an automated agent assembles an evidence packet from existing tenant state — latest invoice, proof of service, contract, the placement's statute-of-limitations status, and the recent audit trail. The packet is captured in a `dispute.evidence_assembled` audit event.

The creditor sees the dispute in the dashboard. (Real-time email-to-creditor notifications on dispute opening are not part of the current implementation.)

## Step 3 — Response routing

The platform's dispute response matrix routes each dispute based on the reason and what evidence is on file:

* **Auto-response (email to debtor).** When the reason maps to `no_invoice`, `wrong_amount`, or `service_not_rendered` AND proof of service is on file, the system emails the debtor either the invoice packet (`dispute_auto_invoice_attached`) or a statute-of-limitations notice (`dispute_auto_sol_warning`). The dispute status flips to `auto_responded`.
* **Escalate to human.** Disputes for `already_paid`, `wrong_party`, anything tagged `unknown`, or any case where proof of service is missing are routed to a human reviewer. The dispute status flips to `awaiting_human` and the placement stays paused.

Possible final dispute statuses in the system: `open`, `reviewing`, `upheld`, `denied`, `withdrawn`, `auto_responded`, `awaiting_human`.

## Step 4 — Debtor is notified (auto-respond path only)

If the matrix chose an auto-response, the debtor receives the templated email directly — invoice attached, or a statute-of-limitations explanation. The email send is logged for cost tracking and audit.

For escalated disputes, the debtor sees status updates in the portal as a human reviewer works the case. Real-time email notification of the creditor's eventual response is not yet automated.

## Step 5 — Debtor can dispute again

If the debtor sees the auto-response and still disagrees, they can open another dispute through the portal. We don't limit how many times a debtor can dispute — but see [Frivolous disputes](/for-debtors/disputes/frivolous-disputes.md) for the rare case where this is abused.

## What's logged

Every step writes to the append-only audit log:

* `dispute_filed` — who disputed and the reason given.
* `dispute.evidence_assembled` — what evidence the platform found and what it couldn't find.
* `dispute.auto_responded` — when an auto-response email fired, including the template used.
* `dispute.escalated_human` — when the matrix routed the dispute to human review.

Audit events are append-only by design — they are never edited or deleted.

## When disputes are escalated

A dispute is escalated to a human reviewer automatically when the response matrix routes it to `escalate_to_human` (see Step 3). That happens for `already_paid` and `wrong_party` disputes, any reason that can't be classified, and any case where proof of service is missing. The placement stays paused while a human works the case.

***

Last reviewed: 2026-05-12 by Compliance Lead.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://help.moderncollections.io/for-debtors/disputes/how-disputes-work.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
