mcpField
A
asc-iap

asc-iap

github.com/tddworksDevelopment587 installsUpdated 5w ago
Repository

About asc-iap

asc-iap is a command-line skill for managing in-app purchases through the asc CLI. It covers product setup, pricing, offer codes, localizations, review assets, and submission workflows.

Key features

  1. 01Create and update in-app purchases
  2. 02Manage pricing and localizations
  3. 03Configure offer codes and code batches
  4. 04Upload review screenshots and images
  5. 05Track review states and submissions

Use cases

  1. 01Set up localized in-app purchases
  2. 02Configure territory pricing and offer codes
  3. 03Prepare purchase items for app review

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/tddworks/asc-cli-skills --skill asc-iap

After installing, type/asc-iapin Claude Code to confirm it loaded.

Details

From the project README

asc In-App Purchases

Manage IAPs via the asc CLI.

Lifecycle

List
asc iap list --app-id <APP_ID> [--limit N] [--pretty]
Create
asc iap create \
  --app-id <APP_ID> \
  --reference-name "Gold Coins" \
  --product-id "com.app.goldcoins" \
  --type consumable

--type ∈ consumable, non-consumable, non-renewing-subscription.

Update
asc iap update --iap-id <ID> \
  [--reference-name "New Name"] \
  [--review-note "Notes for App Review"] \
  [--family-sharable | --not-family-sharable]
Delete
asc iap delete --iap-id <ID>
Submit / Unsubmit
asc iap submit --iap-id <ID>          # state must be READY_TO_SUBMIT (affordance gates this)
asc iap unsubmit --submission-id <ID> # withdraw from review; manual Request<Void>
asc iap versions list --iap-id <ID>   # review versions + state; submittable ones offer addToSubmission

First-time IAP? Apple only reviews it together with an app version, so asc iap submit fails for it. Submit it with the app: asc versions submit --version-id <VERSION_ID> --with-products (run with --dry-run first). See submit-with-products.md for the full workflow.

IAP Pricing

asc iap price-points list --iap-id <ID> [--territory USA]

asc iap prices set \
  --iap-id <ID> \
  --base-territory USA \
  --price-point-id <PP>

Apple auto-equalizes other territories from the base.

IAP Localizations

asc iap-localizations list   --iap-id <ID>
asc iap-localizations create --iap-id <ID> --locale en-US --name "Gold Coins" [--description "In-game currency"]
asc iap-localizations update --localization-id <LOC> [--name "New"] [--description "..."]
asc iap-localizations delete --localization-id <LOC>

IAP Offer Codes (3-level hierarchy)

Level 1 — offer code
asc iap-offer-codes list   --iap-id <ID>
asc iap-offer-codes create --iap-id <ID> --name "FREEGEMS" \
  --eligibility NON_SPENDER --eligibility CHURNED_SPENDER \
  --price USA=pp-usa --price JPN=pp-jpn \
  --free-territory BRA --free-territory IND
asc iap-offer-codes update --offer-code-id <OC> --active false
asc iap-offer-codes prices list --offer-code-id <OC>   # per-territory pricing (read-only)

Pricing is set once, at creation. ASC's prices relationship is read-only after the offer code exists, so include every territory you want covered via --price (paid) or --free-territory. Without these flags the offer code is created with no per-territory pricing and cannot be fixed up later.

--eligibility (repeatable) ∈ NON_SPENDER, ACTIVE_SPENDER, CHURNED_SPENDER.

Level 2 — custom redeemable codes
asc iap-offer-code-custom-codes list   --offer-code-id <OC>
asc iap-offer-code-custom-codes create --offer-code-id <OC> \
  --custom-code "FREEGEMS100" --number-of-codes 500 [--expiration-date 2026-12-31]
asc iap-offer-code-custom-codes update --custom-code-id <CC> --active false
Level 3 — one-time use code batches
asc iap-offer-code-one-time-codes list   --offer-code-id <OC>
asc iap-offer-code-one-time-codes create --offer-code-id <OC> \
  --number-of-codes 3000 --expiration-date 2026-06-30 [--environment production|sandbox]
asc iap-offer-code-one-time-codes update --one-time-code-id <OTC> --active false

# Download the CSV of redemption codes (raw String — not JSON):
asc iap-offer-code-one-time-codes values --one-time-code-id <OTC>

--environment defaults to production. Sandbox batches redeem against sandbox tester accounts (≈10,000/quarter ceiling) — production batches against live App Store accounts (≈150,000/quarter ceiling). Each InAppPurchaseOfferCode reports usage against both ceilings via productionCodeCount / sandboxCodeCount, and each one-time-use code row carries its environment so you can filter:

asc iap-offer-code-one-time-codes list --offer-code-id <OC> \
  | jq '.data[] | select(.environment == "SANDBOX")'

REST equivalents:

GET    /api/v1/iap-offer-codes/{offerCodeId}/one-time-codes
POST   /api/v1/iap-offer-codes/{offerCodeId}/one-time-codes   # body: {numberOfCodes, expirationDate, environment?}
PATCH  /api/v1/iap-offer-code-one-time-codes/{oneTimeCodeId}  # body: {isActive: false}

IAP Review Assets

Review screenshot (singleton — one per IAP)
asc iap-review-screenshot get    --iap-id <ID>          # returns empty data:[] when none uploaded
asc iap-review-screenshot upload --iap-id <ID> --file ./review.png
asc iap-review-screenshot delete --screenshot-id <RS>   # suppressed while assetState == AWAITING_UPLOAD

Upload uses ASC's standard reserve → upload chunks → commit-with-MD5 protocol.

Promotional images (1024×1024, multiple per IAP)
asc iap-images list   --iap-id <ID>
asc iap-images upload --iap-id <ID> --file ./promo-1024.png
asc iap-images delete --image-id <IMG>                  # suppressed while state.isPendingReview

CAEOAS Affordances

Every IAP response embeds ready-to-run follow-up commands:

{
  "affordances": {
    "createLocalization":  "asc iap-localizations create --iap-id <ID> --locale en-US --name <name>",
    "delete":              "asc iap delete --iap-id <ID>",
    "getReviewScreenshot": "asc iap-review-screenshot get --iap-id <ID>",
    "listImages":          "asc iap-images list --iap-id <ID>",
    "listLocalizations":   "asc iap-localizations list --iap-id <ID>",
    "listOfferCodes":      "asc iap-offer-codes list --iap-id <ID>",
    "listPricePoints":     "asc iap price-points list --iap-id <ID>",
    "listVersions":        "asc iap versions list --iap-id <ID>",
    "submit":              "asc iap submit --iap-id <ID>",
    "update":              "asc iap update --iap-id <ID> --reference-name <name>"
  }
}

submit only appears when state == READY_TO_SUBMIT. Each price point includes setPrice only when territory is known.

InAppPurchaseSubmission advertises unsubmit. InAppPurchaseLocalization advertises update + delete. InAppPurchasePromotionalImage advertises delete only when !state.isPendingReview. InAppPurchaseReviewScreenshot advertises delete only once assetState.isComplete || hasFailed.

Resolve App ID

See project-context.md — check .asc/project.json before asking the user or running asc apps list.

Typical Workflow

APP_ID=$(cat .asc/project.json 2>/dev/null | jq -r '.appId // empty')

# 1. Create + localize
IAP_ID=$(asc iap create --app-id "$APP_ID" --reference-name "Gold Coins" \
  --product-id "com.app.goldcoins" --type consumable | jq -r '.data[0].id')
asc iap-localizations create --iap-id "$IAP_ID" --locale en-US --name "Gold Coins" --description "In-game currency"
asc iap-localizations create --iap-id "$IAP_ID" --locale zh-Hans --name "金币"

# 2. Set price (Tier 1 USA, Apple auto-equalizes)
PRICE_ID=$(asc iap price-points list --iap-id "$IAP_ID" --territory USA \
  | jq -r '.data[] | select(.customerPrice == "0.99") | .id')
asc iap prices set --iap-id "$IAP_ID" --base-territory USA --price-point-id "$PRICE_ID"

# 3. Add review screenshot + promo image
asc iap-review-screenshot upload --iap-id "$IAP_ID" --file ./review.png
asc iap-images upload --iap-id "$IAP_ID" --file ./promo-1024.png

# 4. Submit
asc iap submit --iap-id "$IAP_ID"

# 5. Optional: offer code + redemption batch
OC_ID=$(asc iap-offer-codes create --iap-id "$IAP_ID" --name "LAUNCH_PROMO" \
  --eligibility NON_SPENDER --eligibility CHURNED_SPENDER | jq -r '.data[0].id')
asc iap-offer-code-one-time-codes create --offer-code-id "$OC_ID" \
  --number-of-codes 5000 --expiration-date 2026-12-31
# Download the CSV for distribution:
asc iap-offer-code-one-time-codes values --one-time-code-id <OTC_ID> > codes.csv

State Semantics

InAppPurchaseState exposes semantic booleans:

BooleanTrue when state is
isEditableMISSING_METADATA, REJECTED, DEVELOPER_ACTION_NEEDED
isPendingReviewWAITING_FOR_REVIEW, IN_REVIEW
isApproved / isLiveAPPROVED

IAPCustomerEligibility ∈ NON_SPENDER, ACTIVE_SPENDER, CHURNED_SPENDER.

InAppPurchaseReviewScreenshot.AssetState exposes isComplete (uploadComplete or complete) and hasFailed. InAppPurchasePromotionalImage.ImageState exposes isApproved and isPendingReview.

Nil optional fields are omitted from JSON output.

Reference

For full domain-model and REST detail see docs/features/iap-subscriptions.md and the iap-subscriptions/ subdocs.

Comments

Markdown supported