did_change_renewal_pref

Learn about the DID_CHANGE_RENEWAL_PREF App Store Server Notification V2. Fired when a customer upgrades or downgrades their subscription plan.

App Store Server Notifications V2Subscriptions
did_change_renewal_pref

The DID_CHANGE_RENEWAL_PREF notification fires when a customer changes which product they'll renew into — typically an upgrade or downgrade within the same subscription group.


When does it fire?


This notification triggers when a customer selects a different subscription tier:


  • Upgrade (subtype UPGRADE) — the customer switched to a higher-priced tier (takes effect immediately)
  • Downgrade (subtype DOWNGRADE) — the customer switched to a lower-priced tier (takes effect at next renewal)

Payload highlights


The signed renewal info shows the new product ID the customer will renew into, along with the current product ID. For upgrades, you'll also receive a new transaction since upgrades are effective immediately.


How Yeethook helps


Plan changes directly impact your revenue. Yeethook formats these events to clearly show what plan the customer is switching from and to, so your team can track upgrade and downgrade trends.


Common use cases


  • Monitor upgrade rates to measure the effectiveness of upsell prompts
  • Track downgrade trends to identify pricing or value issues
  • Alert your revenue team when high-value subscribers downgrade
  • Analyze plan migration patterns across your subscriber base

Example payload

The decoded body of a downgrade. The plan the customer is moving to is not in this object — it is autoRenewProductId inside signedRenewalInfo, so the switch only becomes visible after decoding that inner JWS.

{
  "notificationType": "DID_CHANGE_RENEWAL_PREF",
  "subtype": "DOWNGRADE",
  "notificationUUID": "e58c0b34-6f27-49da-b915-2c7e8a04f6d3",
  "version": "2.0",
  "signedDate": 1789457612000,
  "data": {
    "appAppleId": 1234567890,
    "bundleId": "com.example.app",
    "bundleVersion": "142",
    "environment": "Production",
    "signedTransactionInfo": "eyJhbGciOiJFUzI1NiIsIng1YyI6...",
    "signedRenewalInfo": "eyJhbGciOiJFUzI1NiIsIng1YyI6...",
    "status": 1
  }
}

What it looks like in Slack

Info

Plan downgrade

Product
com.example.app.pro.yearly
Transaction
2000000823456789
Expires
2027-03-04T18:13:32.000Z
Auto-renew
On
Renewing to
com.example.app.pro.monthly
Subscription status
Active
Environment
Production

The same event arrives with different values depending on what changed. Yeethook rewrites the headline to match:

  • UPGRADE→ Plan upgrade
  • (no subtype)→ Plan changed

Questions about did_change_renewal_pref

When does a downgrade actually take effect?

At the next renewal date. autoRenewProductId changes straight away, which is why Yeethook can show a Renewing to row, but productId in the transaction stays on the current plan until expiresDate passes and the cheaper product bills.

Does an upgrade create a new transaction immediately?

Yes. Upgrades take effect at once, so Apple bills the new plan, refunds the unused portion of the old one prorated, and the subtype is UPGRADE. That is the practical reason to branch on the subtype rather than treat every plan change the same way.

Why did I get this event with no subtype at all?

Reverting a pending change sends DID_CHANGE_RENEWAL_PREF with autoRenewProductId back to the current product and no subtype, which Yeethook posts as the neutral headline "Plan changed". It is the signal that a scheduled downgrade was cancelled.

Can a customer change plans across subscription groups?

No. Renewal preference changes only work between products in the same subscription group, so a move to a product in another group is a separate purchase and arrives as SUBSCRIBED rather than as a preference change.

Get this event in Slack or Discord

Connect Yeethook to receive did_change_renewal_pref notifications in your team's Slack or Discord channels.

Get Started Free