Обновление листинга Play Store через Google Play Developer API
edits.insert), меняешь текст листинга и изображения внутри него (edits.listings.update, edits.images.upload), затем вызываешь edits.commit, чтобы проверить и опубликовать изменения — или edits.abandon, чтобы отменить их. Ничего не публикуется до commit. Авторизация выполняется через сервисный аккаунт Google Cloud, и есть один шаг, на котором спотыкаются почти все: сервисный аккаунт нужно пригласить именно в Play Console, а не просто назначить ему роль в Google Cloud IAM.Google Play Developer API (его официальное название — Android Publisher API) позволяет менять листинг в сторе — название, описания, скриншоты, feature graphic — не открывая Play Console. Это то, что нужно, если ты отправляешь локализованные тексты из CMS, синхронизируешь скриншоты из билд-пайплайна или обновляешь листинги на десятках языков сразу. Ниже — полный процесс, как сделать это правильно, включая нюансы, которые в официальной документации спрятаны глубоко.
Edit — это транзакция, а не набор прямых изменений
Модель, которая избавит тебя от большинства проблем: ты никогда не редактируешь живой листинг напрямую. Ты открываешь edit — приватную черновую копию текущего опубликованного состояния приложения: листинги, изображения, треки — всё копируется туда. Все изменения ты вносишь в эту копию. Затем ты фиксируешь всё сразу одним commit — либо отменяешь, и ничего не происходит.
Формулировка самого Google предельно прямая: «Changes made within an edit are not live until the edit is committed» («Изменения внутри edit не публикуются, пока edit не зафиксирован»). При commit, если ошибок валидации нет, все изменения в edit публикуются одновременно, заменяя текущее состояние. Если валидация не проходит, API выбрасывает ошибку, а живой листинг остаётся нетронутым. Итого, жизненный цикл — ровно четыре шага:
edits.insert— создать edit, получитьeditId.- изменения —
edits.listings.updateдля текста по каждому языку,edits.images.upload/deleteallдля скриншотов и графики. edits.commit— проверить всё, затем опубликовать атомарно.edits.abandon— отбросить черновик, живой листинг не меняется.
Важное ограничение, которое стоит учитывать в архитектуре: у аккаунта может быть открыт только один edit одновременно, и если кто-то зафиксирует edit или изменит приложение через интерфейс Play Console, все остальные открытые edit'ы для этого приложения станут недействительными. Относись к edit как к короткоживущей сущности — открыл, записал, зафиксировал. Не держи его открытым часами, пока человек кликает в консоли.
Авторизация: сервисный аккаунт плюс приглашение, о котором все забывают
Для автоматического обновления тебе нужен сервисный аккаунт, а не пользовательский OAuth. Здесь задействованы две по-настоящему разные системы:
- Google Cloud. Создай сервисный аккаунт, включи Google Play Android Developer API в проекте и скачай JSON-ключ. Единственный нужный scope —
https://www.googleapis.com/auth/androidpublisher. - Play Console. Перейди в раздел Users & permissions, нажми Invite new users, вставь email сервисного аккаунта (адрес вида
...@...iam.gserviceaccount.com) и предоставь доступ к приложению. Только после этого ключ сможет работать с твоим листингом.
Ещё одно предварительное условие: приложение уже должно существовать и иметь хотя бы один релиз (хотя бы один APK/AAB, загруженный через консоль). Создать совершенно новое приложение только через API невозможно.
Четыре вызова в виде REST
Обновление текста листинга
edits.listings.update — это PUT, то есть полная замена листинга для данного языка. Всё, что ты отправишь, становится листингом; поля, которые ты не укажешь, будут очищены, а не сохранены. Поэтому, если нужно изменить только краткое описание, всё равно придётся отправить и название, и полное описание — иначе они будут стёрты. Когда действительно нужно частичное изменение, есть отдельный метод edits.listings.patch, который объединяет только переданные поля. Для большинства пайплайнов полный PUT удобнее — ты и так формируешь весь листинг из своего источника истины, так что заменить его целиком — правильное решение.
Три текстовых поля и их лимиты: title — до 30 символов, shortDescription — до 80, fullDescription — до 4000. Один ресурс листинга на язык, определяемый тегом языка BCP-47 в URL (en-US, de-DE, ja-JP и так далее). Чтобы обновить десять языков, ты делаешь десять вызовов listings.update внутри одного edit — затем один commit публикует их все вместе.
Загрузка скриншотов и feature graphic
Изображения привязываются к языку и к типу изображения. Тип изображения — это перечисление, и каждый слот в листинге соответствует одному из следующих значений:
phoneScreenshots,sevenInchScreenshots,tenInchScreenshots— наборы скриншотов для телефона и планшета.tvScreenshots,wearScreenshots— Android TV и Wear OS.featureGraphic— баннер 1024×500, показываемый в верхней части листинга.icon,tvBanner— значок приложения и баннер для TV.
edits.images.upload добавляет в edit одно изображение заданного языка и типа. Метода «задать весь массив целиком» не существует, поэтому надёжный способ заменить скриншоты — сначала вызвать edits.images.deleteall для этого языка и типа изображения, а затем загрузить новый набор в том порядке, в котором они должны отображаться. edits.images.list показывает, что сейчас находится в edit, а edits.images.delete удаляет одно изображение по id, если нужны точечные изменения. Всё это остаётся внутри edit до момента commit.
Commit — и что на самом деле значит «опубликовано»
Несколько моментов, в которых стоит быть точным, потому что они удивляют людей:
- Новая сборка не требуется. Commit edit'а, затрагивающего только листинг, не требует свежего APK/AAB. Текст и изображения — это метаданные; их можно обновлять сколько угодно раз для уже существующего релиза (нужен лишь тот единственный предыдущий релиз).
- Commit сначала проверяет, потом публикует. Если у скриншота неверные размеры или поле слишком длинное, commit завершится ошибкой, а живой листинг не изменится — ты исправляешь и повторяешь commit.
- Публикация не мгновенная. После успешного commit изменения могут появиться спустя несколько часов — так же, как и при ручном редактировании в Play Console. Не считай код 200 при commit признаком того, что изменения уже видны пользователям.
- Отмена ничего не стоит. Если пробный запуск выглядит неправильно,
edits.abandonотбрасывает черновик без каких-либо последствий для живого листинга. Удобно для проверки пайплайна без риска.
Путь без кода: дизайн, перевод, публикация
Описанный выше API — правильный инструмент, если у тебя есть время инженеров и источник истины для синхронизации. Чего он не делает — так это не создаёт сами материалы. Тебе всё равно нужно спроектировать скриншоты, написать название и оба описания и подготовить всё это на каждом языке — API лишь публикует то, что ты ему передашь.
Именно эту часть берёт на себя Mokbi. Ты проектируешь скриншоты прямо в браузере, тут же составляешь название, краткое и полное описание и переводишь весь листинг на 50 языков за один проход — так что для десяти вызовов listings.update выше у тебя уже есть настоящий, локализованный текст вместо заглушек.
А сама публикация? Mokbi делает и это. Для Google Play под капотом выполняется ровно этот процесс (edits.insert → listings.update → загрузка изображений → commit), так что твой локализованный листинг и материалы публикуются без единой строки кода, описанного выше. Для App Store Mokbi подготавливает версию в App Store Connect, полностью заполненную и готовую к отправке — Apple требует, чтобы финальный Submit нажимал ты сам и проходил проверку. Проектирование скриншотов и feature graphic, написание листинга, перевод на 50 языков и публикация — это один непрерывный процесс.