A refund is about more than returning money. It’s about understanding what went wrong.
Here's a workflow to help you review each case, prepare a clear response, and identify patterns to improve your product.
Create a document titled "Refund Rules."
Add four possible decisions:
Before making a decision, compare the purchase date submitted through the refund request form with the transaction date in Stripe or your payment system. You should also check the customer’s product usage in your course platform, SaaS database, or store.
Every refund request should have one final decision.
Open Jotform: Click Create Form → Start From Scratch → Classic Form.
Add these fields:
Add these options under Refund Reason:
Add these options under Preferred Resolution:
Open Settings → Conditions → Show/Hide Field.
Create these rules:
Preview the form and test every option.
Add this notice (or something similar) above the Submit button: "Submitting this form does not guarantee a refund. We will review your order, product usage, and our refund policy: [POLICY LINK]."
Customers can now explain the problem and tell you what they want in one form.
Create a Google Sheet called Refund Operations.
Add these column headers to row 1: Request ID, Submitted At, Month Key, Name, Email, Order ID, Product, Customer Reason, Customer Details, Preferred Resolution, AI Review, Issue Class, Order Verified, Policy Eligible, Usage Checked, Risk Flag, Decision, Workflow Status, Refund Amount, Refund Reference, Final Outcome, Product Fix.
Each row will represent one refund request.
In Zapier, create a new Zap.
Set up the trigger:
Next, create the Month Key:
Next, add ChatGPT (OpenAI) → Send Prompt.
Paste this prompt (or something similar):
"You assist a human refund reviewer. Use only the facts below.
Return exactly:
SUMMARY:
Likely_issue_class:
Missing_facts:
Risk_flags:
Support_option:
Allowed classes: ACCESS, TECHNICAL, EXPECTATION, BILLING, ACCIDENTAL, OTHER.
Do not approve or deny. Do not invent policy terms, usage, payment status, or customer history.
Order ID: [map Order ID]
Product: [map Product]
Purchase date claimed: [map Purchase Date]
Reason: [map Refund Reason]
Details: [map What Happened]
Tried: [map What Have You Tried]
Preferred resolution: [map Preferred Resolution]"
Finish the Zap with these steps:
Each new form submission will now create a row in the sheet with the customer’s answers and an AI summary.
Open the matching order in your payment and product systems.
Set these values in the sheet:
Review the information before choosing a decision.
The AI summarizes the request. You make the final decision.
Create a second Zap.
Set up the filter so the Zap only continues when both of these are true:
Test the filter. If both conditions are true, the Zap should continue. Otherwise, it should stop.
Create four paths, one for each decision state listed in Step 1:
Path 1: Approve
Address the draft to the customer. Leave placeholders for:
Do not send the draft.
Path 2: Support_first
The prompt should ask the AI to write a reply using only the verified information. Include the support action and explain what the customer should do if it doesn't solve the problem.
Add Gmail → Create Draft. Map the text from ChatGPT to the email body.
Path 3: Deny
State the policy rule that applies. Include a link to your refund policy.
Party 4: Escalate
Include the following in the email:
Add Google Sheets → Update Spreadsheet Row at the end of every path.
Use the trigger's Row ID. Set Workflow Status to _DRAFT\READY or ESCALATED. This updates the same row.
In Stripe:
If the refund is successful, add the refund amount and refund reference to your sheet, if available.
Do not tell the customer the refund has arrived. It may take several business days for the refund to appear.
Create a third Zap.
Use the scheduled time as Input. Subtract one month.
Send the rows to ChatGPT with a prompt asking the AI to summarize the refund data and suggest improvements based solely on the information it receives.
Send the summary to yourself with Gmail → Send Email
Before you publish, test all four paths:
Make sure that everything works as expected before using the workflow with real customers.
One gap I would add to step 7 that bites a lot of early teams. Refunding in Stripe does not revoke access in your app automatically. So you get refunded but still on paid plan as a silent leak. I have seen that same class of bug in billing audits where affiliate commission or rev share was paid on the original invoice and never reversed when the refund happened in the dashboard. Once a month pull all Stripe refunds and also charge dispute created events, since a dispute takes money faster and is more likely to still have access attached, and cross check against active entitlements. The rule should compare amount refunded to invoice total though, a partial refund should not revoke anything.
This sounds like the right balance. AI can organize the evidence and flag suspicious patterns, but letting it make the final refund decision could create some painful customer experiences. How much review time did the system save your team?
Great breakdown. The AI drafts, human decides split is exactly how we build automation for clients too. One thing that helps a lot: keep the actual refund rules in the sheet or rules layer, not just in the prompt. That way when policy changes, you always know what rule applied to an old request. Also agree with the point above about checking Stripe refunds against active access. We have seen that same leak on client accounts.
The "AI drafts, human decides" split is the same principle EzWrite runs on for messages — it writes three versions, but nothing goes out until you pick and often tweak one. Feels like the right default for anything that touches an actual customer relationship, not just refunds.
I like the “AI drafts, human decides” approach. The audit trail point is especially important because it makes mistakes easier to review and improve over time. For a small business, would you start with simple rule-based approvals first, then add AI only for summarizing and drafting replies?
The core instinct is right - AI drafts, human decides - but I'd push the split even harder: the LLM should never be the thing that decides the money, and it also shouldn't be the thing that knows the policy.
What tends to work:
Two failure modes to design against: (1) a confidently-worded draft that quotes your refund policy wrong - keep the actual policy in the rules layer, not in the prompt, or it'll hallucinate terms; (2) no audit trail - log the AI summary and the human decision side by side so you can catch drift when the model or your product changes.
And the pattern-detection piece you mention is honestly the best ROI in the whole flow - clustering refund reasons turns support cost into product feedback, with zero decision risk.
Automate refund reviews by letting AI analyze requests, detect risks, and recommend actions, while human reviewers make the final decision. This improves speed, accuracy, consistency, and customer trust without sacrificing oversight.
Add two columns to that sheet: days since purchase, and number of sessions before the request. Most of our refunds clustered inside the first 72 hours with almost no usage, which meant the problem was activation, not the product, and no amount of reply drafting would have fixed it. The Zaps handle the response, those two fields tell you whether to change onboarding or change the product.
The refund analytics layer is underrated — most founders treat refunds as losses to minimize, not as product feedback. We just finished migrating all our payment infrastructure from PayPal to Creem today, and one thing Creem does better: refund data is centralized and queryable. Before that, PayPal gave us zero insight into why people refunded — just a transaction ID.
One pattern we caught after centralizing: a spike in refunds right after checkout completion. Turned out our "thank you" page didn't display the download link clearly enough for mobile users. That's a $0 fix that recovered revenue. Would love to see your Jotform→Zapier→ChatGPT workflow include a "refund reason categorization" step — cluster them weekly and flag product issues vs. payment issues.
One operational detail I’d add is making the refund step idempotent and event-driven.
A Zap retry, a duplicate form submission, or a reviewer clicking twice could otherwise create a duplicate refund. Before calling Stripe, the workflow should persist the internal request ID, check whether a refund already exists, and store the Stripe refund ID after the action.
I’d also separate states such as REFUND_PENDING and REFUNDED. The workflow can mark a request as pending after the API call, then use the Stripe event or a reconciliation job to confirm the final state. That seems safer than treating a successful button action as proof that the refund has completed.
How are you planning to handle retries, duplicate submissions, and partial refunds?
Great workflow, but it stops one step early. Step 7 refunds the money in Stripe, and nothing here pulls the access. Refunds live in Stripe, entitlements live in your app, and no tool connects the two automatically — so "refunded but still on the paid plan" is one of the most common silent leaks I see doing billing reconciliation. Same class of problem as the affiliate commissions point mihir raised.
Cheap fix that fits your monthly loop: pull the full refunds from Stripe and cross-check them against accounts that still have active access. Takes minutes, and every hit is money quietly walking out the door.
the cross-check catches less than you'd want if it only queries refunds. charge.dispute.created is a separate event from charge.refunded, and a disputed charge takes the money faster and is the one more likely to still have access sitting on it. worth pulling both in the same monthly sweep.
one caveat on the revoke side: a partial refund shouldn't revoke anything, so the rule has to compare amount_refunded against the invoice total rather than just checking that a refund exists.
I’m not very technical, but keeping the final decision with a person makes sense to me. A customer might explain the problem badly or have an unusual situation, and an AI summary could miss something important.
I’d also want the reviewer to see the customer’s original message, not only the AI version. In this workflow, does the human always read the original request before making the decision?
the four outcomes are a good taxonomy. the one I would put a clock on is deny.
a denied refund does not end the transaction, it moves it. the customer still has a chargeback window open, and a chargeback costs you the disputed amount plus a fee, gets decided by the issuer rather than by your policy, and leaves a dispute rate behind that follows you. so on a borderline case the real comparison is not refund versus keep the money, it is refund now versus possibly lose the same money later with a fee attached.
separate thing worth wiring in at the approve step: a refund usually has downstream money attached to it. affiliate commission, rev share, sales commission. if any of those were paid out on the original invoice, approving the refund in a form does not reverse them, and a refund issued by hand in the stripe dashboard will not either unless something on your side is listening for the event.
What stood out to me is that the workflow treats AI as a way to reduce interpretation effort rather than decision responsibility.
That boundary feels important. The more consequential the outcome, the more valuable it becomes to separate preparing a decision from actually making one.
Keeping AI out of the final refund decision is the right boundary. Summarization, classification, and drafting are relatively easy to review, but an approval decision depends on policy, customer history, usage data, and exceptions that may not fit clean rules.
One thing I’d add is an audit trail showing exactly which verified facts were available when the human made the decision. That would make it easier to review inconsistent decisions later and improve the rules without relying only on the AI summary.
Have you found a good way to handle policy exceptions without gradually turning the spreadsheet into a second, undocumented refund policy?
totally agree, a refund always holds a teachable moment.