On November 4, Apple posted a short note titled "Now available: Retention messages for subscriptions." If your app sells an auto-renewable subscription, you can now show a message, an image or an offer to a subscriber who has tapped Cancel Subscription, before they confirm.
Within a day, a post on X was telling iOS developers that Apple had "just opened Retention Messaging API to all developers." That sentence mixes up two products, and the difference decides how much work you have ahead of you. One of them needs no server and is open to everyone with a subscription. The other needs a fast backend and still sits behind a request form.
This guide separates the two, walks through the App Store Connect setup, and covers the review rules most likely to get your first message rejected.
What opened and what didn't
Apple's announcement describes both products in two sentences: you configure retention messages in App Store Connect, and "API access is available by request." The WWDC26 session on the feature said the same thing in June. It called Retention Messaging in App Store Connect "open to all" and pointed developers who want the real-time version to an interest form. Apple's API documentation still labels the Retention Messaging API a pre-release.
| App Store Connect messages | Real-time Retention Messaging | |
|---|---|---|
| Access | Open to all developers with auto-renewable subscriptions | By request, through Apple's form |
| Server needed | No | Yes, an HTTPS endpoint that answers within 700 ms in production |
| Who picks the message | You assign one message per subscription, and the App Store picks the best eligible offer | Your server picks for each subscriber |
| Formats | Message, message with image, message with offer | The same three, plus a switch-plan message |
| Offer type | Retention offers | Promotional offers, signed by your server |
If you open App Store Connect, go to your app's Subscriptions page and see a Retention Messaging section, that section is the first column. You don't need to fill in Apple's form or call an API to use it. Most small teams should stop there for now.
What the subscriber sees
The message appears on the Confirm Cancellation screen, after the subscriber taps Cancel Subscription on a subscription details page. They can still cancel from that screen, or tap Keep Subscription, or redeem an offer if one is shown.
Which version they get depends on the offer setup. A subscriber who qualifies for an offer you attached sees your text and the offer. Everyone else sees your text and your image, or text alone if you added no image. An offer replaces the image, so an eligible subscriber will never see that image.
Apple's API page says messages are visible on iOS and iPadOS 15.1 or later, visionOS 1 or later, and macOS 14 or later. The App Store Connect help page doesn't list OS versions, so treat those numbers as the API's and confirm the App Store Connect case in sandbox if you support older devices.
What Apple's numbers mean at small scale
Apple defines save rate as the share of subscribers who keep their subscription after reaching the cancel confirmation page. In the WWDC26 session it said subscriptions using Retention Messaging saw an average increase of 1.4 percentage points, which it describes as an 82% rise. Promotional offer messages reached 5.5 points, described as a 223% rise. Apple also said results vary across developers.
The percentages sound large because the starting point is small. Working backward (this is my arithmetic, not Apple's figure), 1.4 points being an 82% rise implies a baseline save rate near 1.7%. So for every 1,000 people who reach that page, the average gain is about 14 subscribers kept, and about 55 with an offer message. That's a useful gain for a short setup, and it won't rescue an app with a churn problem. People arriving at this screen have mostly decided, and the two baselines Apple's figures imply also differ, which suggests the groups aren't directly comparable.
The rules that will get a first message rejected
Your text goes through App Review and has to meet the App Review Guidelines like other metadata. The help page is specific about three things.
Prices and offers can't appear in your header or body text. Apple's examples of banned wording are "$9.99," "50% off" and "one month free." The reason is that everyone sees this text, including subscribers who don't qualify for the offer, so a line promising a discount would be false for some readers. App Review rejects messages that do this. The offer card shows the offer details, so your text should stick to the value of the subscription.
Loss statements are allowed if they're factual. "You'll lose access to downloaded content when your subscription ends" is one of Apple's approved examples.
Coercion and unverifiable claims aren't. Apple's example of a bad claim is telling people that canceling a VPN will lead to a virus infection, and softer versions, such as saying a device becomes more susceptible to threats, are strongly discouraged. So are unsupported superlatives like "the best app" and statistics like "92% of parents report improved learning." Apple also recommends normal capitalization and punctuation over all caps and repeated exclamation marks.
Here's how that plays out for a made-up language learning app:
| Draft line | Problem | Better |
|---|---|---|
| Stay and get 50% off for 3 months! | Names an offer in the text | Your streak and saved vocabulary lists stay with your plan. |
| Don't throw away all your progress!!! | Pressure, and possibly untrue if progress survives cancellation | Offline lessons and review decks end with your subscription. |
| The #1 way to learn Spanish | Unverified superlative | New travel Spanish lessons arrive next month. |
That last line only works if the lessons really are arriving. Apple's own demo used this approach with a message about guided yoga launching next month, and an upcoming feature is a stronger reason to stay than a list of what already exists, because the subscriber has already seen the list and decided to leave.
The Retention Messaging API caps the header at 66 characters and the body at 144. The help page gives no limits for the App Store Connect form, so write to those lengths and let the form tell you if its limits differ.
Set it up in App Store Connect
You need the Account Holder, Admin, App Manager or Marketing role.
- Open your app and, under Monetization in the sidebar, click Subscriptions.
- Scroll to the Retention Messaging section. Click Get Started the first time, or the add button (+) after that.
- Enter a reference name. Subscribers never see it, so use something like "Annual plan, November."
- Enter header and body text in your primary language.
- Use the language menu to add a localization for every storefront where the subscription is sold.
- Add an image if you want one, from your Asset Library or as a new upload. Supported sizes are 3840 × 2160 and 5244 × 2950 pixels.
- In Subscriptions & Offers, choose the subscriptions that should show this message.
- Optionally click Add Retention Offer next to a subscription.
- Check the preview tool, including the None option in the Offer menu, which shows what ineligible subscribers get.
- Click Add for Review.
A few limits will affect how you plan this. An app can have 10 retention messages, and deleting one can't be undone. Each subscription can have only one message at a time, and if you add a subscription that already belongs to another message, it moves to the new one when you save. Check that list before saving, or you may pull a subscription off a message you meant to keep.
Editing a live message creates a new draft version, and the approved version keeps showing until App Review approves the draft. Once it's approved it replaces the old version, and you can't roll back. Keep a copy of your approved wording somewhere outside App Store Connect.
Also watch the Accepted status. It means your message passed review but something else in the same submission was rejected, and the message won't go live until every item is accepted or you remove the rejected item from the submission. Plenty of developers on X have complained this week about slow review queues, so leave yourself time if you're timing a message to a launch.
Retention offers without training people to cancel
Retention offers are a new offer type, separate from promotional offers. They only reach subscribers through a retention message, so one that isn't attached to a message does nothing. You can create up to 10 for each billing plan type on a subscription and attach all of them to a single message. When several apply, the App Store chooses the best offer for the eligible subscriber.
Setup asks for a reference name and an offer identifier, and neither can be changed afterward. Choose an identifier you can read in a sales report six months from now, such as retention_annual_3mo_free_v1. Then you set eligibility, the countries or regions, and the payment mode: Pay as you go, Pay up front or Free.
Two eligibility settings do most of the work:
- Paid Subscription Duration is the minimum time someone must have held a paid subscription before they qualify.
- Wait Between Offers is how long a subscriber must wait before redeeming the same offer again.
Both matter because this feature is now common knowledge among consumers. One iPhone tips account on X already suggested it on Thursday: start the cancel, see the offer, then decide. If your offer is generous and repeatable, some loyal subscribers will walk through the cancel flow every few months to claim it, and you'll give a discount to people who were never leaving.
There's a catch in Apple's wording. Wait Between Offers applies to each offer on its own, not across the subscription. If a subscriber qualifies for two different offers, they can take the second one without waiting. So the more offers you attach, the weaker your wait period gets. A small app should start with one offer, a real paid duration requirement and a long wait.
Before you pick a discount, write down what a saved subscriber has to do for it to pay off. As an illustration only, take a $10 monthly plan with a three-month free offer. You give up $30 of revenue from each person who redeems. Someone who would have canceled anyway and then stays for one paid month after the free period brings in $10 you wouldn't otherwise have had. Someone who would have stayed anyway costs you the full $30. The offer pays off only if what the first group pays after the free months outweighs what you gave away to the second, and you can't know that without tracking those subscribers over at least two renewal cycles.
Test it in sandbox and record redemptions
Apple says retention messages are fully testable in sandbox, and sandbox testers always see your latest version, including unpublished drafts. Cancel a sandbox subscription, confirm the message appears, then redeem the offer if you attached one.
On redemption, the signed transaction and renewal info carry a new offerType value of 5, along with the offer identifier, discount type and period. In StoreKit 2 the same information appears as Transaction.OfferType.retention. Your entitlement code shouldn't need a change, since the subscription stays active. What's worth adding is a record of the redemption, because otherwise you'll have no way to compare those subscribers later:
import StoreKit
func listenForTransactions() -> Task<Void, Never> {
Task.detached {
for await update in Transaction.updates {
guard case .verified(let transaction) = update else { continue }
if #available(iOS 17.2, *),
let offer = transaction.offer,
offer.type == .retention {
// Replace with your own analytics call.
print("Retention offer redeemed:",
offer.id ?? "unknown",
transaction.productID)
}
await transaction.finish()
}
}
}
Transaction.Offer requires iOS 17.2. Check the availability note on .retention in your own Xcode version before you ship, since it may need a newer SDK. If the offer spans renewal periods, it also shows up on the offer property of Product.SubscriptionInfo.RenewalInfo.
If you handle App Store Server Notifications, read the decoded transaction and don't rely on a notification type alone. Apple's notification tables list promotional offers, offer codes and win-back offers by name, and at the time of writing they don't list retention offers. Checking the value directly is safer:
# tx is the verified, decoded JWSTransactionDecodedPayload
RETENTION_OFFER = 5
def is_retention_redemption(tx: dict) -> bool:
return tx.get("offerType") == RETENTION_OFFER
Offer identifiers also appear in Sales and Trends reports, which gives you a usable view with no server at all.
How to measure it
RevenueCat's write-up notes that App Store Connect doesn't support A/B testing for these messages, and with one message per subscription you can't split users yourself. Your realistic option is a before and after comparison.
Record your monthly voluntary cancellation rate for the two months before the message goes live, then avoid other big changes during the first month after it. Don't launch a price change or a paywall redesign in the same window. For subscribers who took an offer, check how many are still paying after the offer ends. A subscriber who takes three free months and leaves on the first paid renewal cost you the offer and added nothing.
Small apps should be careful with these numbers. If 40 people reach the cancel screen in a month, Apple's average lift works out to less than one extra subscriber, so a single month of data can't tell you much. Give it a quarter, or run it for the plain reason that a good message costs nothing, and don't build a forecast on it.
When real-time messaging is worth asking for
Your server gets a signed request from the App Store when a subscriber views a subscription details page with a Cancel button. It includes the original transaction ID, the locale and other details, and you respond with a message, a switch-plan suggestion or a signed promotional offer.
Real-time messaging adds two things the App Store Connect version lacks. You can decide per subscriber, for instance by skipping the offer for someone who took one last quarter. And you can use the switch-plan format, which suggests a different plan in the same subscription group, including the monthly plan with a 12-month commitment.
The cost is real engineering. Apple requires a valid SSL certificate, TLS 1.2 and a response within 700 ms in production. You have to pass a performance test in sandbox before you can set a production URL, sign promotional offers on your server, and maintain sandbox and production messages separately. Messages need Apple's approval before they can be shown. If you don't already run a subscription backend, this is a lot of new surface for an app that hasn't yet measured the simple version.
Even if you go this way, set up App Store Connect messages first. When your server fails or times out, the system falls back to your App Store Connect message and any eligible offer. Default messages from the API come after that, and with neither configured, the subscriber sees no message at all.
A reasonable order of work
- Today: confirm the Retention Messaging section appears in your app's Subscriptions page, and note your current voluntary cancellation rate.
- Write one factual message per subscription group, with no prices. Base it on what the subscriber loses or on something you're about to ship.
- Localize it for every storefront you sell in.
- Submit the plain message first and let it run for a few weeks.
- Add one retention offer with a paid duration requirement and a long wait. Log redemptions in your app or on your server.
- After a quarter, look at who stayed past the offer period. Only then decide whether you need the real-time API.
If you're using a coding agent to wire up the logging, this is purchase code, so review the diff yourself and test it in sandbox before you ship. The Claude Code + Xcode: The Production iOS Workflow Kit is a set of Claude Code commands, agents and rules for iOS projects, with risk classification and human approval gates around areas such as payments. It helps with that kind of change, and its product page is clear that it can't guarantee correctness or App Store approval.
Sources
- Apple Developer News: Now available: Retention messages for subscriptions
- App Store Connect Help: Configure retention messages
- App Store Connect Help: Retention message statuses
- WWDC26: Explore Retention Messaging in App Store Connect
- Apple documentation: Retention Messaging API
- Apple documentation: Setting up your Get Retention Message endpoint
- Apple documentation: UploadMessageRequestBody
- Apple documentation: offerType
- Apple documentation: Transaction.OfferType
- Apple documentation: notificationType
- RevenueCat: Understanding Apple's Retention Messaging API
- @MoreOnApple on X, November 5, 2026

Comments