Все статьи
Подробный разбор8 мин чтения

Retention Messaging API от Apple выводит ваши слова на экран отмены, но запросы на возврат через него никогда не проходят

Retention Messaging API от Apple позволяет показать сообщение, смену тарифа или промо-предложение, когда подписчик нажимает «Отменить». Рассказываем, как это работает, сколько стоит в эксплуатации и почему запрос на возврат попадает в Apple, ни разу не коснувшись этого экрана.

Человек за столиком в кафе держит iPhone с открытым экраном настроек подписки, тот самый момент, для которого создан Retention Messaging API от Apple

Главное

  • Retention Messaging API от Apple позволяет разработчику выбрать сообщение, которое подписчик на iPhone увидит после нажатия Cancel Subscription. Типов четыре: текст, текст с изображением, предложение сменить тариф или промо-предложение.
  • Документация Apple по-прежнему описывает Retention Messaging API как предварительную версию, к которой разработчики просят доступ. Версия 1.0 вышла 16 июля 2025 года, версия 1.5 последовала 27 апреля 2026 года.
  • В режиме реального времени Apple вызывает эндпоинт Get Retention Message разработчика, когда активный подписчик открывает страницу с деталями подписки и кнопкой «Отменить». В продакшене эндпоинт должен ответить за 700 мс, иначе Apple покажет сообщение по умолчанию.
  • Сообщение об удержании влияет только на будущие продления. Запрос на возврат уходит в Apple через reportaproblem.apple.com или окно возврата внутри приложения, и экран отмены, где показываются сообщения об удержании, на этом пути не встречается.
  • Когда клиент запрашивает возврат внутри приложения через API запросов на возврат в StoreKit, Apple сам отключает автопродление и отправляет DID_CHANGE_RENEWAL_STATUS с подтипом AUTO_RENEW_DISABLED, то есть те же тип и подтип, что и при отмене на странице настроек Subscriptions.
  • Единственное, чем разработчик может повлиять на возврат в Apple, это CONSUMPTION_REQUEST: ответ через Send Consumption Information в течение 12 часов, и только если клиент согласился на передачу этих данных.
  • У Google Play нет документированного аналога сообщения на экране отмены, выбранного разработчиком. Разработчики получают уведомление SUBSCRIPTION_CANCELED постфактум, а поле userInitiatedCancellation сообщает, почему подписчик ушел.

Подписчикам, которые нажимают «Отменить» на iPhone, теперь можно до подтверждения показать выбранное вами сообщение, более дешевый тариф или скидку. Это Retention Messaging API от Apple, и впервые разработчик получает слово на собственном экране отмены Apple. Пока это предварительная версия, доступ к которой нужно запросить. И у нее есть жесткая граница, важная, если вам небезразличны возвраты: она обращается к людям, которые вот-вот перестанут платить, а не к тем, кто хочет вернуть деньги. Такие запросы попадают в Apple другим путем.

Что делает Retention Messaging API от Apple

Retention Messaging API работает по схеме «сервер к серверу». Вы заранее загружаете в Apple тексты сообщений и изображения, Apple их проверяет, а затем вы выбираете, какое одобренное сообщение увидит подписчик, собравшийся отменить автопродлеваемую подписку. Документация Apple называет четыре типа сообщений:

  • Текстовое сообщение, в котором могут быть пункты списка.
  • Текстовое сообщение с изображением.
  • Сообщение о смене тарифа, которое предлагает другую подписку из той же группы подписок.
  • Сообщение с промо-предложением, которое предлагает сниженную цену на том же или другом уровне с помощью промо-предложения, настроенного в App Store Connect и подписанного на вашем сервере.

Сообщение появляется после того, как клиент нажал Cancel Subscription (Отменить подписку) на странице с деталями подписки. Затем Apple показывает страницу Confirm Cancellation (Подтвердить отмену). Клиент по-прежнему может отменить подписку, нажать Keep Subscription (Сохранить подписку) или принять предложенные вами скидку или тариф. Спрятать выход нельзя, а Apple требует от разработчиков не загружать вводящий в заблуждение или неточный контент.

