The Real Fix for IAP 2.1(b) "App Completeness" Rejection
No PDF. No email course. Just the actual cause — and the one App Store Connect step that clears it.
Who this is for: Indie iOS devs whose paid app keeps getting rejected for Guideline 2.1(b) — App Completeness ("we were unable to review the in-app purchases"). If you fixed your StoreKit code and it still bounces — usually within ~30 minutes — the problem is not your code. It's that the in-app purchase was never actually submitted for review alongside the build.
What this fixed (real apps)
Seven paid apps in my portfolio (AutoChoice, DaysUntil, PromptVault, HabitHash, FocusFlow Lite, TipJar Now, WaterNow) all carry a non-consumable IAP and are live today.
Every one of them hit 2.1(b) at least once. The thing that actually cleared it was never a code change — it was attaching the IAP to the version's review submission so its state moves to Waiting for Review.
Same root cause every time: an IAP stuck in Ready to Submit while the build went to review without it.
The Fix (in App Store Connect)
Your IAP has to be submitted with the app version. Apple's first IAP for an app can only be submitted on a version, not on its own. In ASC:
App Store Connect → your app → the version you're submitting
→ "In-App Purchases and Subscriptions" section
→ "Add for Review" / "Select an In-App Purchase"
→ tick your IAP → submit it together with the version
After that, the IAP state moves from Ready to Submit to Waiting for Review. If it's still Ready to Submit when you submit the build, Apple's automated check rejects 2.1(b) — often within 30 minutes.
The Hidden Trap (this is the one that wastes days)
You cannot do this step with the App Store Connect API. The reviewSubmissionItems endpoint only accepts appStoreVersion, appCustomProductPageVersion, and appEvent — every in-app-purchase relationship name (inAppPurchase, inAppPurchaseV2, etc.) returns 409 ENTITY_ERROR.RELATIONSHIP.UNKNOWN.
The IAP attach is a web-UI-only action — the "Add for Review" toggle on the version page.
Submitting the version alone (API or web) leaves the IAP behind → 2.1(b).
An IAP left in Ready to Submit auto-rejects; it must reach Waiting for Review or Approved before the build clears review.
Don't trust the rejection email's wording — it paraphrases. Verify the IAP state directly (step 3 below).
3-Step Fix Process
1
Check the IAP state first — In ASC, open the in-app purchase. If its status is Ready to Submit (not Waiting for Review / Approved), that is why review fails. Code changes won't move this state.
2
Attach the IAP to the version — On the version page, in "In-App Purchases and Subscriptions", use "Add for Review" and tick the IAP, then submit the version with the IAP. (Make sure the IAP has its review screenshot + review note filled in, or it can't be added.)
3
Verify the state changed — Confirm the IAP now reads Waiting for Review. Via API you can read (not write) it: GET /v2/inAppPurchases/{id} and check attributes.state.
Get the full 5-point rejection checklist
Enter your email — I'll send the complete checklist plus the exact ASC API call to verify your IAP state. No spam, no drip sequence.
Sent! Check your inbox for the full checklist.
Or: Email me directly — I respond to every email within 4 hrs JST Mon-Fri.
5-Point IAP Rejection Checklist
1
IAP state — Must be Waiting for Review or Approved before you submit the build. Ready to Submit = auto-reject.
2
Attached to the version — Use the ASC web "Add for Review" toggle so the IAP is submitted with the version (web-only; the API can't do it).
3
Review screenshot + note — An IAP with no review screenshot can't be added for review. Upload one (it can show the paywall).
4
Product ID consistency — Must match exactly in 3 places: the ASC IAP product ID, your .storekit config, and the ID your app requests in Product.products(for:).
5
New build if previously rejected — A build that was already reviewed won't re-trigger review on its own; bump the build number and upload a fresh binary, then re-submit with the IAP attached.