App Store

    What do I remove from my AI app after a 3.1.1 rejection?

    A developer auditing an AI chatbot iOS build in Xcode, with a Resolution Center note citing Apple Guideline 3.1.1 open next to a list of in-app screens that still reference an external Stripe checkout URL

    If your AI app has just been rejected under Guideline 3.1.1 and you have already deleted the obvious Subscribe button, the second rejection often hits because App Review found a different pointer to your web checkout that you forgot. The audit list for an AI chatbot, image generator, or voice assistant is longer than most builders realise, especially when the app was assembled with Cursor or Claude Code from a web-first template.

    Short answer

    A Guideline 3.1.1 rejection on a non-US storefront means App Review found a route from the app to a digital-goods purchase outside StoreKit. The fix is a full audit of every in-app surface (buttons, settings, webviews, deep links, push payloads, help articles), every piece of App Store metadata (description, screenshots, support URL), and the marketing site behaviour when reached from the app. Per the App Review Guidelines, the prohibition covers buttons, external links, calls to action, and metadata across storefronts other than the US.

    What you should know

    • The rejection language is generic, the trigger is specific. Apple's standard text reads "Your app includes or accesses paid digital content, services, or functionality by means other than in-app purchase," without naming the offending screen. The reviewer often attaches a screenshot in Resolution Center; that screenshot is the most reliable clue.
    • A second 3.1.1 hit usually means a non-obvious pointer survived. Onboarding modals, footer text on the Settings screen, in-app help articles, and customer support widgets are the common second-pass triggers.
    • App Store metadata is part of the audit. App description, screenshots, Promotional Text, and the support URL are read during the same pass as the binary. A screenshot showing a web checkout fails 3.1.1 on its own.
    • Webviews count as in-app surfaces. A WKWebView pointing to your account portal where the user can buy a subscription is treated as an internal purchase mechanism that bypasses StoreKit.
    • Deep links and push notifications are checked at runtime. A push payload that opens a deep link to a web upgrade flow has produced rejections, particularly for apps that send onboarding nudges shortly after install.
    • The US storefront exception is region-specific, not global. Per Apple's May 2025 guideline update, external purchase links are permitted on the US storefront without an entitlement. Every other storefront still requires the entitlement or full removal.
    • A free app status does not exempt the listing. If any in-app surface mentions a paid tier hosted on your website, App Review applies 3.1.1 regardless of the price tag in App Store Connect.

    How do I read the rejection note to know exactly what to remove?

    The Resolution Center note has three useful parts: the cited guideline, the free-text reviewer comment, and any attached screenshots or screen recordings. The cited guideline tells you the rule. The free-text comment occasionally names the screen ("On the Settings tab, the Subscribe button opens an external website"), and the screenshots show the exact pixel the reviewer tapped.

    Start with the screenshots. If the reviewer attached an image of your Settings screen, that is your highest-confidence signal. If they only sent the rejection text, treat the entire app as the audit surface and walk every screen yourself. Reviewers commonly tap monetization-adjacent labels (Upgrade, Pro, Get Plus, Buy credits) within the first two minutes of testing, so the most common rejection triggers cluster there.

    The limit of this approach is that App Review does not list every violation in a single note. A reviewer who finds two clear violations sometimes only cites one, then re-flags the second on resubmission. Treat the rejection note as one example, not the full list. The BuddyBoss documentation on 3.1.1 collects several variants of the rejection text and is useful for matching what you received against the underlying intent.

    Which in-app surfaces should I check first?

    Walk the app in the order a fresh reviewer would. Start at the launch screen, sign in, then tap through every visible navigation entry. The pattern for an AI app is consistent: the upgrade pressure is concentrated in three places.

    In-app surfaceWhat App Review looks forWhat to remove or change
    Paywall and onboarding modalsBuy buttons that open a Stripe or Lemon Squeezy URL, plus disclaimer text mentioning web pricingStrip the external CTA, replace with a StoreKit sheet or remove the modal entirely
    Settings or Account screenManage subscription on web, Billing portal, Upgrade to Pro linksRemove the rows, or route them through StoreKit's subscription management API
    Help, FAQ, or Support webviewAn embedded webview to a help center page that lists pricing or links to checkoutLock the webview to non-monetization pages, or replace with native content
    Empty-state messagingA message like Out of credits, top up on the webReword to point to the StoreKit purchase or remove the call to action entirely
    Push notifications and in-app messagesMarketing payloads that deep-link to a web upgrade URLDisable upgrade-related campaigns on iOS, or filter the payload server-side per platform
    Customer support chatA widget like Intercom that surfaces a Buy Pro suggestion automationDisable the upgrade flow inside the iOS app for those automations

    Reviewers test on a real device with the production bundle, so server-side flags that hide buttons in TestFlight builds do not help here. The build you submitted is what the reviewer sees.

    What about App Store Connect metadata and the support URL?

    Metadata is the second pass and the one most easily overlooked. App Review reads the App Store listing during the same submission cycle and applies 3.1.1 to the listing text. The categories that have caused 3.1.1 rejections include: the app description (mentioning Pro pricing or free trial on the web), the Promotional Text field (a common spot for time-limited web-only offers), and the screenshots (showing a Stripe checkout or an upgrade webpage).

    The support URL field is the subtle one. The URL itself is allowed, but the page it points to is read during App Review. A support URL that lands on a sales page with a Subscribe Now button is treated as the same violation as an in-app link, because the support URL is reachable from the system Settings app once the app is installed. The safer pattern is a support URL that points to a documentation page with no purchase CTA, with the marketing site reachable separately.

    The App Store Connect Help on app information outlines which fields are reviewed alongside the binary, including the description, what's new, support URL, and marketing URL. The marketing URL is optional and is often the safest place for any sales language to live, because that one is treated as a contact point rather than an extension of the app surface.

    How do AI-coded apps trip 3.1.1 in places other builds do not?

    Apps assembled with Cursor, Claude Code, or Windsurf usually start from a web template that treats payments as a frontend concern. The Subscribe button calls a Stripe checkout, the success page sets a cookie, and the rest of the app reads the cookie to gate features. When that template is wrapped in a React Native shell or ported to Expo, the payment flow comes along unchanged.

    The specific patterns that produce 3.1.1 rejections in AI-coded apps:

    1. A Settings screen generated from the web app's user menu, which still contains a Manage Billing row that opens https://yourdomain.com/billing in a webview.
    2. An onboarding flow copied from the web app's first-run wizard, which ends with a Choose your plan screen pulling pricing from a /pricing endpoint and opening Stripe Checkout for the selected tier.
    3. An Out of messages empty state that reads Visit the web app to upgrade, often left in by the AI tool because the original web copy was reused.
    4. A help center widget like Intercom or Crisp that the AI bundled into the app and never disabled the upgrade automation for the iOS audience.
    5. A push notification campaign in OneSignal or Customer.io targeting iOS installs with an upgrade deep link, set up before the developer realized App Review tests notifications during the review window.

    The quickest verification step is a grep over the bundle for stripe, checkout, your domain, and the words subscribe, pricing, upgrade. PTKD.com (https://ptkd.com) runs this kind of pre-submission audit across compiled IPAs for AI-coded apps, and the repeat finding is that the literal Stripe checkout URL is still hardcoded in the JavaScript bundle even after the visible button has been removed. App Review does not decompile the bundle, but the string presence often correlates with a code path the reviewer can still reach through some other surface.

    How should I phrase the Resolution Center reply to App Review?

    A Resolution Center reply is read by the reviewer who rejected you, and sometimes by a second reviewer if the case was escalated. Keep it short, specific, and free of marketing language. The pattern that performs well is: name the screens you changed, name what you removed, and state the rule you are now compliant with.

    A workable template:

    Hello, thank you for the review. The previous build included buttons and links to external purchase flows on the Settings, Paywall, and Help screens. The new build removes those buttons and webviews. The Help screen now opens a native FAQ page with no pricing references. The Settings screen no longer contains a Manage Billing row. The Paywall has been removed for non-US storefronts in this build. App Store Connect metadata, screenshots, and support URL have been updated to remove references to web-only pricing. Per Guideline 3.1.1, the app now contains no external purchase mechanisms for digital goods on storefronts other than the US.

    Avoid promising what you cannot enforce, avoid arguing the rule, and avoid asking the reviewer to test the app a second time. The reviewer will test on the new build automatically when you resubmit.

    For a B2B SaaS or reader-style app where the rejection feels wrong, the Apple Developer Forums thread on B2B SaaS apps rejected under 3.1.1 collects developer reports where Reader-style or Multiplatform Service exceptions were attempted, often without success. The honest read is that escalation works only when the app is clearly outside 3.1.1's scope (no in-app sale signal at all), and even then the appeal usually goes through the App Review Board rather than the original reviewer.

    What to watch out for

    A few honest limits and traps:

    • The US storefront escape route is real but partial. Restricting the app to the US storefront in App Store Connect bypasses the rejection, but it also cuts off most of the international audience and the metadata still has to be clean.
    • Hidden links are still links. A button that is visually hidden by opacity zero, by display: none, or by a feature flag still counts if the reviewer can reach it. App Review has rejected for inactive code paths that produced a webview when a server flag was flipped during testing.
    • Receipt of a Resolution Center reply is not approval. A reviewer can read your reply, retest, and still reject. Plan for the possibility of a third pass, especially if the first rejection note was thin on detail.
    • A myth worth rejecting: hiding the Subscribe button behind a paywall already passed by App Review last year. Apple re-reviews the full app on every binary upload. A pattern that survived in 2024 is not safe in 2026.
    • A second myth: developer-facing claims that App Review is automated only for 3.1.1. The first pass is partly automated, but the actual rejection notes on 3.1.1 are issued by human reviewers who tap monetization buttons. Treat the audit as a human-reviewer audit.
    • A common partial fix: removing the button label without removing the underlying screen. The route that the button used is often still reachable through a hidden gesture, a deep link, or a webview row in Settings. Removing the entry point only counts when there is no other route to the same destination.

    The broader frame, per OWASP MASVS, is that any in-app surface tied to a payment flow falls under MASVS-PLATFORM-1, which expects payment events to use the platform-provided mechanism. Conformance with that control overlaps with passing 3.1.1, because both want the same end state: payments happen through StoreKit on iOS, with auditable receipts and platform-managed restore.

    Key takeaways

    • A 3.1.1 rejection on an AI app is rarely solved by removing one button. The reliable fix is a full audit of every in-app screen, every webview, every push notification, and every App Store Connect metadata field.
    • The cleanest signal of where to look is the screenshot the reviewer attached in Resolution Center. Walk that screen first, then sweep the rest of the app in the order a fresh tester would.
    • AI-coded apps from Cursor, Claude Code, or Windsurf inherit the web template's payment flow more often than developers realise. The grep for stripe, your domain, and upgrade copy is the fastest way to find what is left.
    • Some builders outsource the pre-submission audit to platforms like PTKD.com (https://ptkd.com) that scan a compiled IPA for these residual external purchase strings and report them before the binary reaches App Review.
    • The Resolution Center reply that works is short, specific, and free of promises. Name the screens you changed, the rule you are now compliant with, and resubmit.

    Published 2026-05-17. Last reviewed 2026-05-17. This article reflects the App Review Guidelines as updated through May 2025, including the US storefront external purchase link provisions.

    • #guideline-3-1-1
    • #in-app-purchase
    • #app-store-rejection
    • #ai-coded-apps
    • #external-purchase-link
    • #storekit
    • #resolution-center

    Frequently asked questions

    Does deleting the Subscribe button alone fix a 3.1.1 rejection?
    Rarely. App Review usually catches the button first, but the same audit will flag onboarding copy, the Settings screen, the help center webview, and any Visit our site to upgrade text that survives the cut. Reviewers retest the full app on resubmission and reject again for any residual pointer, even a paragraph in your About page that mentions Pro pricing on the web.
    Can I keep a Restore Purchases link that quietly calls my server?
    Yes, as long as it is wired to StoreKit and not to your web checkout. A genuine Restore Purchases button using StoreKit 2 transaction history is required by Guideline 3.1.1 anyway. The risk is naming a button Restore Purchases while it actually opens a webview to your account portal where the user can buy a subscription. That pattern reads as a steering link and gets rejected.
    Is my app description on the App Store covered by 3.1.1 too?
    Yes outside the US storefront. The guideline calls out metadata explicitly. A screenshot showing a web checkout, a description line that lists web-only Pro features, or a Promotional Text field that mentions a free trial available on yourdomain.com are all flagged. App Review reads the listing during the same pass as the binary, so the metadata audit has to happen alongside the in-app audit.
    If I make the app free with no monetization at all, am I safe?
    Usually yes, provided no in-app surface references a paid web tier. A common trap with AI apps is a Settings screen that still shows Manage subscription or Upgrade for unlimited messages, even after the marketing team has positioned the iOS build as the free tier. Strip those entry points, the privacy policy mention of paid features, and any in-app help articles that describe the web purchase flow.
    How long does Apple usually take to re-review a 3.1.1 fix?
    Resubmissions after a metadata or guideline rejection often re-enter review within 24 to 48 hours, faster than first submissions in the same window. The timer resets when you upload a new binary or change metadata. If the second pass fails for the same reason, expect a longer wait and a more pointed Resolution Center note, because the reviewer flags the case for a second human read.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free