Сообщения по умолчанию и режим реального времени

Есть два способа работы. Простой: сообщения по умолчанию, то есть текст с изображением или пунктами либо без них, назначенный для каждого продукта и локали. Более гибкий: режим реального времени, в котором Apple вызывает эндпоинт Get Retention Message на вашем сервере, а вы отвечаете идентификатором сообщения. Только в режиме реального времени можно показывать сообщения о смене тарифа и с промо-предложениями.

На практике сообщения по умолчанию обязательны. Apple использует их как запасной вариант, когда вызов в реальном времени не удался, и вообще не показывает сообщение об удержании для продукта в любой локали, где нет сообщения по умолчанию.

ПараметрЧто говорит документация Apple
СтатусПредварительная версия, разработчики подают заявку на участие
ПродуктыАвтопродлеваемые подписки
Типы сообщенийТекст, текст с изображением, смена тарифа, промо-предложение
Лимит ответа в реальном времени700 мс в продакшене
Доступ к продакшенуСначала пройти тест производительности в песочнице, около 700 мс
Заголовок и пункты спискаПо 66 символов, не больше пяти пунктов
Основной текст144 символа
Альтернативный текст изображения150 символов
Сообщений на приложение2 000
ПроверкаНовые сообщения начинают со статуса PENDING и показываются только после статуса APPROVED
УстройстваiOS 15.1, iPadOS 15.1, visionOS 1, macOS 14 или новее

Что Apple сообщает вашему серверу при вызове в реальном времени

Запрос представляет собой JWS, подписанный App Store. После декодирования в нем есть originalTransactionId, appAppleId, productId, userLocale, UUID requestIdentifier, среда и signedDate. Apple велит проверять, что appAppleId совпадает с вашим приложением, и не отвечать, если не совпадает. Самое полезное здесь originalTransactionId: по нему можно посмотреть, что этот подписчик на самом деле делал в вашем приложении, прежде чем решить, что ему сказать.

Где появляется сообщение об удержании, а где нет

Apple показывает сообщение на одном экране: на шаге Confirm Cancellation после нажатия Cancel Subscription, например в Apple Account > Subscriptions или на странице подписки в App Store. Этот экран решает, состоится ли следующее продление. Уже полученных денег он не касается.

Запрос на возврат это отдельное действие. Страница поддержки Apple отправляет клиентов на reportaproblem.apple.com, где они выбирают «Request a refund» (Запросить возврат), указывают причину и покупку и ждут ответа от 24 до 48 часов. Внутри вашего приложения beginRefundRequest из StoreKit открывает окно возврата Apple, и, по словам Apple, App Store нужно до 48 часов, чтобы одобрить или отклонить запрос. Ни один из этих путей не проходит через экран Confirm Cancellation.

МоментГде это происходитЧто на конуКто решаетВаше участие
ОтменаСтраница с деталями подписки, затем Confirm CancellationБудущие продленияКлиентВыбранное вами сообщение об удержании, ответ за 700 мс
Запрос на возвратreportaproblem.apple.com или окно возврата в вашем приложенииУже уплаченные деньгиAppleДанные для CONSUMPTION_REQUEST в течение 12 часов, если клиент дал согласие

Может ли сообщение об удержании остановить запрос на возврат?

Нет. Запрос на возврат никогда не доходит до экрана, где находится сообщение. Одна деталь в документации Apple по уведомлениям делает это наглядным. Когда клиент запрашивает возврат в вашем приложении через API запросов на возврат, Apple сам отключает автопродление и отправляет DID_CHANGE_RENEWAL_STATUS с подтипом AUTO_RENEW_DISABLED. Клиент, который отменяет подписку на странице настроек Subscriptions, порождает те же тип и подтип. Ваш сервер видит одно уведомление для двух совершенно разных клиентов, и только один из них видел ваше сообщение об удержании.

