Customers ask Apple for refunds, not you. Apple decides, and your server hears about it through App Store Server Notifications V2: CONSUMPTION_REQUEST when a customer asks for a refund and Apple wants your data, then REFUND if it's granted, REFUND_DECLINED if it's refused, and REFUND_REVERSED if a granted refund is later reversed. You can answer a consumption request with the Send Consumption Information endpoint, but only with the customer's consent and, per Apple, "within 12 hours". When a refund goes through, the transaction gets a revocationDate, and that is your signal to remove access. If you missed notifications, Get Refund History returns every approved refund for a customer.
How customers ask for a refund
Apple lists several ways, such as "Contacting Apple Customer Support and asking for a refund", using Apple's self-service site reportaproblem.apple.com, or "Asking their payment method issuer for a refund". Apps can also start a refund request inside the app with StoreKit's beginRefundRequest methods; the request still goes to Apple, which makes the decision.
The notifications
All of these arrive at the App Store Server Notifications V2 URL you set in App Store Connect. If nothing arrives, see App Store Server Notifications not arriving.
| notificationType | Apple's description | What to do |
|---|---|---|
| CONSUMPTION_REQUEST | The customer "initiated a refund request" and "the App Store is requesting that you provide consumption data." | If the customer consented, call Send Consumption Information within 12 hours. If not, don't respond. |
| REFUND | "the App Store successfully refunded a transaction" for a consumable, non-consumable, auto-renewable subscription or non-renewing subscription. | Remove what the transaction gave the customer. |
| REFUND_DECLINED | "the App Store declined a refund request." | Nothing to undo. |
| REFUND_REVERSED | "the App Store reversed a previously granted refund due to a dispute that the customer raised." | "If your app revoked content or services as a result of the related refund, it needs to reinstate them." |
| REVOKE | A purchase the customer had through Family Sharing (or from an organization) "is no longer available", including when "the purchaser receives a refund." | Remove access for that family member. |
Three related details from Apple's notification list:
- When a customer starts a refund from your app with the refund request API, Apple turns off auto-renew and you get DID_CHANGE_RENEWAL_STATUS with subtype AUTO_RENEW_DISABLED.
- REFUND_DECLINED is described in Apple's use-case table as a refund "that the customer initiated in the app, using the request refund API." Apple doesn't say whether it is also sent for requests made outside the app.
- For REFUND_REVERSED on an auto-renewable subscription, "the renewal date remains unchanged when the App Store reverses a refund."
The notification payload is a signed JWS. To read one while debugging, paste it into the App Store JWS decoder; it runs in your browser.
Which products get a CONSUMPTION_REQUEST
Apple's pages don't fully agree here, as read on 1 November 2026. The notificationType reference describes CONSUMPTION_REQUEST for "a consumable In-App Purchase or auto-renewable subscription", and so does the consumptionRequestReason page. The Send Consumption Information page says Apple sends it "When a customer initiates a refund request for any product type (consumable, non-consumable, non-renewing subscription, or auto-renewable subscription)", and the request body page says "You can provide consumption information for any type of product". In practice, handle the notification for every product type you sell.
The notification includes consumptionRequestReason, the customer's stated reason:
| Value | Meaning |
|---|---|
| UNINTENDED_PURCHASE | "The customer didn't intend to make the in-app purchase." |
| FULFILLMENT_ISSUE | "The customer had issues with receiving or using the in-app purchase." |
| UNSATISFIED_WITH_PURCHASE | "The customer wasn't satisfied with the in-app purchase." |
| LEGAL | "The customer requested a refund based on a legal reason." |
| OTHER | "The customer requested a refund for other reasons." |
Send Consumption Information
PUT https://api.storekit.apple.com/inApps/v2/transactions/consumption/{transactionId} (sandbox: api.storekit-sandbox.apple.com)
The transactionId is the one in the CONSUMPTION_REQUEST notification. Apple's rules:
- Deadline. "Respond within 12 hours of receiving the CONSUMPTION_REQUEST notification." Apple doesn't say what happens to a late reply.
- Consent first. "If the customer provided consent, respond by calling this API and sending the consumption data in the ConsumptionRequest to the App Store. If not, don't respond to the CONSUMPTION_REQUEST notification." Getting that consent is your job: "You, the developer, are solely responsible for obtaining valid consent".
- Not the tracking prompt. "Don't use the App Tracking Transparency prompt to obtain consent" for this; Apple calls the two "distinct and unrelated."
- Privacy label. If you adopt the endpoint, Apple says to answer the app privacy questions to disclose the data you collect and what it's used for.
- What it does. "The App Store uses the consumption information you provide to inform its refund decisions." It is one factor among "a variety of factors".
A successful call returns 202 Accepted. Other responses Apple lists: 400 (invalid request), 401 (bad JWT), 404 (transaction not found), 429 (rate limit) and 500 (try again later).
The request body (ConsumptionRequest)
| Field | Required | What it holds |
|---|---|---|
| customerConsented | Yes | true if the customer agreed to share consumption data. Anything other than true is rejected with HTTP 400 InvalidCustomerConsentedError. |
| deliveryStatus | Yes | DELIVERED, UNDELIVERED_QUALITY_ISSUE, UNDELIVERED_WRONG_ITEM, UNDELIVERED_SERVER_OUTAGE or UNDELIVERED_OTHER. |
| sampleContentProvided | Yes | true if, before the purchase, you offered "A free sample or free trial" or "Information about the content and how it works". |
| consumptionPercentage | No | How much the customer used, in milliunits: 40% is 40000, 100% is 100000. |
| refundPreference | No | DECLINE, GRANT_FULL or GRANT_PRORATED. |
Rules that make a request fail or change its meaning:
- Undelivered means zero. If deliveryStatus isn't DELIVERED, consumptionPercentage must be 0, or you get HTTP 400
UndeliveredConsumptionPercentageNonZeroError. - No percentage for auto-renewable subscriptions. Sending one fails with HTTP 400
ConsumptionPercentageAutoRenewableSubscriptionError; Apple works out the share for subscriptions itself "based on elapsed time." - GRANT_PRORATED needs a consumptionPercentage "greater than 0 and less than 100000" for consumables, non-consumables and non-renewing subscriptions.
GRANT_FULLandDECLINEwork for all product types. - Apple's example: if a transaction has a quantity of two consumables and one was fully used, consumptionPercentage is
50000.
Apple's ConsumptionRequest page, as read on 1 November 2026, lists only these five fields.
Get Refund History
GET https://api.storekit.apple.com/inApps/v2/refund/lookup/{anyTransactionId}
- Pass any
originalTransactionId,transactionIdorappTransactionIdthat belongs to the customer for your app. - It returns "App Store-approved refunds" for all product types, up to 20 per page, sorted by revocationDate. If
hasMoreis true, call again with?revision=and the token from the last response. - Apple says the information "is the same as the information in one or more REFUND notifications", and suggests the endpoint to "retrieve any refund notifications you may have missed, such as during a server outage."
- Apple suggests keeping the revision token from the last page so a later call returns only new refunds.
- An empty
signedTransactionsarray means the customer has no approved refunds.
Declined requests and reversed refunds aren't described as part of this response; Apple says it holds approved refunds.
Revoking access
A refunded transaction carries these fields in its signed payload (JWSTransactionDecodedPayload):
- revocationDate: "The UNIX time, in milliseconds, that the App Store refunded the transaction or revoked it from Family Sharing."
- revocationReason:
0means a refund "for other reasons, for example, an accidental purchase";1means "due to an actual or perceived issue within your app." - revocationType:
REFUND_FULL,REFUND_PRORATED,FAMILY_REVOKEorASSIGNMENT_REVOKE. - revocationPercentage: for a prorated refund, "The percentage, in milliunits, of the transaction that the App Store has refunded or revoked."
The rule is simple: if a transaction has a revocationDate, it no longer grants what it used to. On the device, StoreKit does this for you in one place: "Products that the App Store has refunded or revoked don't appear in the current entitlements." So an app that checks Transaction.currentEntitlements on launch drops a refunded non-consumable or subscription without extra code. Consumables never appear there, so for coins, credits or other balances kept on your server you have to subtract them yourself when REFUND arrives. Apple also suggests telling customers in the app about any action you take because of a refund.
What you can't control
- The decision. Apple decides. Your consumption data and refundPreference are inputs, and "The final refund percentage may differ from the value you provide."
- How refunds are requested. Customers can go to Apple support, reportaproblem.apple.com or their card issuer without involving you.
- Reversals. A refund can be reversed after a customer's dispute; you then have to restore access.
- Reasons. The only reason you get up front is consumptionRequestReason, and revocationReason after the fact.
Apple's pages don't say how long it takes to decide a refund, whether you can appeal one, or whether the refunded amount comes out of your proceeds in a specific way. They also don't promise that every refund request produces a CONSUMPTION_REQUEST.
FAQ
Do I have to answer CONSUMPTION_REQUEST?
No. Apple tells you not to respond if the customer hasn't consented. If you do answer, Apple asks for it within 12 hours.
Can I send consumption data without consent?
No. The App Store rejects any request where customerConsented isn't true, with HTTP 400.
I missed some REFUND notifications. How do I catch up?
Call Get Refund History with any transaction ID for that customer. Apple suggests it for notifications missed "such as during a server outage."
How do I know a transaction was refunded on the device?
It drops out of Transaction.currentEntitlements, and the transaction's revocationDate is set.
Does a reversed refund need any action?
Yes. If you removed access after REFUND, Apple says you need to reinstate it after REFUND_REVERSED.
Sources
All read on 1 November 2026.
- notificationType, App Store Server Notifications
- consumptionRequestReason, App Store Server Notifications
- Send Consumption Information, App Store Server API
- ConsumptionRequest, App Store Server API
- deliveryStatus, refundPreference, consumptionPercentage, sampleContentProvided, App Store Server API
- Get Refund History and RefundHistoryResponse, App Store Server API
- JWSTransactionDecodedPayload, revocationDate, revocationReason, revocationType, App Store Server API
- Handling refund notifications, StoreKit
- currentEntitlements, StoreKit
Apple's refund rules and API fields change; check the pages above for current details.