skills/gplay-iap-setup/SKILL.md
In-app products, subscriptions, base plans, and offers setup for Google Play monetization. Use when configuring in-app purchases or subscription products.
npx skillsauth add tamtom/gplay-cli-skills gplay-iap-setupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when you need to set up monetization for your Android app.
Google Play has two APIs for one-time products:
| | Legacy (gplay iap) | New Monetization (gplay onetimeproducts) |
|---|---|---|
| API | inappproducts | monetization.onetimeproducts |
| Price format | priceMicros/currency | units/nanos/currencyCode |
| Structure | Flat prices map | purchaseOptions with regionalPricingAndAvailabilityConfigs |
| States | active/inactive | DRAFT → ACTIVE (requires explicit activation) |
| Regional pricing | --auto-convert-prices flag | --regions-version required |
Prefer the new monetization API (gplay onetimeproducts) for new products. It supports purchase options, better regional pricing control, and is the actively developed API.
Use the legacy API (gplay iap) only for managing existing legacy products.
Never mix the two APIs for the same product. A product created via gplay iap create cannot be managed via gplay onetimeproducts and vice versa.
Google Play permanently reserves product IDs after deletion. If you create premium_unlock and later delete it, the ID premium_unlock can never be reused — not even with a different API. Choose product IDs carefully.
This means:
premium_unlock_v2)gplay onetimeproducts list --package com.example.app
--regions-version is required — the create command uses PATCH with allowMissing=true internally:
gplay onetimeproducts create \
--package com.example.app \
--product-id premium_unlock \
--json @product.json \
--regions-version "2025/03"
{
"productId": "premium_unlock",
"listings": [
{ "languageCode": "en-US", "title": "Premium Unlock", "description": "Unlock all premium features" },
{ "languageCode": "es-ES", "title": "Desbloqueo Premium", "description": "Desbloquea todas las funciones premium" }
],
"purchaseOptions": [
{
"buyOption": { "legacyCompatible": true },
"newRegionsConfig": {
"availability": "AVAILABLE",
"usdPrice": { "currencyCode": "USD", "units": "9", "nanos": 990000000 },
"eurPrice": { "currencyCode": "EUR", "units": "9", "nanos": 990000000 }
},
"regionalPricingAndAvailabilityConfigs": [
{ "regionCode": "US", "availability": "AVAILABLE", "price": { "currencyCode": "USD", "units": "9", "nanos": 990000000 } },
{ "regionCode": "GB", "availability": "AVAILABLE", "price": { "currencyCode": "GBP", "units": "7", "nanos": 990000000 } },
{ "regionCode": "IN", "availability": "AVAILABLE", "price": { "currencyCode": "INR", "units": "249", "nanos": 990000000 } }
]
}
]
}
New products start in DRAFT state. You must activate before users can purchase:
gplay purchase-options batch-update-states \
--package com.example.app \
--product-id premium_unlock \
--json '{"requests":[{"activatePurchaseOptionRequest":{"packageName":"com.example.app","productId":"premium_unlock","purchaseOptionId":"default"}}]}'
gplay onetimeproducts patch \
--package com.example.app \
--product-id premium_unlock \
--json @product-updated.json \
--regions-version "2025/03" \
--update-mask "purchaseOptions"
gplay onetimeproducts get --package com.example.app --product-id premium_unlock
gplay onetimeproducts delete \
--package com.example.app \
--product-id premium_unlock \
--confirm
# Get multiple products
gplay onetimeproducts batch-get \
--package com.example.app \
--product-ids "premium_unlock,coins_100"
# Update multiple products (regionsVersion goes inside JSON)
gplay onetimeproducts batch-update \
--package com.example.app \
--json @products-batch.json
Use only for managing existing legacy products.
gplay iap list --package com.example.app
gplay iap create \
--package com.example.app \
--sku premium_upgrade \
--json @product.json
{
"sku": "premium_upgrade",
"status": "active",
"purchaseType": "managedUser",
"defaultPrice": {
"priceMicros": "990000",
"currency": "USD"
},
"prices": {
"US": { "priceMicros": "990000", "currency": "USD" },
"GB": { "priceMicros": "799000", "currency": "GBP" }
},
"listings": {
"en-US": { "title": "Premium Upgrade", "description": "Unlock all premium features" },
"es-ES": { "title": "Actualización Premium", "description": "Desbloquea todas las funciones premium" }
}
}
# Update
gplay iap update --package com.example.app --sku premium_upgrade --json @product-updated.json
# Batch update
gplay iap batch-update --package com.example.app --json @products.json
# Batch get
gplay iap batch-get --package com.example.app --skus "premium,coins_100,coins_500"
# Delete (permanent — ID cannot be reused)
gplay iap delete --package com.example.app --sku premium_upgrade --confirm
gplay subscriptions list --package com.example.app
gplay subscriptions create \
--package com.example.app \
--json @subscription.json
Subscriptions use the units/nanos/currencyCode price format:
{
"productId": "premium_monthly",
"basePlans": [
{
"basePlanId": "monthly",
"state": "ACTIVE",
"regionalConfigs": [
{
"regionCode": "US",
"newSubscriberAvailability": true,
"price": { "currencyCode": "USD", "units": "4", "nanos": 990000000 }
}
],
"autoRenewingBasePlanType": {
"billingPeriodDuration": "P1M"
}
},
{
"basePlanId": "yearly",
"state": "ACTIVE",
"regionalConfigs": [
{
"regionCode": "US",
"newSubscriberAvailability": true,
"price": { "currencyCode": "USD", "units": "49", "nanos": 990000000 }
}
],
"autoRenewingBasePlanType": {
"billingPeriodDuration": "P1Y"
}
}
],
"listings": [
{ "languageCode": "en-US", "title": "Premium Subscription", "description": "Get all premium features" }
]
}
Base plans define the billing period and price for subscriptions.
gplay baseplans activate \
--package com.example.app \
--product-id premium_monthly \
--base-plan monthly
gplay baseplans deactivate \
--package com.example.app \
--product-id premium_monthly \
--base-plan monthly
gplay baseplans migrate-prices \
--package com.example.app \
--product-id premium_monthly \
--base-plan monthly \
--json @migration.json
Offers provide discounts, free trials, or introductory pricing.
gplay offers list \
--package com.example.app \
--product-id premium_monthly \
--base-plan monthly
gplay offers create \
--package com.example.app \
--product-id premium_monthly \
--base-plan monthly \
--json @offer.json
{
"offerId": "trial_7day",
"state": "ACTIVE",
"phases": [
{
"duration": "P7D",
"pricingType": "FREE_TRIAL"
}
],
"regionalConfigs": [
{
"regionCode": "US"
}
]
}
{
"offerId": "intro_50_off",
"state": "ACTIVE",
"phases": [
{
"duration": "P1M",
"pricingType": "SINGLE_PAYMENT",
"price": {
"priceMicros": "2490000",
"currency": "USD"
}
}
]
}
# Activate
gplay offers activate \
--package com.example.app \
--product-id premium_monthly \
--base-plan monthly \
--offer-id trial_7day
# Deactivate
gplay offers deactivate \
--package com.example.app \
--product-id premium_monthly \
--base-plan monthly \
--offer-id trial_7day
Manage offers on one-time product purchase options:
# List offers
gplay otp-offers list --package com.example.app --product-id premium_unlock --purchase-option-id default
# Activate offer
gplay otp-offers activate --package com.example.app --product-id premium_unlock --purchase-option-id default --offer-id promo_50off
# Deactivate offer
gplay otp-offers deactivate --package com.example.app --product-id premium_unlock --purchase-option-id default --offer-id promo_50off
gplay pricing convert \
--package com.example.app \
--json @price-request.json
{
"basePriceMicros": "4990000",
"baseCurrency": "USD",
"targetCurrencies": ["GBP", "EUR", "JPY"]
}
# 1. Create product
gplay onetimeproducts create \
--package com.example.app \
--product-id premium_unlock \
--json @premium.json \
--regions-version "2025/03"
# 2. Activate purchase option
gplay purchase-options batch-update-states \
--package com.example.app \
--product-id premium_unlock \
--json '{"requests":[{"activatePurchaseOptionRequest":{"packageName":"com.example.app","productId":"premium_unlock","purchaseOptionId":"default"}}]}'
# 3. Verify
gplay onetimeproducts get --package com.example.app --product-id premium_unlock
# 1. Create subscription
gplay subscriptions create \
--package com.example.app \
--json @sub.json
# 2. Create free trial offer
gplay offers create \
--package com.example.app \
--product-id premium \
--base-plan monthly \
--json @trial.json
{
"productId": "premium",
"basePlans": [
{
"basePlanId": "basic_monthly",
"regionalConfigs": [{ "regionCode": "US", "newSubscriberAvailability": true, "price": { "currencyCode": "USD", "units": "2", "nanos": 990000000 } }],
"autoRenewingBasePlanType": { "billingPeriodDuration": "P1M" }
},
{
"basePlanId": "premium_monthly",
"regionalConfigs": [{ "regionCode": "US", "newSubscriberAvailability": true, "price": { "currencyCode": "USD", "units": "4", "nanos": 990000000 } }],
"autoRenewingBasePlanType": { "billingPeriodDuration": "P1M" }
},
{
"basePlanId": "premium_yearly",
"regionalConfigs": [{ "regionCode": "US", "newSubscriberAvailability": true, "price": { "currencyCode": "USD", "units": "49", "nanos": 990000000 } }],
"autoRenewingBasePlanType": { "billingPeriodDuration": "P1Y" }
}
]
}
In your app code, use test product IDs:
android.test.purchasedandroid.test.canceledandroid.test.refundedandroid.test.item_unavailableAdd test accounts in Play Console: Settings → License Testing → Add license testers
premium_monthly, not prod_001. IDs are permanent and cannot be reused after deletion.gplay onetimeproducts for new products, not gplay iap.gplay-ppp-pricing skill) instead of same price everywhere.gplay purchase-options batch-update-states to activate.gplay --help to see all command groups. Purchase option management is under gplay purchase-options, not under gplay onetimeproducts.P1W - 1 weekP1M - 1 monthP3M - 3 monthsP6M - 6 monthsP1Y - 1 yeardevelopment
App vitals monitoring for crashes, ANRs, performance metrics, and errors via gplay vitals commands. Use when asked to check app stability, crash rates, ANR rates, or performance data from Google Play Console.
development
User and grant management for Google Play Console via gplay users and gplay grants commands. Use when asked to manage developer account users, permissions, or app-level access grants.
development
Beta testing groups and tester management for Google Play closed testing tracks. Use when managing testers and beta groups.
tools
Bulk-localize subscription display names, descriptions, and offer tags across all Google Play locales using gplay. Use when you want to fill in subscription metadata for every language without clicking through Play Console manually.