Developer Console

Receipt Verification for Tiered Subscriptions

Use Real-Time Notifications (RTN) and Receipt Verification Service (RVS) together to help detect and validate tier changes:

  • With RTN, you can detect the subscription tier or term change made by your app's users.
  • With RVS, you can validate purchases made by your app's users.

RTN for tiered subscriptions

Real-Time Notifications provides real-time server push notifications when a change in tier occurs. The following table provides details about tier change notifications.

Notification Type Description
SUBSCRIPTION_MODIFIED_DEFERRED A subscription plan was modified with the "deferred" proration mode. The subscription plan is scheduled to change at the next renewal date. The current plan remains active until the renewal date.
SUBSCRIPTION_MODIFIED_IMMEDIATE A subscription plan was modified with the "immediate" proration mode. The existing plan is canceled with a prorated refund, and the new plan is activated immediately. The notification includes the canceled receipt ID.

Capture these events with RTN and use RVS to verify the change in subscription. For a complete list of notification types, see Supported Notification Types.

Example RTN responses

Amazon handles plan changes differently based on whether they are immediate or deferred.

  • For immediate plan changes:
    • Amazon cancels the current plan and activates the new one immediately.
    • Amazon marks the current receipt ID as canceled.
    • The relatedReceipts field of the RTN payload includes the canceled receipt ID.
  • For deferred plan changes:
    • The current receipt remains active and Amazon schedules the plan change for the upcoming billing cycle.
    • The relatedReceipts field in the RTN payload is an empty array.

The following examples show RTN responses for the SUBSCRIPTION_MODIFIED_IMMEDIATE and SUBSCRIPTION_MODIFIED_DEFERRED notification types.

Example for SUBSCRIPTION_MODIFIED_IMMEDIATE

{
  "Type" : "Notification",
  "MessageId" : "723acf52-cb22-57f5-b13e-afa29908f61d",
  "TopicArn" : "arn:aws:sns:us-east-1:033616359524:MyTopic",
  "Message" : "{\"appPackageName\":\"com.example.amazonsdkapivalidator3\",\"notificationType\":\"SUBSCRIPTION_MODIFIED_IMMEDIATE\",\"appUserId\":\"io9oFdzmCSMuKk_pp9pYccoIHRfc6kSAAYaNo51xZrg=\",\"receiptId\":\"R4TWNm8Uspo4Ujio51B5_7xBnRFzr4B2k9Bv48_7mRY=:3:11\",\"relatedReceipts\":{"cancelledReceiptId": "IgThFebRSngPTn9JntrLMby52NqMjyMMQnrUFlczwV0=:3:11"},\"timestamp\":1752584166563,\"betaProductTransaction\":false}",
  "Timestamp" : "2025-07-15T12:56:10.667Z",
  "SignatureVersion" : "1",
  "Signature" : "EXAMPLEw6JRN...",
  "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-9c6465fa7f48f5cacd23014631ec1136.pem",
  "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:033616359524:MyTopic:3c2cebb7-5dc3-4eca-9d55-4e8922144131"
}

Here is a closer look at the contents of the Message field in JSON format.

{
  "appPackageName": "com.example.amazonsdkapivalidator3",
  "notificationType": "SUBSCRIPTION_MODIFIED_IMMEDIATE",
  "appUserId": "io9oFdzmCSMuKk_pp9pYccoIHRfc6kSAAYaNo51xZrg=",
  "receiptId": "R4TWNm8Uspo4Ujio51B5_7xBnRFzr4B2k9Bv48_7mRY=:3:11",
  "relatedReceipts": {
    "cancelledReceiptId": "IgThFebRSngPTn9JntrLMby52NqMjyMMQnrUFlczwV0=:3:11"
  },
  "timestamp": 1752584166563,
  "betaProductTransaction": false
}

Notice the relatedReceipts field includes the canceled receipt ID. For an immediate plan change, Amazon immediately cancels the current plan and activates the new one.

Example for SUBSCRIPTION_MODIFIED_DEFERRED

{
  "Type" : "Notification",
  "MessageId" : "64140cd1-13e4-57d8-baf6-6c2141c2646f",
  "TopicArn" : "arn:aws:sns:us-east-1:033616359524:MyTopic",
  "Message" : "{\"appPackageName\":\"com.example.amazonsdkapivalidator3\",\"notificationType\":\"SUBSCRIPTION_MODIFIED_DEFERRED\",\"appUserId\":\"io9oFdzmCSMuKk_pp9pYccoIHRfc6kSAAYaNo51xZrg=\",\"receiptId\":\"PnkS4FtcuGLylYyc_vNjrN_ucm9hhaur43iCacRAd14=:3:11\",\"relatedReceipts\":{},\"timestamp\":1752584161620,\"betaProductTransaction\":false}",
  "Timestamp" : "2025-07-15T12:56:06.409Z",
  "SignatureVersion" : "1",
  "Signature" : "EXAMPLEw6JRN...",
  "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-9c6465fa7f48f5cacd23014631ec1136.pem",
  "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:033616359524:MyTopic:3c2cebb7-5dc3-4eca-9d55-4e8922144131"
}

Here is a closer look at the contents of the Message field in JSON format.

{
  "appPackageName": "com.example.amazonsdkapivalidator3",
  "notificationType": "SUBSCRIPTION_MODIFIED_DEFERRED",
  "appUserId": "io9oFdzmCSMuKk_pp9pYccoIHRfc6kSAAYaNo51xZrg=",
  "receiptId": "PnkS4FtcuGLylYyc_vNjrN_ucm9hhaur43iCacRAd14=:3:11",
  "relatedReceipts": {},
  "timestamp": 1752584161620,
  "betaProductTransaction": false
}

Notice the relatedReceipts array is empty. For a deferred plan change, Amazon maintains the existing receipt and schedules the plan change for the upcoming billing cycle.

RVS for tiered subscriptions

Set up RVS for tiered subscription apps the same as you would for any other app. For more details, see Receipt Verification Service for Appstore SDK IAP.

For apps with tiered subscriptions, RVS uses an additional cancelReason response code for canceled subscriptions.

Cancel reason response codes

The cancelReason response code is a long integer that indicates why a product is canceled. Possible values are null, 0, 1, 2, or 4, where each integer represents a cancellation reason, described in the following table.

cancelReason Code Description
null The purchase is not canceled.
0 The cancel reason is currently unavailable and renders at a later time.
1 Your customer canceled the order.
2 Amazon's system canceled the purchase. For example, a customer purchases a subscription with invalid payment and the purchase isn't completed in the grace period.
4 The subscription is replaced with a new subscription. For example, if a customer moves to a new tier, the original receipt is canceled and a new receipt is provided.

You can find a complete list of response fields in the RVS documentation.

Example RVS response

The following code is an example of a full RVS response.

{
 "autoRenewing":false,
 "betaProduct":true,
 "cancelDate":1400784371000,
 "cancelReason":4,
 "countryCode":"US",
 "freeTrialEndDate":null,
 "gracePeriodEndDate":null,
 "parentProductId":null,
 "productId":"sub1",
 "productType":"SUBSCRIPTION",
 "purchaseDate":1400784241000,
 "quantity":null,
 "receiptId":"JyGJ5iEtYgFu1ngnQovTqSIHQxR53GsMLqkR1tKLp5c=:3:11",
 "renewalDate":null,
 "term":"1 Week",
 "termSku":"sub1-weekly",
 "testTransaction":true
}

The cancelReason indicates that the app has changed to a different tier, which cancels the previous subscription.

For more RVS examples, see RVS Examples for Appstore SDK IAP.


Last updated: Jul 22, 2025