Unexpected appAccountToken mutation in JWSRenewalInfo during in-app crossgrade

Hello Apple Developer Support / StoreKit Team,

We recently observed a behavior regarding the appAccountToken in App Store Server Notifications v2 that seems to completely contradict the official documentation.

According to the Set App Account Token documentation:

The same appAccountToken continues to apply to renewal transactions if the customer upgrades, downgrades, or cross-grades the subscription.

However, we encountered a scenario where an active in-app crossgrade resulted in an updated/overwritten appAccountToken inside the subsequent JWSRenewalInfoDecodedPayload, despite our backend never calling the Set App Account Token REST API.

Our Observation:

  1. A user subscribes to our 1-month plan (Product A). Apple generates an originalTransactionId bound to their initial appAccountToken (Token A).

  2. Later, a crossgrade to a 1-year plan (Product B) is initiated from within the app while the user is logged into a different account in our system (Token B), but using the same underlying Apple ID on the device.

  3. When the crossgrade takes effect at the next renewal date, we receive a DID_RENEW webhook.

The Anomaly (See Attached Screenshots): Upon decoding the JWSRenewalInfoDecodedPayload from the webhook, we noticed that the appAccountToken had unexpectedly changed to the new token (Token B).

As shown in the attached redacted screenshots:

Screenshot 1 (Before/Original): JWSRenewalInfoDecodedPayload for Product 00001 shows the appAccountToken ending in ...e9a.

Screenshot 2 (After Crossgrade): JWSRenewalInfoDecodedPayload for Product yearly_saver shows the appAccountToken has mutated to ending in ...507, even though the originalTransactionId remains exactly the same.

To reiterate, our server did not call the POST /inApps/v1/subscriptions/appAccountToken/{originalTransactionId} endpoint to manually overwrite this token at any point.

Our Questions:

  1. Is this the intended StoreKit 2 behavior? Does Apple automatically overwrite the base appAccountToken in the RenewalInfo if a new token is somehow associated during an active in-app crossgrade transaction?

  2. If this is intended, could the documentation be clarified? The current phrasing strongly suggests the token is permanently locked to the initial purchase and will never change during crossgrades unless the REST API is explicitly called.

While this behavior is actually quite helpful for our backend to track multi-account users, we want to ensure we aren't relying on an undocumented bug that might be patched unexpectedly.

Any insights from the StoreKit engineering team would be highly appreciated. Thank you!

Please submit a feedback assistant ticket at (http://feedbackassistant.apple.com). Please provide as much information as possible, ie a sysdiagnose, app apple ID, in-app apple IDs, sandbox account apple ID (if applicable), transactions IDs, steps to reproduce and other relevant details.

  • File ticket under iOS & iPadOS, macOS, tvOS, watchOS, or visionOS and ensure you select “App Store” for the question “Which area are you seeing an issue with?”
  • Categorize the type of feedback
  • Please attach all available files needed to verify
  • please re-replicate the behavior and share a timestamp, when it was observed

After submitting the feedback, please regularly check the ticket as we'll only communicate through it from then on.

Once you open the Feedback Assistant Ticket report, please post the FB number here for reference.

If you have any questions about filing a report, take a look at Bug Reporting: How and Why (https://developer.apple.com/forums/thread/712889)?

Unexpected appAccountToken mutation in JWSRenewalInfo during in-app crossgrade
 
 
Q