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 的退款自動駕駛
繼續閱讀
三天內不確認 Google Play 購買,Google 就會退款,這會讓你付出什麼代價
只要你的伺服器在三天內沒有確認某筆購買,Google Play 就會自動退款並撤銷這筆購買。這是整合失誤,不是客戶的決定,而且完全可以避免。下面講清楚具體規則、它為什麼會觸發,以及每一筆流失的銷售真正的代價。
連環退款濫用讓你損失兩次,以下是應用商店給你的反擊方法
一次又一次申請退款的客戶並非偶然。退款濫用不僅讓你退回金額,還要搭上你已經花掉的算力,而兩大商店都會給你一個身分訊號,即 Apple 的 appAccountToken 和 Google 的混淆帳戶 ID,用來把這種模式串連起來。