Apple's CONSUMPTION_REQUEST, explained: the 12 hours that decide your refund
When a customer asks Apple for a refund, Apple asks you first. Here's exactly what the CONSUMPTION_REQUEST notification contains, what Apple expects back, how to answer one end to end, and why most developers silently forfeit.
要点
- When a customer requests an App Store refund, Apple sends your server a CONSUMPTION_REQUEST notification and waits up to 12 hours for evidence before deciding.
- You respond by calling the Send Consumption Information endpoint with a small payload: consent, delivery status, sample content, consumption percentage, and your refund preference.
- Silence is an answer: if you send nothing, Apple decides from the customer's claim and account history alone.
- Consent is a hard gate. Apple's documentation says that without the customer's consent to share consumption data, you should not respond at all.
- For auto-renewable subscriptions Apple calculates the consumption percentage itself from elapsed time; sending your own value returns an error.
- The window is too short for a manual process. The developers who benefit are the ones whose response is generated and submitted automatically.
Here is what this whole mechanism is about: Apple decides every App Store refund itself, but it does not want to decide blind. So it built a formal channel for your side of the story. When a customer requests a refund, Apple pauses, sends your server a question, and gives you a fixed window to answer with facts about the purchase. Answer well and unreasonable requests get declined. Ignore it and Apple rules on the customer's word alone.
Every App Store refund starts the same way: a customer opens reportaproblem.apple.com, picks a purchase, and taps a reason. What most developers don't know is what happens next — Apple turns to you and asks for evidence before it decides.
The notification nobody answers
If your app has App Store Server Notifications V2 configured, Apple sends a CONSUMPTION_REQUEST notification the moment the refund is requested. The payload names the transaction, the product, and — since 2024 — the customer's stated reason: UNINTENDED_PURCHASE, FULFILLMENT_ISSUE, UNSATISFIED_WITH_PURCHASE, LEGAL, or OTHER.
From that moment you have 12 hours to call the Send Consumption Information endpoint with your side of the story. The current payload is deliberately small: five fields, numbers and flags only.
| Field | What it tells Apple | Example |
|---|---|---|
| customerConsented | The customer agreed that usage data may be shared | true |
| deliveryStatus | Whether the purchase was delivered and works | DELIVERED |
| sampleContentProvided | A free sample or trial existed before purchase | true |
| consumptionPercentage | How much of the purchase was used, 100% = 100000 | 67500 |
| refundPreference | Your preference: decline, grant, or no preference | DECLINE |
What Apple does with your answer
Apple explicitly uses consumption information as an input to its refund decision. Send nothing and the decision is made entirely from the customer's claim and account history. Send evidence — '87 scans in six days' reads very differently from silence — and contested refunds are frequently declined.
How to answer one yourself, end to end
If you want to build the response path in-house, this is the full sequence. None of it is secret; all of it has to work at 3 a.m.
1. Get the notification flowing
In App Store Connect, open your app's App Information page and set a Production Server URL under App Store Server Notifications, on Version 2. V1 does not carry consumption requests. Apple will now POST every notification, refunds included, to that URL as a signed JWS payload.
2. Create the right key
Responses are authenticated with an In-App Purchase key from Users and Access, under Integrations. This is its own key type: the App Store Connect API key next to it will not work. You download the .p8 once, then mint a short-lived ES256 JWT for every call.
3. Verify, match, decide
When the CONSUMPTION_REQUEST arrives, verify the JWS signature chain against Apple's root certificates before trusting a byte of it. Then match the transaction to your user, ideally through the appAccountToken UUID you attached at purchase, and pull their real usage. Decide your preference: grant the goodwill cases, contest the consumed ones.
4. Send it back in time
PUT your five fields to the Send Consumption Information endpoint for that transaction id, within the 12-hour window. Two traps catch almost everyone: the percentage is in milliunits, so 100% is 100000, not one million; and consent is a gate, because Apple's own documentation says that without customer consent you should not respond at all. Add the consent language to your terms of service before you ship any of this.
Why developers forfeit
Twelve hours is a brutal window for a human process. The notification can land at 3 a.m. on a Saturday. It requires a server that verifies Apple's JWS signature chain, matches the transaction to a user, computes a consumption percentage in milliunits, and calls a JWT-authenticated API — per request, every time, forever.
The practical checklist looks like this:
- Configure App Store Server Notifications V2 so the request reaches you at all.
- Verify the signed payload against Apple's certificate chain before trusting it.
- Match the transaction to your own user, usually through the appAccountToken you attached at purchase.
- Compute a consumption percentage from real usage, not guesswork.
- Call Send Consumption Information with an In-App Purchase key before the window closes.
That's the entire reason RefundHalt exists: the response is generated and submitted in seconds, from real usage data when you connect it, with your policy applied — grant the goodwill cases, contest the rest. The 12-hour window stops being a threat and becomes your home-field advantage.
常见问题解答
- What happens if I never respond to a CONSUMPTION_REQUEST?
- Apple still decides the refund, but only from the customer's claim and account history. You lose the only opportunity to show that the purchase was delivered and heavily used. In practice unanswered requests are approved far more often.
- Do I need the customer's consent to send consumption data?
- Yes. Apple requires that customerConsented is true, and that you actually obtained that consent, typically through your terms of service or privacy policy. Apple's documentation says that without consent you should not respond to the notification at all.
- Can I send a consumption percentage for subscriptions?
- Only for non-renewing subscriptions. For auto-renewable subscriptions Apple calculates consumption from elapsed time in the current billing period and the API rejects a supplied percentage. Your evidence still drives the refund preference.
- Which key do I use to call the API?
- An In-App Purchase key, created in App Store Connect under Users and Access, Integrations. It is a different key type from the App Store Connect API key, and the .p8 file can only be downloaded once, at creation.
- How fast do I really need to answer?
- Apple's production window is 12 hours from the notification. In the sandbox environment it is only 5 minutes, which is a hint about the direction Apple expects: an automated response, not a human one.
来源和延伸阅读
RefundHalt
App Store 和 Google Play 退款自动驾驶
继续阅读
儿童未经授权的应用内购买几乎每次都会退款给家长,而成本由你承担
当孩子在家长的手机上购买一个金币包时,Apple 和 Google 都会退款,而且都不会先征询你的意见。监管机构就是这样设计的。下面介绍这些未经授权的应用内购买退款在每个商店如何运作、资金流失的那 15 分钟窗口,以及一次退款到底会让你付出多少代价。
应用退款税从来不是你的,所以退款损失的是你的那一份,而不是收据上的总额
为一笔应用内购买办理退款,收据上会显示价格加税一并退回。那笔税从来都不是你的钱。Apple 和 Google 作为登记商户负责收取并上缴,退款时再以同样方式冲回,完全不动你的那一份。这篇讲清楚一笔退款到底损失多少,以及唯一一种让税变成你责任的设置。