The App Store rejection rate for first-time indie submissions is brutal — not because the bar is high, but because the prep list is long and most people skip half of it. Here is the actual list, ordered by what blocks submission first.
Background
Apple’s App Store review is rule-based, not vibe-based. Most rejections are not “your app is bad,” they are “you did not configure something correctly.” For an indie developer the highest leverage move is to do every piece of prep before your first submission so you spend one review cycle instead of four. This list covers what you need before you press “Submit for Review” — not what you need to ship a great app.
How to tell
- You have a working build that runs on a real device.
- You have an Apple Developer account (the $99/year one, not just Xcode).
- You have at least 5 days of buffer before any external launch commitment.
- You have basic legal entities sorted (or are launching as an individual).
Step by step
-
Create the App Store Connect record: App Store Connect → My Apps → ”+” (top-left) → “New App”.
- Bundle ID: must match your Xcode project (Xcode → Target → Signing & Capabilities → Bundle Identifier). Use reverse-domain naming:
com.<your-domain-reversed>.<appname>, e.g.com.yoursite.pockethabits. - Primary Language: permanently locked after launch (drives default listing language). Pick the audience’s language carefully.
- Primary Category: changeable later, but heavily weights search ranking — pick deliberately.
- App Name + SKU: SKU is internal, never shown. Use a self-describing slug like
appname-2026q2.
- Bundle ID: must match your Xcode project (Xcode → Target → Signing & Capabilities → Bundle Identifier). Use reverse-domain naming:
-
Host the privacy policy at a stable URL. Free options on GitHub Pages / Vercel:
mkdir privacy && cd privacy echo "# Privacy Policy for <App Name>" > privacy.md echo "Last updated: 2026-05-21" >> privacy.md # deploy to https://yoursite.com/privacy/The policy must include 7 blocks: data collected / purpose / third-party sharing / retention period / user rights / deletion flow / contact. Use the template in App privacy policy checklist.
-
App Privacy form (App Store Connect → App Privacy). Walk Apple’s 32 data categories:
Identifiers → required if using Crashlytics / Adjust / AppsFlyer Usage Data → required if using Firebase Analytics / Mixpanel Diagnostics → almost any Sentry / Crashlytics setup Contact Info → if you collect email / phone Health & Fitness → if using HealthKit ...For each checked: Linked to User / Not Linked / Used for Tracking.
Third-party SDKs count as “you collect” — audit
Podfile/Package.swift, check each dependency’s Privacy Manifest:# Xcode 15+ — verify all dependencies' PrivacyInfo.xcprivacy find . -name "PrivacyInfo.xcprivacy" -exec cat \{\} \; -
Screenshots (iPhone 6.7” / 6.5” / 5.5” + iPad 12.9” if iPad). Specs:
iPhone 6.7" / 6.9": 1290x2796 or 1320x2868 (iPhone 16 Pro Max) iPhone 6.5": 1242x2688 (iPhone 11 Pro Max) iPhone 5.5": 1242x2208 (iPhone 8 Plus) iPad Pro 12.9": 2048x2732Automate with Fastlane snapshot:
gem install fastlane fastlane snapshot init # Write UI tests in SnapfileUITests/SnapshotHelper.swift fastlane snapshot --devices "iPhone 16 Pro Max,iPad Pro 13-inch (M4)"Add captions / device frames with AppLaunchpad or Figma templates, but the screen content must be from a real running build.
-
Write App Name / Subtitle / Keywords: full rules in App Store listing copy. Spec recap:
App Name: ≤30 char Subtitle: ≤30 char Keywords: ≤100 char, comma-separated, no spaces e.g. habit,streak,daily,routine,morning,evening,ritual,offline Description: ≤4000 char What's New: ≤4000 char -
Age Rating: App Store Connect → App Information → Age Rating → “Edit”. Apple asks 14 questions:
Cartoon or Fantasy Violence → None / Infrequent / Frequent Realistic Violence → ... Profanity → ... Sexual Content → ... Gambling → ... (even a dice game = check Simulated Gambling) Unrestricted Web Access → if the app contains a WKWebView that loads arbitrary URLs, you MUST check thisMost common mistake: “Unrestricted Web Access” — any WKWebView loading external URLs requires this checked; unchecked = reject.
-
IAP: configure BEFORE referencing in build. App Store Connect → your app → Features → In-App Purchases → ”+”:
Type: - Consumable one-time consumables (coins, items) - Non-Consumable one-time permanent unlock ("Remove ads") - Auto-Renewable Subscription monthly / annual - Non-Renewing Subscription recurring but no auto-renew Reference Name: internal, e.g. "Pro Monthly" Product ID: referenced in code, e.g. com.yoursite.appname.pro_monthly Price Tier: Tier 1 ($0.99) → Tier 87 ($999.99) Display Name: user-facing, e.g. "Pocket Habits Pro" Description: user-facing, ≤45 charIAP screenshot (paywall page) must be uploaded. Then in Xcode:
// StoreKit 2 usage let products = try await Product.products(for: ["com.yoursite.app.pro_monthly"]) -
TestFlight with real users. App Store Connect → TestFlight → Internal / External Testing:
Internal: up to 100 App Store Connect team members, instant test after upload External: up to 10,000 invitees; first build needs Apple review (24-48h) Process: 1. Xcode → Product → Archive → Distribute App → App Store Connect → Upload 2. Wait for build processing (10-30 min) 3. TestFlight → select build → Add External Testers → send invitation emails 4. Don't proceed without ≥5 real-user feedback + 0 crashesFix obvious issues before submitting for App Review.
-
Final pre-submit checklist:
- [ ] App icon legible at both 1024x1024 and 60x60 - [ ] Launch screen is not blank or a placeholder - [ ] No leftover print() / NSLog / TODO / debug-only menu - [ ] No "test@example.com" / "lorem ipsum" - [ ] Every link in About / Settings / Help responds to curl - [ ] Delete app → reinstall → full cold-start flow without crash - [ ] Review account filled in App Review Information AND verified working on a test device - [ ] Every red "Required" in App Store Connect now green# One-shot grep audit grep -rE "TODO|print\\(|NSLog|test@example|lorem" --include="*.swift" --include="*.m" --include="*.mm" .
Common pitfalls
- Using a personal email or a free hosting subdomain for the privacy policy URL. Apple wants it stable; use your own domain.
- Skipping the App Privacy questionnaire because “I do not collect data.” If you use Firebase Analytics, Sentry, or anything similar — you do collect data.
- Submitting before testing IAP in TestFlight sandbox. IAP bugs are caught in review and waste a full cycle.
- Mockup screenshots that show features your app does not have. This is rule 2.3.3 and a common rejection.
- Listing fake reviews, fake user counts, or “as featured in” claims you cannot substantiate.
- Choosing a name that contains a trademarked term you do not own. Apple’s legal screen will catch this.
Who this is for
First-time iOS publishers and solo developers who want to compress prep work and avoid silly rejections.
When to skip this
Larger teams with an existing release process — you likely already have most of this; focus on the rejection-reasons article instead.
FAQ
- How long does the first submission usually take to review?: In 2026, median review time is 24-48 hours, but first submissions often hit “Metadata Rejected” on day one and restart the clock. Plan a week.
- Do I need an LLC to publish?: No. You can publish as an individual on a personal Apple Developer account. Some choose an LLC for liability or branding reasons, but it is not required.
- Can I publish under a brand name without trademark registration?: Yes, but Apple may ask you to prove ownership if there is a conflicting trademark. Search the USPTO database before you commit.
- What if my app is mostly a web wrapper?: Read rule 4.2 carefully. Pure web wrappers without native value get rejected. Add real native features (notifications, offline, share extensions) or expect rejection.