Building a price-update workflow with the App Store Connect API
A step-by-step guide to automating App Store price changes using the App Store Connect API — covering JWT auth, price-point lookups, schedule POSTing, subscriber grandfathering, and safety rails for a production-ready workflow.
Manually updating prices in App Store Connect is a Saturday-night chore that most developers recognise immediately: log in, navigate to the app, find the pricing section, select a tier, confirm across territories, repeat for every in-app purchase, and hope you didn't miss a step. For an app with a handful of subscriptions and a global user base, that's easily an hour of careful clicking — per price change.
The App Store Connect API gives you a programmatic alternative. A well-structured workflow lets you apply territory-aware price changes in minutes, schedule them in advance, and maintain an audit trail that a click-through UI can never provide. This post walks through a practical five-step automation, including the edge cases that catch developers off-guard.
Prerequisite: This guide assumes you already have an App Store Connect API key and can generate signed JWTs. If not, start with our walkthrough on setting up the API key and the JWT authentication guide before continuing here.
What the App Store Connect API exposes for pricing
Apple's App Store Connect API provides three core resource types for app pricing:
- appPricePoints — A read-only catalogue of every available price point across every storefront. This is your lookup table: price-point IDs map to local currency amounts and to Apple's proceeds for that tier.
- appPriceSchedule — The current and future price schedule for a paid app (base territory plus manual overrides per storefront). A GET against this resource tells you exactly what you currently charge, and when any pending changes take effect.
- inAppPurchasePriceSchedules — The equivalent resource for individual in-app purchases and subscriptions, with support for both automatic and manual price-setting per territory.
The distinction between automatic and manual territory pricing is consequential. Automatic pricing lets Apple calculate local equivalents from your base-territory price using its own currency conversion rules — convenient, but the results drift as exchange rates shift and rarely reflect local purchasing power. Manual pricing gives you explicit control over what a user pays in, say, Brazil or Turkey, but requires you to set each territory yourself. The API supports both modes; a mature workflow handles the transition between them cleanly.
A practical five-step workflow
The following pattern is language-agnostic — examples use curl and jq, but the logic applies equally in Python, Ruby, or any CI runner.
Step 1: Generate a short-lived JWT
Every API call requires a bearer token signed with your private key. JWTs for the App Store Connect API are valid for up to 20 minutes — generate a fresh one at the start of each script run rather than caching across runs.
TOKEN=
Store the token in a shell variable for reuse throughout the workflow. Never log it to stdout or commit it to source control.
Step 2: Fetch the current price schedule
Before making any change, capture the current state. This serves two purposes: it gives you a rollback reference, and it confirms the resource IDs you'll need for subsequent calls.
curl -s -H "Authorization: Bearer " "https://api.appstoreconnect.apple.com/v1/apps//appPriceSchedule?include=manualPrices,automaticPrices,baseTerritory" | jq . > current_price_schedule.json
Save this file. If anything goes wrong post-update, you have the exact prior configuration to re-apply.
Step 3: Look up target price points
Apple's pricing tiers are not arbitrary numbers — they are named price-point IDs that map to specific local prices per storefront. The appPricePoints endpoint lets you query what a given tier costs in a given territory and what proceeds Apple passes through.
curl -s -H "Authorization: Bearer " "https://api.appstoreconnect.apple.com/v2/appPricePoints?filter[territory]=USA,GBR,DEU,BRA,IND&fields[appPricePoints]=customerPrice,proceeds,territory" | jq '.data[] | {id: .id, price: .attributes.customerPrice}'
Build a mapping from the territory codes you care about to the price-point IDs that correspond to your target price. For context on why different territories need different absolute prices rather than simple currency conversions, see our post on how currency conversion fails for global iOS pricing.
Step 4: POST the new price schedule
With your price-point IDs confirmed, construct and POST the updated schedule. The payload's relationships.manualPrices array references the specific price-point IDs for each territory you want to set manually; any territory omitted from the array reverts to automatic (Apple-calculated) pricing.
python3 -c "
import json, sys
manual_prices = [
{'type': 'appPricePoints', 'id': 'USA_PRICE_POINT_ID'},
{'type': 'appPricePoints', 'id': 'GBR_PRICE_POINT_ID'},
{'type': 'appPricePoints', 'id': 'DEU_PRICE_POINT_ID'},
]
payload = {
'data': {
'type': 'appPriceSchedules',
'relationships': {
'app': {'data': {'type': 'apps', 'id': 'APP_ID'}},
'manualPrices': {'data': manual_prices}
}
}
}
print(json.dumps(payload))
" > payload.json
curl -sS -X POST -H "Authorization: Bearer " -H "Content-Type: application/json" -d @payload.json "https://api.appstoreconnect.apple.com/v1/appPriceSchedules"
A 201 response confirms success. Capture the response body — it contains the schedule ID you'll need for any subsequent inspections or updates.
Step 5: Verify and notify
Re-fetch the price schedule a couple of minutes after posting and diff it against your intended state:
sleep 120
curl -s -H "Authorization: Bearer " "https://api.appstoreconnect.apple.com/v1/apps//appPriceSchedule?include=manualPrices" | jq '.included[] | {id, price: .attributes.customerPrice}'
Pipe the diff output to a Slack webhook or email notification so the change is on record and the team is aware. App Store Connect API changes propagate to the storefront within minutes in practice, though Apple's documentation notes propagation times are not formally guaranteed.
Handling grandfathering and subscriber protection
Price automation becomes meaningfully more complex when existing subscribers are involved. Apple's grandfathering rules — the mechanism that determines whether current subscribers keep their existing price or must accept the new one — apply regardless of whether the change was made via the UI or the API.
| Scenario | Grandfathering applies? | Subscriber action required? | Notes |
|---|---|---|---|
| Price increase, same product | Yes | Yes — must consent to new price | Apple notifies by email and in-app; subscriber can cancel |
| Price decrease, same product | No | No | All subscribers benefit immediately |
| New product with migration offer | No (new product) | Opt-in offer required | Old product can be deprecated after migration window |
| Currency-driven adjustment (same tier) | Territory-dependent | May require consent | Apple's rules shifted in late 2023; always verify against current docs |
The practical implication for an automated workflow: never apply a subscription price increase immediately. Schedule it at least two to four weeks ahead, give customer support time to prepare for inbound questions, and monitor your cancellation rate closely in the window after Apple sends grandfathering notifications. Data published by RevenueCat has consistently shown that price increase events produce a measurable but typically temporary spike in voluntary cancellations — automated monitoring is your early-warning system.
Automation trap: If your script raises a subscription price and simultaneously removes the old price schedule entry in the same API call, you may inadvertently sever the grandfathering link Apple uses to notify existing subscribers. Always add new price entries to the schedule rather than replacing the entire schedule wholesale when active subscribers are in scope. For a full breakdown, see our dedicated post on Apple grandfathering rules for subscription price changes.
Safety rails and scheduling cadence
A price-update workflow is only as reliable as the guardrails built around it. Several failure modes are easy to prevent upfront:
| Safety rail | What it prevents | Implementation effort |
|---|---|---|
Dry-run mode (--dry-run flag) |
Unintended live changes during testing or CI review | Low — flag skips the POST step |
| Approval gate for increases above a threshold | Unreviewed price hikes reaching subscribers | Medium — GitHub Actions environment or Slack bot |
| Idempotency check before POSTing | Duplicate API calls on retried jobs | Low — compare target vs current state before proceeding |
Rollback snapshot (current_price_schedule.json) |
Inability to undo a mistaken change | Low — save before every write operation |
| Post-propagation diff check | Silent partial failures | Low — re-fetch and compare after a short delay |
On scheduling cadence: the App Store Connect API makes it technically trivial to change prices every day, but Phiture's published writing on subscription monetisation suggests that price stability matters to conversion rates, and visible churn in pricing can introduce subscriber uncertainty that suppresses new sign-ups even when existing subscribers are fully grandfathered. Treat automation as a tool for executing deliberate, well-researched decisions faster and more accurately — not as a licence to price-experiment continuously.
For apps with meaningful revenue in emerging markets, a monthly review of PPP-adjusted price points is a reasonable cadence. You can use the AppsOps pricing tools to benchmark your current tiers against purchasing-power equivalents before pushing any changes through the workflow above.
Sources and further reading
- App Store Connect API — Apple Developer Documentation
- App Store Connect Help — Set a Price for Your App
- RevenueCat Engineering Blog
- Phiture Mobile Growth Stack
- Apple Developer News & Updates
Share this post
Ready to put this into practice?
AppsOps is the first App Store ops dashboard — PPP-fair pricing for 175 App Store territories, AI metadata localization in 39 languages, AI screenshot localization for 14 Apple device classes, and one-click App Store Connect API push — all from one dashboard, all for $19/month.
Try AppsOps free — no card →