Disputes API
Disputes are created by customers during collection campaigns. The Disputes API lets you list disputes, inspect details, reply as the company, and resolve them.
Endpoints
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /disputes | disputes:read | List all disputes with filters and pagination. |
| GET | /disputes/{dispute_id} | disputes:read | Get dispute details, including the message thread. |
| POST | /disputes/{dispute_id}/reply | disputes:write | Reply to a dispute as the company. |
| PUT | /disputes/{dispute_id}/resolve | disputes:write | Resolve a dispute; syncs account status as appropriate. |
Scope behavior and empty-scope full-access rules are documented in Core Concepts → Authentication.
List disputes
Supported query parameters:
| Param | Type | Description |
|---|---|---|
status | string | Filter by open, replied, or resolved. |
customer_id | UUID | Filter by customer. |
page | integer | Page number (default: 1, min: 1). |
per_page | integer | Results per page (default: 20, min: 1, max: 100). |
Pagination behavior and the meta object (including total_pages) are documented in Core Concepts → Pagination.
Reply to a dispute
Request
{
"message": "Thank you for reaching out. We are reviewing your dispute."
}Response
{
"id": "uuid",
"grievance_id": "uuid",
"message": "Thank you for reaching out. We are reviewing your dispute.",
"sent_at": "2026-03-14T08:00:00Z"
}Resolve a dispute
{
"id": "uuid",
"status": "resolved",
"resolved_at": "2026-03-14T08:00:00Z"
}Resolving a dispute syncs invoice status using backend workflow:
- Count remaining non-resolved grievances on the invoice.
- If any are still open, invoice remains
DISPUTED. - If all are resolved:
- invoice with
campaign_id->IN_PROGRESS - invoice without
campaign_id->NOT_ASSIGNED
- invoice with
- Backend then resumes or completes campaign execution for the invoice automatically.
Reopening behavior
Resolved disputes can be implicitly reopened. If a customer replies to a resolved dispute,
status moves back to open and invoice status is synced back to DISPUTED.
There is no dedicated reopen endpoint.
Audit trail
Dispute actions are captured in immutable audit logs (internal API: GET /api/v1/audit-logs)
with actor, entity, timestamp, old/new values, and request metadata.
Fields affected by resolution
Dispute resolution only updates Invoice.status.
- Not affected:
enrollment_status - Not affected:
paid_amount,paid_at - Not affected: payment records