MCP guides
Refunding a customer
For assistants
An assistant connected to the Qualy MCP server reads this guide as the resource qualy://guides/refunds. Generated from the Qualy MCP server’s guide registry.
A refund draws against one charge: the transaction that took the customer's money, not the payment as a whole. Your account's refund approval policy decides what happens once you start it. Do it in this order: find the charge, see its routes, preview the figures, start it, then decide or follow it.
1. Find the charge
transaction_list with paymentIntent (the payment's number or id) lists its transactions; transaction_get reads one by number (QLY-TR-1234) or id. Refund a charge (transactionType charge, not an offset) whose status is succeeded or approved: refund_options refuses any other. Refunds already made show as negative amounts.
2. See how it can be refunded
Call refund_options with the charge's number (QLY-TR-1234) or id and the settlementCurrency the customer should receive. maxRefundable, in the charge's currency, is what the charge can still refund. Each of its options has a kind, a method, requiredFields, maxAmount and a status: use an active one rather than guessing a rail. A disabled one says why in statusReason, for example an open dispute, a payment already fully refunded, or a refund already in progress on the charge (a charge takes one at a time).
kind | Where the money goes | Also send |
|---|---|---|
native-reverse | Back to the original payment method. | |
contact-bank | To the customer's bank account. | bankAccount: active, in the settlementCurrency (what the customer receives), the customer's own. |
supplier-payout | To the supplier. The customer is not refunded. | partnership: the supplier's. |
Without kind, the refund goes back to the original payment method in the payment's currency, or to the customer's bank account in another currency (send bankAccount). With source supplier, the customer is still refunded through you and the supplier's share is tracked as supplier funding you can receive later (send partnership).
3. Preview the figures
refund_preview takes the same arguments as refund_intent_create and runs the same checks and tax, fee and FX calculation, but saves nothing and moves no money. amount is the gross, in major units of the charge's currency. Go on only when valid is true; otherwise reasons says why. Per item: feeRetained, taxTotal, refundableNet (gross less tax and fee), settlementAmount (what the customer receives, in the settlement currency; an estimate in another currency, at an indicative fxRate) and remainingAfter.
4. Start it
Call refund_intent_create with the previewed arguments and a reason (approvers see it). Its preview names your account's refund approval policy and says which applies:
- Needs approval. The refund waits as Needs review (
statusreview-pending). Nothing moves until it is approved. - Auto-approve. Confirming approves it and sends the money straight away. It can't be undone.
- No policy. It is refused. An admin can add one under Approvals → Approval policies, applying to Refund.
The result is the refund, with its approvalRequest and contacts (the customer of the refunded charge).
5. Approve or reject it
refund_intent_approve and refund_intent_reject decide that approval request as you. Their previews refuse what deciding would refuse: not one of its approvers, not your turn, no longer holding an approver role, or already decided. approval_request_get on the approvalRequest gives the same answer beforehand, as viewer (how approvals work: qualy://guides/approvals).
- Under Any approver or Round-robin your approval releases the refund and money moves. Under All approvers or Sequential only the last approval needed does; the preview says how many are still needed.
- Afterwards read
approval:released,approvedofrequired, and anoteto pass on. Sending starts in the background, so a released refund can still read Needs review: follow it withrefund_intent_get. - Any of its approvers may reject, once. The refund becomes Rejected and is never sent.
6. Follow it through
refund_intent_getshows one refund's amounts, fees, taxes, route and settlement state;refund_intent_listfilters bystatus, payment, charge or acreatedAtFrom/createdAtTowindow.refund_intent_cancelstops a refund before it is sent (Draft, Needs review or Approved).refund_intent_abandon_fundinggives up on a Processing or Partially completed refund waiting on a funding payment nobody paid (for example an unpaid PIX cobrança). It refuses if the provider says it was paid; otherwise that payment is canceled and the part of the refund waiting on it fails: the refund becomes Failed, or Partially completed if some of it was already refunded.refund_intent_receiptmakes the customer's receipt PDF once the refund is Completed or Partially completed.
Worked examples
See how that charge can be refunded
{
"tool": "refund_options",
"arguments": {
"transaction": "QLY-TR-1234",
"settlementCurrency": "AUD"
}
}
Use an option whose status is active: its kind and method go into the preview. maxRefundable is the most you can refund.
Preview a partial refund to the original card
{
"tool": "refund_preview",
"arguments": {
"transaction": "QLY-TR-1234",
"amount": 150,
"currency": "AUD",
"method": "ZAI_CC",
"kind": "native-reverse",
"reason": "Course cancelled before the start date."
}
}
Go on only when valid is true. settlementAmount is what the customer receives.
Start the refund you previewed
{
"tool": "refund_intent_create",
"arguments": {
"transaction": "QLY-TR-1234",
"amount": 150,
"currency": "AUD",
"method": "ZAI_CC",
"kind": "native-reverse",
"reason": "Course cancelled before the start date."
}
}
The preview says whether it waits for approval or, under Auto-approve, is sent straight away.
Previews first: the call returns a preview to show the person. Call it again with the same arguments plus confirmationId and userConfirmed: true only after they approve.
Approve a refund that needs review
{
"tool": "refund_intent_approve",
"arguments": {
"refundIntentId": "66f1c3b7e4b0a1b2c3d4e5f7",
"comment": "Checked against the cancellation policy."
}
}
Then read approval.released: under All approvers or Sequential one approval may move nothing.
Previews first: the call returns a preview to show the person. Call it again with the same arguments plus confirmationId and userConfirmed: true only after they approve.