Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

App Store Connect Programmatic Pricing Guide

App Store Connect Node.js License: MIT

A practical guide to managing subscription prices across 175+ App Store territories programmatically—audit from CSV, normalize to .99 endings, handle pagination, tolerance bands, checkpoint resume, and failures files.

Audience: Developers who need to set or correct subscription prices in ASC for many territories without manual UI work.
Requirements: Node.js (or your preferred stack), App Store Connect API key (App Manager or Admin), exported "Prices in places" CSV from ASC.


1. Why programmatic?

  • Scale: N products × 175 territories = hundreds or thousands of price points. Manual UI is error-prone and slow.
  • Consistency: Pricing rules (e.g. tolerance bands, .99 endings) are enforced in code.
  • Audit trail: CSV export → audit report → fix report → failures file gives a clear record.
  • Resume: Long runs can time out; checkpoint files let you resume without redoing work.

2. High-level flow

Export "Prices in places" (CSV) from ASC
         ↓
1-audit  (no API) → audit-report.json
         ↓
2-report (optional) → price-report.json  [who needs .99 normalization?]
         ↓
3-fix (API) → set prices; checkpoint + failures file
  • Audit (no API): Compare CSV to your target prices; output a list of territories that are off.
  • Report (optional): Filter to "prices not ending in .99" (or your rule) for psychological pricing.
  • Fix (API): For each item in the report, fetch all price points for that territory (pagination), pick the best match within tolerance, set it via API. Save progress to a checkpoint; write failures to a file for manual fix.

3. Principles that make it efficient

3.1 Pagination

Apple returns price points in pages (e.g. limit 200, links.next). Always follow pagination until you have the full list for that territory. "No price found" should never be due to missing pages—if you don't find a price, it's because no price in the grid meets your rules (tolerance, .99, etc.), not because you didn't fetch enough.

3.2 Tolerance bands

Define an "expected" price per product/territory based on your pricing strategy. Only set a price if the chosen price is within ±X% of that expected (e.g. 10%). If you relax tolerance for stubborn territories, use a higher percentage (e.g. 25%) but still never set a price that would slash or overcharge vs current (e.g. require chosen price within 80–120% of current).

3.3 Safeguards against wrong prices

  • Primary: Chosen price within 10% of expected.
  • Fallback: If no .99 in 10%, try 40%—but if the chosen price would be < 85% or > 120% of current, reject it (no slashing/overcharging).
  • Last resort: Accept any .99 within 80–120% of current. If none, do not set; write to failures file for manual fix.
  • Never set a price and report "verified" when it's outside these bands.

3.4 Checkpoint resume

For each successful update, append product:territory to a checkpoint file. On the next run, skip entries in the checkpoint. If the run times out or you cancel, re-run the same command to continue; use --no-resume only when you want to start from scratch.

3.5 Failures file

Write every entry the script could not fix (no valid price in range, or skipped by rule) to a text/JSON file: product, territory, current price, desired price, currency, reason. Use it for manual fix in ASC or for re-runs with relaxed options (e.g. --no-cache to refetch from API).

3.6 Cache (optional)

Cache territory price points (e.g. 24h TTL) to avoid re-fetching the same list. Provide a --no-cache flag so users can force fresh data (e.g. after ASC propagation or to retry failures).

3.7 Territory–currency quirks

Some territories are priced in a different currency than the country code suggests (e.g. Kuwait/KWT in USD, not KWD). Maintain a territory → currency map and default unlisted territories to USD (or your base). Use the latest CSV export when auditing so the audit reflects current ASC state.


4. API usage

  • Auth: JWT (ES256) with issuer ID, key ID, and private key (.p8). Token lifetime ~20 min; refresh as needed.
  • Endpoints:
    • List price points: GET /subscriptions/{id}/pricePoints?filter[territory]={TERRITORY}&limit=200; follow links.next for more pages.
    • Set price: POST /subscriptionPrices with body linking subscription, price point, and territory.
  • Rate limits: Apple returns 429; back off (e.g. 60 s) and retry. Add a delay between requests (e.g. 300–500 ms) to reduce 429s.
  • Idempotency: Setting the same price point again is safe; "current price already set" can be treated as success or skip.

5. Script layout (reference)

Script Input Output API?
1-audit Folder of CSVs (one per product) audit-report.json, .txt No
2-report audit-report.json price-report.json, .txt No
3-fix price-report.json Checkpoint + failures file Yes

See examples/script-layout.md for an implementation checklist.

Config: Subscription IDs per product, target prices per territory, tolerance %. Replace with your app's IDs and pricing rules.


6. Commands (example)

# 1. Export "Prices in places" from ASC (per product), save CSVs to a folder.

# 2. Audit (no API)
node 1-audit.js "/path/to/CSV/folder"

# 3. Report who needs .99 normalization
node 2-report.js

# 4. Fix – dry run
node 3-fix.js --dry-run

# 5. Fix – execute (resume from checkpoint if present)
node 3-fix.js --execute --no-resume

# Optional: relax tolerance for remaining skips
node 3-fix.js --execute --relax-tolerance=25

# Optional: bypass cache (fresh API data)
node 3-fix.js --execute --no-resume --no-cache

7. Result (example)

  • 49 product/territory pairs updated to a .99 price within tolerance.
  • 11 failed (no .99 in allowed band); written to failures.txt for manual fix in ASC.
  • 1 skipped (desired price outside tolerance by design).

8. Adapt to Your App

To use this approach in your project:

  1. Define your subscription IDs — Map each product to its ASC subscription ID.

  2. Define your target prices — Expected price per product/territory based on your pricing strategy.

  3. Set up ASC API key — Create an API key in App Store Connect with App Manager or Admin role. You'll need:

    • Issuer ID
    • Key ID
    • Private key file (.p8)
  4. Export "Prices in places" CSV — In ASC, go to each subscription → Subscription Prices → Export. Save one CSV per product.

  5. Implement the scripts — Use Node.js, Python, Swift, or your preferred stack. See examples/script-layout.md for a checklist.

  6. Run the flow — Audit → Report → Fix (dry run) → Fix (execute).


Contributing

Found a bug or have a suggestion? Open an issue or PR.

License

MIT — see LICENSE.

About

A practical guide to managing subscription prices across 175+ App Store territories programmatically—audit from CSV, normalize to .99 endings, handle pagination, tolerance bands, checkpoint resume, and failures files.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors