export reads the current App Store manual (and with --with-automatic the equalized) prices and the Play purchase option regional prices into one CSV. import parses and checks the sheet, prints a diff table (change %), and after a confirmation writes one App Store price schedule per changed product (base territory + every manual price, future-dated changes via start_date, price point ids looked up per territory) and the Play regional configs (CSV over current, convertRegionPrices for regions without a price, --reconvert). MCP: prices_diff (read-only), prices_export; applying stays a terminal command. store-iap-setup skill: price sheet section.
6.3 KiB
6.3 KiB
| name | description |
|---|---|
| store-iap-setup | Create and price in-app purchases (consumables, non-consumables like "remove ads", coin/gem packs, starter packs) on Google Play and App Store Connect from one product list - regional prices, local overrides, a price sheet CSV for many products and regions (diff first, future-dated App Store changes), activation, review screenshots, submitting first IAPs with a version, license/sandbox testers. Use when the user sets up, prices, re-prices or tests in-app products/IAPs, or hits Play onetimeproducts / inappproducts 403 or App Store IAP submission errors. |
In-app purchases on both stores
CLI: storebound (or bunx storebound in a project that has it, or bun <toolchain>/cli/index.ts). One list in storebound.config.ts products[] drives
both stores: id (same on both), type (consumable | non_consumable), usd base price, optional overrides
({ region: 'TR', currency: 'TRY', price: 99.99 }), listings per language (title <= 30, description <= 45 for
Apple), reviewScreenshot.
Prerequisites
- Play: a build with
com.android.vending.BILLINGuploaded to any track; payments profile set up. - Apple: Paid Applications agreement + banking + tax active (Business > Agreements), the app record exists.
Google Play (API)
storebound check, thenstorebound play products --dry(shows create/update and region count per product).storebound play products. Per product:pricing:convertRegionPrices(USD -> every region at local price points, and theregionsVersion), your overrides on top,PATCH .../onetimeproducts/{id}?allowMissing=true®ionsVersion.version=...(create or update), thenoneTimeProducts/{id}/purchaseOptions:batchUpdateStatesto activate (new options are DRAFT).- Verify:
storebound play statuslists every product withbuy:ACTIVE. - Test: Play Console > Settings > License testing: add tester Gmail accounts; install from the internal testing link; purchases are free test orders.
App Store (API + UI)
storebound apple iap --dry, thenstorebound apple iap: creates missing products, localizations, a price schedule (USA base + overrides; Apple equalizes the rest) and availability. Existing schedules are not changed (change prices in the UI if needed).- Review screenshot per product (a real device size, e.g. 1290 x 2796, showing the item in the shop):
storebound apple iap-review. States move to READY_TO_SUBMIT when complete. - UI: each IAP page > "Add for Review"; this puts them into the version's draft submission. Then submit the version (owner, see appstore-first-release).
- Test: Sandbox testers (Users and Access > Sandbox) on device; or a StoreKit configuration file in Xcode for local runs (those transactions are signed locally and fail server-side receipt checks).
Many prices at once: the price sheet (both stores)
For price changes after the products exist (sales, regional pricing, a new price everywhere), keep one CSV:
product,store,region,currency,price,start_date (store = apple | play | both; region ISO alpha-2; start_date
App Store only, a future YYYY-MM-DD).
storebound prices exportwrites the current prices of both stores tostore/prices.csv(--with-automaticadds Apple's equalized prices askind=auto, for reference; they are ignored on import).- Edit the rows. Apple only takes its own price points: an exact value per territory (the error lists the neighbours); Play takes any price in the region's currency.
storebound prices import --dry(MCP:prices_diff) prints the diff table: product, store, region, from, current, new, change %. Show it to the owner.- The owner runs
storebound prices import(asks first; not an MCP tool). Apple: one new price schedule per changed product (base territory, default the current one orprices.baseTerritory, plus every manual price; territories without one follow Apple's equalization). Play: the purchase option's regional prices are replaced; regions the product has no price for getconvertRegionPricesfrom the USD base,--reconvertresets every region the CSV does not list.
- Future-dated changes (
start_date) are App Store only; Play has no scheduled prices (change them on the day). - Apple's IAP pricing guide warns that a price increase cannot be reverted once it is in effect: tell the owner.
- Prices are public the moment the stores apply them. Never import without the owner reading the diff.
Gotchas
- Play legacy
inappproductsreturns 403 "Please migrate to the new publishing API" -> usemonetization.onetimeproducts. - Path casing: PATCH works on
onetimeproducts, but list +purchaseOptions:batchUpdateStatesneedoneTimeProducts; the wrong casing answers with an HTML 404 page. - Play has no consumable flag: the app consumes the purchase after granting it. Use
legacyCompatible: trueso older billing libraries see the product by id. - Apple: first IAPs must ship with an app version ("FIRST_*_MUST_BE_SUBMITTED_ON_VERSION" from
inAppPurchaseSubmissions). If the version is already in review without them: cancel the review submission
(
storebound apple status --cancel-submission <id>, ask the owner), re-add via "Add for Review", resubmit. - Reported, verify before relying on it: App Store Connect API 4.4.1 manages IAPs as versions
(
inAppPurchaseVersions) and its release notes say a review submission item can take aninAppPurchaseVersion. That should let later IAP versions be added toreviewSubmissionsthrough the API; the first attachment of a new app's first IAPs still needed the UI "Add for Review" in our runs. storebound does not automate either yet. - Apple needs an exact existing price point for each manual price; the error lists the nearest ones.
- Apple IAP display name 2-30 characters, description max 45 (App Store Connect Help > Reference > "In-app purchase information"; an older App Store marketing page says 55, but App Store Connect enforces 45).
- Product ids can never be reused after deletion on either store. Never delete without the owner.
- Do not put prices or product names in store descriptions; say "offers optional in-app purchases".
- If the game ships without real billing yet, hide every purchase surface in store builds (review rejects mock purchases) and answer "digital purchases: No" in IARC.