Skip to main content

Disputes

ZendFi supports a customer-to-merchant dispute flow with optional admin resolution.

1) Request Dispute OTP (Public)

POST /api/v1/payments/{payment_id}/dispute/request-otp
Requests an email OTP used to verify customer ownership before dispute creation.

Request Body

customer_email
string
required
Customer email associated with the payment.

Response

{
  "payment_id": "0f1b6f0b-02ef-4fd4-bf31-a89f2fb52f54",
  "customer_email": "customer@example.com",
  "expires_at": "2026-03-22T10:31:15.871Z"
}

2) Create Dispute (Public)

POST /api/v1/payments/{payment_id}/dispute
Creates a dispute after customer verification.

Request Body

customer_email
string
required
Customer email for identity matching and OTP validation.
customer_wallet
string
Optional customer wallet used as alternate ownership proof.
dispute_type
string
required
One of: duplicate, unauthorized, product_not_received, other.
description
string
required
Customer dispute description.
evidence
object
Optional evidence object.
otp_code
string
required
OTP from the request-otp step.

3) List Merchant Disputes

GET /api/v1/merchants/me/disputes
Session-authenticated merchant endpoint.

Query Parameters

  • limit (default 50, max 100)
  • offset (default 0)
  • status (open, under_review, resolved_merchant_favor, resolved_customer_favor, closed)
  • dispute_type (duplicate, unauthorized, product_not_received, other)
  • start_date and end_date

4) Get Dispute Detail

GET /api/v1/merchants/me/disputes/{id}

5) Merchant Respond to Dispute

POST /api/v1/merchants/me/disputes/{id}/respond

Request Body

response
string
required
Merchant response text.
evidence
object
Optional structured evidence payload.

6) Merchant Issue Refund From Dispute

POST /api/v1/merchants/me/disputes/{id}/issue-refund
Creates a linked refund through the refunds system and resolves dispute to customer favor.

Request Body

amount_usd
number
required
Refund amount to issue.
refund_reason
string
Refund reason.
metadata
object
Optional metadata forwarded to the refund request.

7) Admin Resolve Dispute

POST /admin/disputes/{id}/resolve
Admin-authenticated endpoint for final resolution.

Request Body

outcome
string
required
merchant_favor, customer_favor, or closed.
resolution_notes
string
Optional admin notes.

Dispute Statuses

StatusMeaning
openDispute created, pending merchant action
under_reviewMerchant responded / evidence review in progress
resolved_merchant_favorFinal decision in merchant favor
resolved_customer_favorFinal decision in customer favor
closedDispute closed without favor designation

Dispute Lifecycle Events

  • DisputeOpened
  • DisputeResponded
  • DisputeResolved
See Webhooks.