Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.whop.com/llms.txt

Use this file to discover all available pages before exploring further.

Two things can happen after a payment goes through. Refunds are a reversal you (or your support team) issue on purpose. Disputes are chargebacks the buyer files with their bank. You don’t always control how a dispute lands, but you can respond with evidence.
Subscribe to webhooks for refund.created, refund.updated, dispute.created, dispute.updated, and dispute_alert.created so you can reconcile status changes without polling.

Refunds

Refunds reverse a successful payment. Whop processes them through the original payment processor. The matching membership status updates automatically.

Issue a refund

Refunds are created against a payment, not directly on the refunds resource. Call payments.refund(id, ...). Omit partial_amount for a full refund, or pass it for a partial.
import Whop from "@whop/sdk";

const client = new Whop({ apiKey: process.env.WHOP_API_KEY });

// Full refund
const fullRefund = await client.payments.refund("pay_xxxxxxxxxxxxx");

// Partial refund
const partialRefund = await client.payments.refund("pay_xxxxxxxxxxxxx", {
  partial_amount: 5.0, // in payment currency, e.g. 5 USD
});
The response is the updated Payment object. The refunded_amount field reflects the cumulative refunded total. You can call refund multiple times against a payment up to its full amount.
Required permission: payment:manage. Add it from the Permissions guide before publishing your app.

Inspect refunds

Refunds have their own resource if you need to look them up after the fact.
const refund = await client.refunds.retrieve("ref_xxxxxxxxxxxxx");

for await (const page of client.refunds.list({
  company_id: "biz_xxxxxxxxxxxxx",
})) {
  console.log(page);
}

Disputes

A dispute (chargeback) opens when the buyer’s bank challenges a payment. You have a window to respond with evidence before the bank decides. Whop forwards the dispute to you, you submit evidence, the bank rules, and the dispute closes.

Watch for incoming disputes

Two events to subscribe to:
EventMeaning
dispute_alert.createdEarly warning before a formal dispute. Some processors give a heads-up. Not every alert turns into a dispute.
dispute.createdFormal dispute opened. Response window starts.
dispute.updatedStatus changes (e.g. from needs_response to under_review, then won or lost).

List and retrieve

for await (const page of client.disputes.list({
  company_id: "biz_xxxxxxxxxxxxx",
})) {
  console.log(page);
}

const dispute = await client.disputes.retrieve("dp_xxxxxxxxxxxxx");

Respond with evidence

Disputes have a two-step response: stage your evidence with updateEvidence, then submit with submitEvidence. Update is idempotent. You can edit fields up until you submit.
// Stage evidence (call as many times as needed)
await client.disputes.updateEvidence("dp_xxxxxxxxxxxxx", {
  customer_name: "Jane Doe",
  customer_email_address: "jane@example.com",
  product_description: "Annual subscription to Acme Pro, purchased 2026-01-15.",
  service_date: "2026-01-15",
  refund_policy_disclosure: "Customer agreed to no-refunds policy at checkout.",
  notes: "Customer used the product 47 times across 8 sessions before disputing.",
});

// Submit evidence to the processor. After this, you can no longer edit.
await client.disputes.submitEvidence("dp_xxxxxxxxxxxxx");

Evidence fields

Every field is optional, but the more you provide, the stronger the response. Common ones:
FieldWhat to put in it
customer_name / customer_email_addressIdentifying info you have on file
product_descriptionWhat the customer bought, in plain language
service_dateWhen the service was rendered (ISO 8601)
billing_addressThe address used at checkout
customer_communication_attachmentEmail or chat threads showing the customer engaged
cancellation_policy_attachment / cancellation_policy_disclosureYour policy and proof the customer accepted it
refund_policy_attachment / refund_policy_disclosureSame for refunds
refund_refusal_explanationWhy you didn’t refund (e.g. usage past return window)
access_activity_logLogin or usage logs proving the customer used the product
uncategorized_attachmentAnything else relevant
Attachment fields take an uploaded file ID. Upload first via the Files API, then pass file.id.

Dispute statuses

The dispute moves through a state machine. There are two phases: the early-warning phase (statuses prefixed warning_, surfaced via dispute_alert.created) and the formal dispute phase. Every status the SDK can return:
StatusPhaseMeaning
warning_needs_responseAlertA dispute alert is open. You can preempt with a refund or response before it escalates.
warning_under_reviewAlertYou responded to the alert; the processor is deciding whether to escalate.
warning_closedAlertThe alert resolved without becoming a formal dispute.
needs_responseDisputeFormal dispute open. Submit evidence before the response window closes.
under_reviewDisputeYou submitted evidence; the processor is deciding.
wonDisputeFunds stay with you.
lostDisputeFunds go back to the buyer. The original payment is reversed.
closedDisputeDispute closed without a formal won/lost outcome (e.g. withdrawn).
otherEitherCatch-all for statuses that don’t fit the above. Treat as informational.
When a dispute is lost, Whop does not auto-create a Refund record and you cannot create one yourself. payments.refund rejects calls against a disputed payment with “This payment has been disputed. Therefore, it cannot be refunded.” Track the lost dispute as the source of truth and do not expect a refund.created event.

Permissions

ActionRequired permission
Create a refundpayment:manage
Retrieve / list refundspayment:basic:read
Retrieve / list disputespayment:dispute:read
Update or submit evidencepayment:dispute
Add these from the Permissions guide.

Next steps

Accept payments

The flow that creates the payments you’ll later refund or defend.

Listen to webhooks

React to refund and dispute events server-side.

Upload files

Upload evidence attachments for dispute responses.

Disputes API reference

Full resource: fields, statuses, and every endpoint.