Highlight
Apple adds Retention Messaging to App Store Connect, letting developers show retention messages and offers when users cancel subscriptions. It also opens the Real-time Retention Messaging API, allowing a server to return personalized messages, downgrade options, or promotional offers during the real-time cancellation request. Apps already using this feature saw average save rate increase by 82%, and promotional-offer mode increased it by 223%.
Core Content
Anyone who builds a subscription app shares the same pain: a user silently opens system settings and cancels, and you never get a chance to speak. Previously, you could only place a “manage subscription” entry inside the app, but users who truly intend to cancel usually never go through your flow.
This year Apple opens the cancellation confirmation step in the subscription management page. (00:15)
Static configuration in App Store Connect: start with no backend
For developers without a backend team, or who do not want to write code, Retention Messaging can be configured directly in App Store Connect. Open the subscription management page, click “Get Started” to create a retention message, enter a title and description, choose an image from Asset Library, and bind it to specific subscription products. One message can be associated with multiple subscriptions, and you can configure multiple Retention Offers. The App Store automatically chooses the best offer for eligible users. (02:43)
After configuration, when a user taps cancel subscription, the system shows your configured message on the cancellation confirmation page. Apple’s data is direct: apps using Retention Messaging increased average save rate by 1.4 percentage points, an 82% relative lift. When paired with promotional offers, save rate increased by 5.5 percentage points, a 223% relative lift. (02:06)
Real-time Retention Messaging: precise personalization
For teams with backend capabilities, the main feature is Real-time Retention Messaging. When a user taps cancel, the App Store sends an HTTP request to your server. Your server can use user data to decide in real time what to show. (06:48)
Real-time responses support three formats:
- Return a message, with text only or text plus an image.
- Return a downgrade option (
alternateProduct) that recommends another product in the same subscription group. - Return a promotional offer (
promotionalOffer) with a time-limited discount.
With this mode, you can use activity level, usage duration, payment history, and other data to decide whether to discount, recommend a lower-priced plan, or simply show a reminder message. This is much smarter than sending the same coupon to everyone. (08:57)
Three-level fallback mechanism
The real-time interface has strict response-time requirements. If your server times out or returns an error, the App Store falls back in this order: (10:10)
- Use the real-time response first.
- Fall back to static Retention Messaging configured in App Store Connect.
- Finally fall back to the default message configured through the Retention Messaging API.
This means users will not see a blank page even if the real-time interface has a problem.
Details
Retention Messaging API endpoint overview
The real-time feature is served through https://api.storekit.apple.com/inApps/v1/messaging, with these core endpoints: (07:50)
// URL configuration
PUT /realtime/url // Set the real-time callback URL
GET /realtime/url // Query the current URL
DELETE /realtime/url // Delete the URL
// Message configuration
PUT /message/{messageIdentifier} // Create or update a message
DELETE /message/{messageIdentifier} // Delete a message
GET /message/list // List all messages
PUT /default/{productId}/{locale} // Set the default message
DELETE /default/{productId}/{locale} // Delete the default message
GET /default/{productId}/{locale} // Query the default message
// Image configuration
PUT /image/{imageIdentifier} // Upload an image
DELETE /image/{imageIdentifier} // Delete an image
GET /image/list // List all images
// Performance test (Sandbox only)
POST /performanceTest // Start a performance test
GET /performanceTest/result/{requestId} // Query test results
Key points:
- All configuration operations are server-to-server and do not require client participation.
- Messages, images, and default configurations are independent and can be combined flexibly.
- The Sandbox environment must pass
/performanceTestbefore Production can be enabled.
Real-time request format from the App Store
When a user taps cancel, the App Store sends the following JSON to your callback URL: (08:34)
{
"originalTransactionId": "123456789",
"appAppleId": 6745974591,
"productId": "Yoga_summer_2026",
"userLocale": "en-US",
"requestIdentifier": "c03248af-dd76-4e9b-9c1e-4489cd19a768",
"environment": "Production",
"signedDate": 1780920000000
}
Key points:
originalTransactionIdlocates the user’s subscription record.userLocaletells you which language to use in the response.requestIdentifieris used for tracing and debugging.environmentdistinguishes Sandbox from Production.
Response format 1: return a message
{
"message": {
"messageIdentifier": "551ee7c0-c097-418e-9dd5-2a98533a7390"
}
}
Key points:
messageIdentifiermust already be configured throughPUT /message/{id}.- A message can show text alone or pair it with an image uploaded through
PUT /image/{id}. - If the same message is also configured in App Store Connect, the two remain consistent.
Response format 2: return a downgrade product
{
"alternateProduct": {
"messageIdentifier": "ed7f25fc-5741-46a3-8502-062e0fb8afd0",
"productId": "Yoga_summer_2026_annual"
}
}
Key points:
productIdmust be in the same Subscription Group as the subscription being canceled.- When the user taps it, they switch directly to the new product without going through purchase again.
- This is useful for users who “do not need premium features”; you keep the user’s LTV with a lower-priced plan.
- The new 12-month commitment monthly payment plan in iOS 26.5 can also be specified through the
billingPlanTypefield. (11:11)
Response format 3: return a promotional offer
{
"promotionalOffer": {
"messageIdentifier": "80135e2b-ae15-4ec4-8c5c-9ecc8045c0dc",
"promotionalOfferSignatureV2": "eyJhbGciOiJFUzI..."
}
}
Key points:
- You must use the V2 promotional offer signature. V1 signatures do not work.
- Signature generation follows the StoreKit 2 specification.
- This is suitable for high-value users who are about to churn, using a time-limited discount for precise retention.
Identify Retention Offer transactions
When a user accepts a retention offer, the transaction contains new markers: (06:08)
{
"bundleId": "com.example.app",
"productId": "Yoga_summer_2026",
"type": "Auto-Renewable Subscription",
"transactionReason": "RENEWAL",
"offerType": 5,
"offerIdentifier": "Yoga_2026_cancel_free_3m",
"offerDiscountType": "FREE_TRIAL",
"offerPeriod": "P3M",
"originalTransactionId": "1000011859217"
}
Key points:
offerType: 5is the new Retention Offer type.- Previously,
offerTypeonly had values 1-4, so backend parsing logic needs an enum update. offerIdentifier,offerDiscountType,offerPeriod, and related fields match regular offers.
Comparing the two approaches
| Dimension | Static configuration in App Store Connect | Real-time Retention Messaging |
|---|---|---|
| Decision method | App Store chooses automatically | Developer controls in real time |
| Configuration entry | App Store Connect or ASC API | Retention Messaging API |
| Offer type | Retention Offer | Promotional Offer |
| View support | Message / image / offer | Message / image / offer / downgrade option |
| Server required | No | Yes |
| Performance requirement | None | Must pass Sandbox performance test |
(11:52)
Key Ideas
1. Configure static first, then move to real time
Teams without a backend, or with limited backend resources, should first configure static Retention Messaging in App Store Connect. Apple’s data already shows that even a text-only message can increase average save rate by 82%. This is zero code, zero cost, and should be done immediately.
- What to build: Configure one retention message and one image for each subscription product in ASC.
- Why it is worth doing: No development cost, with direct access to the 82% save-rate lift.
- How to start: Open App Store Connect > Subscriptions > Retention Messaging > Get Started.
2. Use alternateProduct for smart downgrades
Do not offer a discount every time someone cancels. Analyze why the user is cancelling. If the reason is “I do not need premium features,” return a lower-priced basic subscription in the same group. This preserves LTV and avoids training users to expect a discount whenever they cancel.
- What to build: Return
alternateProductin the real-time response based on user profile data. - Why it is worth doing: It is more elegant than discounting and causes less margin loss.
- How to start: Create a lower-priced tier in the subscription group, then configure a downgrade message through the Retention Messaging API.
3. Cache user profiles in Redis
The real-time interface is extremely latency-sensitive. Do not query a database or third-party service after receiving the request. Precompute user activity, payment history, usage preferences, and similar data, store it in Redis, and return directly from cache using originalTransactionId.
- What to build: A low-latency retention decision service.
- Why it is worth doing: The performance test is a launch gate, and latency directly affects user experience.
- How to start: Use
originalTransactionIdas the key and pre-warm user profile data into cache.
4. Combine with Win-back for a full lifecycle loop
Retention Messaging intercepts users who are cancelling right now. Win-back brings back users who already cancelled. Together they close the subscription lifecycle loop.
- What to build: Use Retention to intercept during cancellation and Win-back to recover users after cancellation.
- Why it is worth doing: Covers both critical churn moments in the subscription lifecycle.
- How to start: Launch Retention Messaging first, then integrate Win-back Offer.
Related Sessions
- What’s new in Apple In-App Purchase - Learn about the new 12-month commitment monthly payment plan in iOS 26.5, and how Retention Offers appear in transactions.
- Enhance your presence on the App Store - Learn how to use Asset Library. Images for Retention Messaging are reused directly from Asset Library.
- App Intents: What’s new - If your app supports Siri or Shortcuts, combine App Intents with subscription management through voice.
- What’s new in StoreKit - Understand StoreKit 2’s transaction model and promotional offer signature mechanism in depth.
Comments
GitHub Issues · utterances