Возврат через Advanced Commerce API остаётся единственным способом, которым iOS-разработчик может инициировать возврат, и окончательное решение всё равно за Apple
Большинство iOS-разработчиков не могут вернуть деньги клиенту. Приложения на Advanced Commerce API от Apple могут запросить возврат, отозвать подписку или вернуть произвольную сумму. Разбираем, как работает каждый endpoint, в чём Apple всё ещё может отказать и где теряются деньги.

Главное
- В июне 2026 года инженер Apple заявил, что разработчик не может напрямую оформить возврат за обычную покупку в App Store. Единственное, что может сделать разработчик, это отправить данные о потреблении и refundPreference в ответ на CONSUMPTION_REQUEST.
- Приложения, одобренные для Advanced Commerce API от Apple, получают endpoint Request Transaction Refund, который просит App Store вернуть деньги за разовый платёж или транзакцию подписки, а также endpoints Revoke Subscription и Cancel a Subscription.
- Чтобы вызывать endpoints Advanced Commerce API для возврата, отзыва и отмены, Account Holder разработчика должен подписать Advanced Commerce API Addendum. По словам Apple, если последняя версия не принята, вызов вернёт ошибку.
- Endpoint Request Transaction Refund принимает refundType со значением FULL, PRORATED или CUSTOM, а refundAmount в тысячных долях денежной единицы допускается только с CUSTOM. По словам Apple, сумма должна включать налог во всех регионах, кроме Канады и США.
- Поле refundRiskingPreference по умолчанию равно true. Это позволяет App Store отправить CONSUMPTION_REQUEST по запросу на возврат, который подал сам разработчик. Apple просит ответить в течение 12 часов.
- Endpoints Advanced Commerce API для возврата, отзыва и отмены ограничены в продакшене 5 запросами в секунду на приложение, а в sandbox доступно 10 процентов от этого лимита.
- После успешного вызова Revoke Subscription Apple отправляет уведомление REFUND и предписывает прекращать доступ с даты revocationDate, но не раньше, чем придёт уведомление.
Обычные iOS-разработчики не могут вернуть деньги клиенту. В июне 2026 года App Store Commerce Engineer ответил на вопрос на форуме разработчиков одной фразой: в настоящее время разработчик не может напрямую оформить возврат. Есть одно исключение, и оно находится внутри Advanced Commerce API. Приложения, которые Apple к нему допускает, могут отправить запрос на возврат через Advanced Commerce API, отозвать подписку с возвратом денег или запросить произвольную сумму. Переводить ли деньги, по-прежнему решает Apple.
Что такое Advanced Commerce API и кто его получает
Apple выпустила Advanced Commerce API 23 января 2025 года. Он обрабатывает встроенные покупки Apple для исключительно больших каталогов: произвольных разовых покупок, подписок и подписок с дополнительными опциями. Вы не создаёте каждый продукт в App Store Connect. Вы определяете SKU на своём сервере и передаёте их Apple в момент покупки.
Доступ выдаётся отдельно для каждого приложения. Вы заполняете форму заявки, а страница Apple о соответствии требованиям называет три бизнес-модели, которые должны быть основой приложения:
- Исключительно большие каталоги разовых покупок, например аудиокниги, занятия, курсы или мини-приложения.
- Исключительно большие каталоги контента по подписке, где предложение каждого автора является отдельной подпиской.
- Подписка с дополнительными опциями, которые продлеваются вместе как одна покупка, например премиальные каналы или спорт.
Apple также разрешает подать заявку, если API требуется для другой программы. Его требует Mini Apps Partner Program, которая выплачивает участникам 85% от соответствующих продаж встроенных покупок в размещённых мини-приложениях.
Endpoints для возвратов появились позже, и для них нужна подпись
Версия 1.1 от 24 марта 2025 года добавила Request Transaction Refund и Revoke Subscription. Страница программы Apple говорит, что приложения с контентом по подписке также могут получить право на API Cancel, Revoke и Refund, чтобы обрабатывать отмены, проверять контент после покупки и управлять каталогами. Страница каждого endpoint добавляет одно и то же условие: ваш Account Holder должен подписать Advanced Commerce API Addendum, а если последняя версия не принята, вызов вернёт ошибку. Сценарии использования каждого endpoint перечислены в Addendum, а не в документации.
Три endpoint рядом
| Cancel a Subscription | Revoke Subscription | Request Transaction Refund | |
|---|---|---|---|
| Путь | advancedCommerce/v1/subscription/cancel/{transactionId} | advancedCommerce/v1/subscription/revoke/{transactionId} | advancedCommerce/v1/transaction/requestRefund/{transactionId} |
| Охват | Автопродлеваемые подписки | Подписка и все её позиции | Разовые платежи и транзакции подписок |
| Возврат денег | Нет | FULL или PRORATED | FULL, PRORATED или CUSTOM, по каждому SKU |
| Доступ | Сохраняется до конца периода | Прекращается в revocationDate | Задаётся для каждой позиции флагом revoke |
| Лимит в продакшене | 5 в секунду | 5 в секунду | 5 в секунду |
Cancel a Subscription останавливает следующее списание
Cancel отключает автопродление. По словам Apple, клиент сохраняет доступ до конца текущего периода. Ничего не возвращается. Это правильный вызов, когда клиент хочет уйти и уже использовал оплаченное время.
Revoke Subscription прекращает всё сразу
Revoke устанавливает автопродление в false и отзывает подписку с полным или пропорциональным возвратом. Тело запроса содержит refundReason, refundRiskingPreference, refundType и requestInfo. Затем Apple отправляет уведомление REFUND на ваш endpoint App Store Server Notifications V2. Указание Apple конкретное: отключайте доступ с даты revocationDate из этого уведомления и не отключайте его до того, как уведомление придёт.
Request Transaction Refund работает по позициям
Это точный инструмент. Вы отправляете список позиций, и в каждой указаны SKU, refundReason, refundType и флаг revoke. С CUSTOM вы также передаёте refundAmount в тысячных долях денежной единицы, то есть 4990 означает 4,99. Если отправить сумму с FULL или PRORATED, Apple отклонит запрос с ошибкой 4000155. Ответ содержит подписанную транзакцию, а для подписок ещё и подписанные данные о продлении.
Apple принимает такие значения refundReason: UNINTENDED_PURCHASE, FULFILLMENT_ISSUE, UNSATISFIED_WITH_PURCHASE, LEGAL, OTHER и MODIFY_ITEMS_REFUND. Седьмое значение, SIMULATE_REFUND_DECLINE, предназначено только для тестирования в sandbox и TestFlight. Оно существует потому, что App Store может отказать.
Apple может отклонить даже ваш собственный запрос на возврат
Название endpoint честное. Это запрос. Два поля показывают, где на самом деле принимается решение.
refundRiskingPreference открывает дорогу проверке потребления
Apple описывает refundRiskingPreference как признак того, запросит ли App Store у вас данные о потреблении для решения о возврате. По умолчанию значение true. Если оно true, вы получаете CONSUMPTION_REQUEST по собственному запросу на возврат и отвечаете через Send Consumption Information. Apple просит разработчиков ответить в течение 12 часов после получения CONSUMPTION_REQUEST. Установите false, и это уведомление не придёт.
Ошибки, которые означают отказ
| Ошибка | Код | Что говорит Apple |
|---|---|---|
| AlreadyRefundedError | 4030021 | По транзакции уже сделан возврат |
| PendingRefundError | 4000181 | По транзакции есть ожидающие возвраты |
| TransactionNotRefundableError | 4030024 | Транзакция не подлежит возврату |
| TransactionCannotBeRefundedContactSupportError | 4030025 | Клиент может обратиться в Apple Support |
| RefundAmountWithoutCustomError | 4000155 | Сумма отправлена без CUSTOM |
К PendingRefundError нужно готовиться заранее. Вероятная причина: клиент уже обратился к Apple через Report a Problem до того, как отреагировала ваша поддержка. Правила Apple и так требуют, чтобы у этих приложений был путь к возврату внутри приложения, ссылка Report a Problem или API beginRefundRequest, поэтому обе двери открыты одновременно.

