How to handle App Store refund requests (and the consumption request)
How App Store refunds work for subscriptions: who decides, the CONSUMPTION_REQUEST notification, what to send Apple in 12 hours, and what to do next.
On the App Store, you never issue a subscription refund yourself and you never answer a card dispute. Apple is the merchant: it takes the payment, it decides on refunds, and it deals with the customer’s bank. What you can do is narrower but still useful: tell Apple how the customer actually used what they paid for, react correctly when a refund goes through, and spot patterns of abuse.
This guide covers that process for auto-renewable subscriptions. It sticks to Apple’s own documentation, mainly Send Consumption Information, the ConsumptionRequest body, the notificationType reference and Get Refund History (all accessed November 2026).
How customers ask for a refund
Apple’s guide to handling refund notifications lists the ways a customer can ask for their money back:
- contacting Apple Customer Support;
- using Apple’s self-service site, reportaproblem.apple.com;
- asking their payment method issuer for a refund.
There is a fourth route you control: your app can open Apple’s refund sheet with StoreKit’s beginRefundRequest(in:). Apple suggests calling it from account settings or a help menu. The sheet shows the purchase and a list of reasons, and Apple’s documentation says the App Store takes up to 48 hours to approve or deny the request.
Whatever the route, the decision is Apple’s. You have no button to approve or decline.
The notifications you will receive
If you have App Store Server Notifications V2 set up, refunds produce a small set of events:
| Notification | What it means |
|---|---|
CONSUMPTION_REQUEST |
A customer started a refund request and Apple asks you for consumption data |
REFUND |
Apple refunded a transaction |
REFUND_DECLINED |
Apple declined a refund request |
REFUND_REVERSED |
Apple reversed a refund it had granted, because of a dispute the customer raised |
DID_CHANGE_RENEWAL_STATUS with AUTO_RENEW_DISABLED |
Among other cases, the system turned off auto-renew because the customer requested a refund through your app |
REVOKE |
Access through Family Sharing or a group ended, for example because the purchaser was refunded |
The CONSUMPTION_REQUEST payload carries a consumptionRequestReason with the reason the customer gave. Apple documents five values: UNINTENDED_PURCHASE, FULFILLMENT_ISSUE, UNSATISFIED_WITH_PURCHASE, LEGAL and OTHER. Store it. Over time it tells you whether refunds come from accidental purchases, from bugs, or from people who simply did not like the product.
Answering the consumption request
Apple says it “uses a variety of factors” to decide on a refund, and that the consumption information you send is one of them. It is your only way to put facts in front of the reviewer.
The rules
Apple’s documentation is strict on three points:
- Consent first. You may only send data if the customer consented to share it with Apple. If they did not, Apple says not to respond to the
CONSUMPTION_REQUESTat all. The server rejects any request wherecustomerConsentedis nottruewith an HTTP 400 error. - 12 hours. Respond within 12 hours of receiving the notification.
- Consent is your job. Apple states that you are “solely responsible for obtaining valid consent”, that it must be freely given, specific, informed and unambiguous, and that you must not use the App Tracking Transparency prompt for it. If you adopt the API, you also have to disclose the data use in your app privacy details.
The request
You call PUT https://api.storekit.apple.com/inApps/v2/transactions/consumption/ followed by the transaction ID from the notification. The ConsumptionRequest body has five fields:
| Field | What to put in it |
|---|---|
customerConsented |
true, the only value Apple accepts |
deliveryStatus |
DELIVERED, or one of UNDELIVERED_QUALITY_ISSUE, UNDELIVERED_WRONG_ITEM, UNDELIVERED_SERVER_OUTAGE, UNDELIVERED_OTHER |
consumptionPercentage |
How much was consumed, in milliunits. Must be 0 if the item was not delivered |
refundPreference |
Optional: GRANT_FULL, GRANT_PRORATED or DECLINE |
sampleContentProvided |
Whether you offered a free sample, trial or description of the functionality before purchase |
For auto-renewable subscriptions, one constraint matters: if you choose GRANT_PRORATED, do not send consumptionPercentage. Apple calculates the percentage itself for subscriptions.
Choosing what to say
Be honest, because it is the right thing to do and because Apple gets the last word anyway. A simple rule set:
- The app failed (outage, broken feature, content never unlocked): set the matching
UNDELIVERED_*status, a consumption of 0, andGRANT_FULL. Fighting a refund for something that did not work is pointless. - Accidental purchase, no usage:
DELIVERED, 0 or near 0 consumption, andGRANT_FULLor no preference. - Real, sustained usage over the period:
DELIVEREDandDECLINEorGRANT_PRORATED, depending on your policy. - Free trial before the paid period: set
sampleContentProvidedtotrue.
The numbers must come from your own usage data, measured the same way for every customer. That means you need usage tied to the App Store transaction, which in practice means setting an appAccountToken at purchase so you can map Apple’s transaction to your user.
When a refund goes through
A REFUND notification means the money is gone. Apple’s notification reference says the transaction’s revocationDate holds the refund timestamp and revocationReason holds the reason. There are two reason values:
0: refunded for other reasons, for example an accidental purchase;1: refunded because of an actual or perceived issue within your app.
Practical steps:
- Revoke access for the refunded transaction, and say so in the app with a short message. Apple’s guide recommends “contextual messaging in the app for any actions you take as a result of the refund.”
- Record the reason. A rising share of reason
1is a product signal, not a billing one. - Watch for reversals. If a
REFUND_REVERSEDarrives, Apple says you need to reinstate the content or service. For auto-renewable subscriptions, the renewal date stays unchanged. - Backfill missed events. Get Refund History returns a customer’s App Store-approved refunds, 20 per page, and Apple suggests it for recovering refund notifications missed during an outage.
What about chargebacks?
Customers can ask their card issuer for a refund, but on the App Store the dispute is between the bank and Apple. You will not receive dispute evidence requests and there is nothing to submit. What you will see is the outcome: a REFUND if the money went back, and REFUND_REVERSED if Apple reversed a refund after a customer dispute.
So the “chargeback work” for an iOS app is mostly prevention and detection:
- Make the refund path inside your app easy to find (the
beginRefundRequestsheet), so unhappy customers use it instead of their bank. - Answer every consumption request you are allowed to answer, on time.
- Map refunds to accounts. Apple’s guide suggests mapping
REFUNDnotifications to your user accounts to “identify repeated refunded purchases” and suspicious activity.
Common mistakes
- Sending data without consent. It is rejected by the API and it breaks Apple’s rules.
- Missing the 12-hour window. Process
CONSUMPTION_REQUESTin a queue with an alert, not in a nightly batch. - Always sending
DECLINE. Your preference is only one factor, and claiming usage you cannot back up does not help. - Not revoking after a refund, or not restoring after a reversal.
- No link between Apple transactions and your users. Without
appAccountTokenyou cannot measure consumption, and you cannot answer.
Doing this with NoChurn
NoChurn reads your App Store Server Notifications, so refund requests, refunds, declines and reversals appear on each customer’s timeline with the reason Apple gave. When Apple sends a consumption request for a customer who consented, NoChurn can answer it with that customer’s real usage from your data, within Apple’s window. Refunds also feed the churn score. Apple keeps the payment, the refund decision and anything involving the customer’s bank; NoChurn never pretends otherwise. Setup and limits are on NoChurn + App Store.