Если запрос на возврат идет дальше, канал для доказательств это CONSUMPTION_REQUEST. Apple присылает его при запросах на возврат по любому типу продукта, и у вас есть 12 часов, чтобы ответить через Send Consumption Information. Отвечать можно только при согласии клиента. После этого решение Apple приходит уведомлением REFUND или REFUND_DECLINED, если Apple отклоняет возврат, запрошенный клиентом в вашем приложении.

Есть ли у Google Play API для сообщений при отмене?

Не согласно документации Google о жизненном цикле подписок. Подписчик Google Play отменяет подписку в центре подписок Play, сохраняет доступ до конца текущего платежного периода и до тех пор может нажать Resubscribe (Подписаться снова), чтобы все вернуть. Google называет это восстановлением. Вы узнаете об отмене постфактум из уведомления SUBSCRIPTION_CANCELED, а поле userInitiatedCancellation в ресурсе подписки сообщает, почему пользователь ушел. Пауза, которая, по словам Google, включена по умолчанию для всех подписок, это главный встроенный способ сократить добровольный отток.

Со стороны возвратов у Google Play свой канал для доказательств. PendingRefundReviewNotification приходит, когда чарджбэк требует проверки разработчиком, и у вас есть 24 часа, чтобы ответить через orders.reviewrefund. По заказам, оформленным после 3 августа 2026 года, при удовлетворенном чарджбэке Google перекладывает на разработчика цену покупки за вычетом сервисного сбора Play, а также комиссии банка за чарджбэк.

Сколько денег стоит вам экран отмены

Retention messaging кажется бесплатным. Это не так, и счета приходят из трех мест.

Вычисления при каждом просмотре страницы

Apple вызывает ваш эндпоинт, когда активный подписчик открывает страницу с деталями подписки и кнопкой «Отменить», а не только когда он отменяет. Каждый визит это запрос, который ваш сервер должен аутентифицировать, обработать и ответить на него за 700 мс, иначе Apple покажет сообщение по умолчанию. Это исключает функцию с холодным стартом, которой иногда нужно две секунды. Вы платите за постоянно прогретые мощности плюс за все чтения из базы данных и платные вызовы сторонних API, которые ваша логика принятия решений делает на каждый запрос.

Разработчик за столом следит за графиками времени ответа сервера на мониторе рядом с ноутбуком и iPhone, именно такой постоянно доступный эндпоинт ожидает Retention Messaging API от Apple

Скидка это выручка, от которой вы отказались сами

Промо-предложение, которое удержало подписчика, это реально сохраненные деньги. Предложение тому, кто и так остался бы, это чистая скидка. Вот иллюстрация, а не эталонный показатель. Месячный тариф за 9,99 $ с предложением половинной цены на три месяца теряет 14,99 $ на каждом принятом предложении. Если каждый третий из принявших остался бы и по полной цене, тысяча принятий обходится примерно в 5 000 $ скидки людям, которым она была не нужна. По другую сторону баланса стоят подписчики, которые действительно уходили.

Возврат, который провоцирует неприятный выход

Apple оставляет кнопку Cancel Subscription на странице, так что удержать человека в ловушке нельзя, но раздражать все еще можно. У клиента, на которого давят, есть другой вариант: попросить Apple вернуть последний платеж. Когда возврат происходит, деньги уходят обратно, а вычисления, хранение, вызовы API и любые партнерские выплаты, связанные с этим подписчиком, остаются потраченными. Эти расходы не вернет ни одно сообщение об удержании.

Как пользоваться retention messaging, не повышая долю возвратов