Во сколько вам обходится возврат через Advanced Commerce API
Вернуть деньги по своей инициативе кажется дешевле, чем спорить. Но это всё равно расход, а API позволяет легко повторять некоторые ошибки в больших масштабах.
Налог внутри произвольной суммы
По словам Apple, запрошенный refundAmount должен включать налог во всех регионах, кроме Канады и США. Команда, которая рассчитывает возврат CUSTOM от цены SKU без налога, недоплатит клиентам во всех остальных витринах, а потом потратит время поддержки на исправление каждого случая.
Расходы, которые не возвращаются
- Выплаты: в каталоге авторов или у хоста мини-приложений доля автора часто выплачивается при продаже. Возврат клиенту её не вернёт.
- Лицензии на контент: отчисления правообладателю за аудиокнигу или курс могут, в зависимости от договора, начисляться уже при доступе, и возврат их не отменяет.
- Вычисления: стриминг, транскодирование и вся серверная работа по покупке уже в вашем счёте.
- Вызовы API: сторонние сервисы с оплатой за запрос, от распознавания речи до инференса моделей, остаются оплаченными после возврата.
Полный возврат, когда имелась в виду одна позиция
Revoke Subscription возвращает деньги и прекращает всю подписку вместе с дополнительными опциями. Если клиент оспаривает только одну опцию, Request Transaction Refund позволяет вернуть только этот SKU, с флагом revoke лишь для этой позиции. Вызов Revoke Subscription из-за жалобы на одну позицию возвращает и выручку за базовый тариф.
Чек-лист перед включением
- Убедитесь, что ваш Account Holder принял текущую версию Advanced Commerce API Addendum, и настройте оповещение на ошибку, которая приходит, когда принятие истекает.
- Генерируйте новый requestReferenceId в формате UUID для каждого запроса и используйте тот же повторно только при повторе вызова, завершившегося по тайм-ауту.
- Ставьте вызовы возвратов в очередь. Лимит составляет 5 в секунду на приложение, а ответ 429 содержит заголовок Retry-After в миллисекундах UNIX.
- Тестируйте отказы в sandbox с SIMULATE_REFUND_DECLINE и помните, что лимиты sandbox составляют 10 процентов от продакшена.
- Решайте вопрос с refundRiskingPreference в каждом случае отдельно и держите наготове обработчик данных о потреблении на 12-часовое окно, если значение остаётся true.
- Прекращайте доступ только после прихода уведомления REFUND, с его revocationDate.
- Записывайте причину, сумму и SKU каждого запроса, чтобы видеть собственную долю возвратов раньше, чем её увидит Apple.
Частые вопросы
- Может ли iOS-разработчик напрямую вернуть деньги клиенту?
- Не за обычную покупку в App Store. В июне 2026 года инженер Apple заявил, что разработчик не может напрямую оформить возврат. Приложения, одобренные для Advanced Commerce API и подписавшие Addendum, могут запросить его через endpoint Request Transaction Refund, но решение всё равно принимает Apple.
- Чем Cancel отличается от Revoke в Advanced Commerce API?
- Cancel отключает автопродление, и клиент сохраняет доступ до конца периода, без возврата. Revoke сразу прекращает подписку и все её позиции и возвращает полную или пропорциональную сумму. После Revoke Apple отправляет уведомление REFUND.
- Можно ли вернуть произвольную сумму через Advanced Commerce API?
- Да. Установите refundType в CUSTOM и передайте refundAmount в тысячных долях денежной единицы. По словам Apple, сумма должна включать налог во всех регионах, кроме Канады и США, а отправка суммы с FULL или PRORATED возвращает ошибку 4000155.
- Получу ли я CONSUMPTION_REQUEST по возврату, который запросил сам?
- Можете получить. refundRiskingPreference по умолчанию равно true, поэтому App Store может запросить у вас данные о потреблении через CONSUMPTION_REQUEST, и Apple просит ответить в течение 12 часов. Установите false, и, по словам Apple, это уведомление не будет отправлено.
- Почему мой запрос на возврат через Advanced Commerce API не прошёл?
- Проверьте код ошибки. 4030021 означает, что по транзакции уже сделан возврат, 4000181 означает, что возврат уже ожидает обработки, 4030024 означает, что транзакция не подлежит возврату, а 4030025 означает, что клиенту следует обратиться в Apple Support. Неподписанный или устаревший Addendum тоже приводит к ошибке.
Источники и дополнительное чтение
- Apple Developer: Advanced Commerce API eligibility and requirements
- Advanced Commerce API: Request Transaction Refund
- Advanced Commerce API: RequestRefundItem
- Advanced Commerce API: refundRiskingPreference
- Advanced Commerce API: Revoke Subscription
- Advanced Commerce API: Rate limits
- Advanced Commerce API changelog
- App Store Server API: Send Consumption Information
- Apple Developer Forums: Refund option in App Store Server API
- Apple Developer: Mini Apps Partner Program
RefundHalt
Автопилот возвратов для App Store и Google Play
Читайте дальше
Чрезмерные запросы на возврат обходятся дороже самих возвратов: оба магазина приложений считают их сигналом качества
Правило 5.6.4 Apple прямо называет чрезмерные запросы на возврат признаком того, что приложение не соответствует стандартам качества, а соглашение Google о распространении позволяет удалять приложения новых разработчиков по доле возвратов. Разбираем, что пишет каждый магазин, во что обходится удаление и как не попасть под удар.
Проверяйте серверные уведомления App Store, прежде чем реагировать на возврат, ведь отправить запрос на ваш URL вебхука может кто угодно
Уведомление о возврате остается обычным HTTPS-запросом, пока вы не проверили его подпись. Рассказываем, как проверять серверные уведомления App Store и сообщения RTDN из Google Play, что подписывает каждый магазин и во что обходится поддельный или ошибочно отклоненный возврат.