Shipping paid apps
The App Store Connect setup that in-app purchases add on top of a normal submission.
Everything on this page is on top of the normal App Store submission flow. Free apps can skip it entirely. The preview’s simulated store needs none of it either, so do this setup when you are actually ready to ship, not before.
The work all happens in two dashboards Apple and RevenueCat own: App Store Connect and RevenueCat. Contrast cannot do these steps for you yet, but this page is the order that avoids the classic multi-day debugging sessions.
1. Agreements first
In App Store Connect under Business > Agreements, the Paid Applications agreement must be signed and banking and tax details complete. Until then, in-app purchase products silently fail to load on device and in TestFlight, which is the single most common “my products don’t appear” cause. The account checklist covers this; for paid apps it is not optional.
2. Create the products in App Store Connect
Your app’s page in App Store Connect has a Subscriptions section (and In-App Purchases for non-subscription products). Create each product with the same product identifier you use in RevenueCat, then clear its Missing Metadata status. A product stays in Missing Metadata until every required field is filled:
- Display name and description for at least one localization
- A subscription group and duration (for subscriptions)
- A price
- The review screenshot (a screenshot of your paywall is fine)
Products in Missing Metadata do not load on device. If your TestFlight build shows an empty paywall while preview worked, check this before anything else.
3. Give RevenueCat its Apple credentials
RevenueCat validates purchases with Apple on your behalf. In the RevenueCat
dashboard, your app’s App Store configuration needs the In-App Purchase
key: generate it in App Store Connect under
Users and Access > Integrations > In-App Purchase, download the .p8
file, and upload it to RevenueCat with its key id and issuer id. RevenueCat
also accepts an App Store Connect API key for product and pricing sync;
their setup screen walks through both.
Without the .p8, purchases can appear to work in sandbox but fail server
validation, which surfaces as entitlements that never activate.
4. Sandbox testers and TestFlight
- Create a sandbox tester account in App Store Connect under Users and Access > Sandbox Testers to test purchases on a device without real charges. Sign into it on the device under Settings > App Store > Sandbox Account.
- TestFlight builds purchase in the sandbox environment automatically and no one is charged. This is where your webhook route and durable subscription row get exercised for real: sandbox purchases hit RevenueCat’s servers and fire webhooks, unlike preview purchases.
- Sandbox subscriptions renew on an accelerated clock (minutes instead of months), so renewal and expiration handling can be observed in a sitting.
One app-side note: the subscription architecture Contrast’s agents build rejects sandbox entitlements in production builds by design, with an explicit allowlist for Apple’s reviewer accounts. If a TestFlight tester reports premium not unlocking durably, that guard is usually why, and it is working as intended.
5. Review, and why paid apps get rejected
Apple reviews in-app purchases with the binary. The rejections that hit subscription apps over and over:
- The first in-app purchase must be submitted with an app version. Select the products on the version page when you submit; a product alone cannot go through review.
- Restore Purchases must exist and work. A visible restore control on or near the paywall. The generated paywall includes one; do not remove it.
- The paywall must say what the subscription costs and when it renews, with price, duration, and auto-renewal terms visible before purchase, plus links to your privacy policy and terms of use.
- A demo account for review if your app requires sign-in, entered in the review notes (see the submission checklist).
- The reviewer will actually purchase in sandbox. If your products are in Missing Metadata or agreements are incomplete, review fails with a purchase-related rejection even though the app itself is fine.
After approval, revenue from live purchases flows into the Revenue pane in the Production section once RevenueCat records it.