What does the App Store notification DID_CHANGE_RENEWAL_STATUS mean?

The App Store notification DID_CHANGE_RENEWAL_STATUS means the customer changed whether their subscription renews automatically.

Quick facts#

Notification notificationType DID_CHANGE_RENEWAL_STATUS
Where App Store Server Notifications v2 (responseBodyV2DecodedPayload)
Sent by The App Store server, to your notification URL
What Apple says The customer changed the subscription's renewal status. AUTO_RENEW_ENABLED means auto-renew was turned on; AUTO_RENEW_DISABLED means it was turned off, by the customer or by the App Store after a refund request.

What triggers it#

  • Subtype AUTO_RENEW_DISABLED: the customer cancelled from the App Store Subscriptions page, or the App Store turned off auto-renew after the customer started a refund through your app's refund request API.
  • Subtype AUTO_RENEW_ENABLED: the customer subscribed again after cancelling, which turns auto-renew back on.
  • Apple also sends it without a subtype when the customer cancels after a price increase notice.

What your server should do#

  1. Verify the signedPayload with Apple's App Store Server Library (SignedDataVerifier.verifyAndDecodeNotification) before you act on anything in it.
  2. Keep access until expiresDate: the customer paid for the period.
  3. On AUTO_RENEW_DISABLED, start your win-back flow. Apple suggests this notification as one input for deciding who is eligible for a promotional offer.
  4. On AUTO_RENEW_ENABLED, stop the win-back flow.
  5. Answer HTTP 200 (any code from 200 to 206) once you have stored the notification. Apple retries other answers five times, at 1, 12, 24, 48 and 72 hours after the previous attempt, so make your handler safe to run twice (the payload carries a notificationUUID).

Example#

JavaScript
// Run on the decoded payload, after you verified Apple's signature.
const notification = {"notificationType":"DID_CHANGE_RENEWAL_STATUS","subtype":"AUTO_RENEW_DISABLED","data":{"environment":"Sandbox","bundleId":"com.example.app"}};

function decide(n) {
  if (n.notificationType !== "DID_CHANGE_RENEWAL_STATUS") return "ignore";
  if (n.subtype === "AUTO_RENEW_DISABLED") return "keep access to the end of the period, start win-back";
  if (n.subtype === "AUTO_RENEW_ENABLED") return "stop win-back";
  return "check the renewal info";
}

console.log(decide(notification));

Run-checked: npm run check:snippets runs this snippet with Node and compares its output with start win-back (checked 2026-10-03).

How RevenueDot handles it#

RevenueDot verifies Apple's signature, checks the bundle ID, stores the notification and answers 200. A purchase RevenueDot has not seen is applied only when the app's Track new purchases from server-to-server notifications setting is on. Type overrides set auto-renew from the subtype. Turning it off gives a CANCELLATION event with cancel_reason: UNSUBSCRIBE (or the store's reason, or BILLING_ERROR when a billing issue exists); turning it back on gives UNCANCELLATION. Access is not touched, so no EXPIRATION is sent until the period ends.

Source#

Checked: 2026-10-03

Edit this page on GitHub ↗ View as Markdown Last updated