Относитесь к экрану отмены как к месту для точности, а не для хитрости. Несколько правил удерживают его на правильной стороне границы возвратов:

  • Решайте для каждого подписчика отдельно. По originalTransactionId из запроса Apple посмотрите недавнее использование. Скидку или более дешевый тариф предлагайте тем, кто пользуется продуктом. Тем, кто не открывал его неделями, покажите короткое честное сообщение.
  • Отвечайте быстро. Рассчитывайте решение заранее, когда меняются данные об использовании, чтобы сам запрос был одним поиском, который с запасом укладывается в 700 мс.
  • Напишите сообщение по умолчанию для каждого продукта и локали. Без него неудачный вызов означает, что сообщения не будет вовсе.
  • Внимательно следите за AUTO_RENEW_DISABLED. Если следом приходит CONSUMPTION_REQUEST для того же originalTransactionId, перед вами запрос на возврат, а не отмена, и 12-часовой отсчет уже пошел.
  • Отвечайте на каждый CONSUMPTION_REQUEST, на который вам разрешено ответить. RefundHalt отправляет Apple точные данные о потреблении в 12-часовом окне и отвечает на проверку чарджбэка в Google Play в течение 24 часов, потому что это единственные два момента, когда магазины спрашивают вашу позицию.

Стоит ли просить у Apple доступ?

Если вы продаете автопродлеваемые подписки и уже обрабатываете App Store Server Notifications V2, скорее всего, да. Экран отмены это последнее место, где можно достучаться до подписчика перед уходом, а смена тарифа обходится дешевле, чем потеря его целиком. Просто заложите бюджет на эндпоинт, который отвечает при каждом просмотре страницы подписки, и держите защиту от возвратов там, где возвраты действительно происходят.

Частые вопросы

Что такое Retention Messaging API от Apple?
Это API по схеме «сервер к серверу», которое позволяет разработчику выбрать сообщение, которое подписчик увидит после нажатия Cancel Subscription в автопродлеваемой подписке. Apple поддерживает четыре типа: текст, текст с изображением, предложение сменить тариф и промо-предложение. Документация Apple по-прежнему описывает его как предварительную версию, к которой разработчики просят доступ.
Как быстро должен отвечать мой эндпоинт Get Retention Message?
За 700 мс в продакшене. Если ваш сервер медленнее или дает сбой, Apple показывает сообщение по умолчанию, настроенное для этого продукта и локали, а если его нет, не показывает ничего. Кроме того, нужно пройти тест производительности в песочнице, около 700 мс, прежде чем Apple позволит указать URL для продакшена.
Появляется ли сообщение об удержании, когда клиент запрашивает возврат?
Нет. Apple показывает сообщения об удержании на экране Confirm Cancellation после нажатия Cancel Subscription. Запросы на возврат идут через reportaproblem.apple.com или окно возврата в приложении, которое открывает beginRefundRequest, и единственное участие разработчика там это CONSUMPTION_REQUEST с ответом в течение 12 часов, если клиент дал согласие.
Как отличить запрос на возврат от отмены в App Store Server Notifications?
Только по уведомлению о продлении не получится. Отмена на странице настроек Subscriptions и запрос на возврат через ваше приложение дают одно и то же: DID_CHANGE_RENEWAL_STATUS с подтипом AUTO_RENEW_DISABLED. CONSUMPTION_REQUEST по той же транзакции, а позже уведомление REFUND или REFUND_DECLINED показывают, что идет запрос на возврат.
Позволяет ли Google Play разработчикам показывать сообщение при отмене подписки?
Документация Google о жизненном цикле подписок ничего такого не описывает. Разработчики получают уведомление SUBSCRIPTION_CANCELED постфактум и могут прочитать поле userInitiatedCancellation, чтобы узнать причину отмены. Пауза, включенная по умолчанию для всех подписок, это главный встроенный инструмент Google Play против добровольного оттока.

Источники и дополнительное чтение

RefundHalt

Автопилот возвратов для App Store и Google Play

Читайте дальше

Следующий запрос на возврат уже в пути.

Настройте RefundHalt за то время, что уходит на чтение очередного письма в поддержку о возврате, который вы не успели оспорить.