What the rejection typically looks like
We identified one or more issues with a recent delivery for the following app: [App Name] [Version] ([Build])
ITMS-91053: Missing API declaration - Your app's code in the "Runner" file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryUserDefaults. For more details about this policy, including a list of required reason APIs and approved reasons for their use, see Apple's developer documentation.
Paraphrased example – the exact wording in your message may differ.
What ITMS-91053 actually means
Apple calls a small set of system APIs "required reason APIs" because they could be misused to fingerprint a device, which Apple forbids even when the user allows tracking. Whenever your app, or an SDK inside it, uses one of these APIs, the bundle containing that code must declare an approved reason in a privacy manifest called PrivacyInfo.xcprivacy.
ITMS-91053 is the email App Store Connect sends, usually shortly after an upload is processed, when it finds such an API without a matching declaration. Apple's documentation says that since May 1, 2024, apps that don't describe their use of required reason APIs aren't accepted by App Store Connect. Before that date the email said no action was required yet, which is why older forum threads call it a harmless warning.
Three details matter for the fix:
- The email names a file. "Your app's code in the
Runnerfile" points to your main executable. A path likeFrameworks/SomeSDK.framework/SomeSDKpoints to a dynamic framework. The declaration has to live in the manifest of that exact bundle. - Reasons must be true. You may use the API and derived data only for the declared reasons, never for tracking.
- Platforms: the rule covers iOS, iPadOS, tvOS, visionOS and watchOS.
Related privacy manifest errors
| Code | What it means |
|---|---|
ITMS-91053 | A required reason API is referenced but not declared. |
ITMS-91056 | A privacy manifest is invalid: malformed plist, unexpected keys or values, reason codes that don't belong to the category, or empty arrays. Apple requires valid manifests for submissions since November 12, 2024 (see TN3181). |
ITMS-91061 | An SDK from Apple's list of commonly used SDKs ships without its own privacy manifest. Apple's emails cite February 12, 2025 as the start date for new apps and for updates that add a listed SDK. |
ITMS-91065 | A listed SDK used as a binary dependency (for example a prebuilt XCFramework) is missing its signature. See Apple's guide on verifying the origin of XCFrameworks. |
Why your build gets flagged
- No manifest at all. Many older native projects and cross-platform templates ship without one.
- The file isn't bundled. Without target membership it never reaches the root of
YourApp.app. Check Build Phases → Copy Bundle Resources. - An incomplete list. You declared UserDefaults, but your code also reads
creationDateormodificationDateviaFileManager(file timestamp) or checks free space before a download (disk space). - Statically linked dependencies. CocoaPods libraries built as static libraries end up inside your main executable, so their API usage is attributed to your app's file. Expo's docs note that Apple doesn't correctly parse all manifests from static CocoaPods dependencies.
- App extensions. A widget, share extension or notification service extension is a separate bundle with its own executable. If it uses UserDefaults, it needs its own manifest.
- Outdated SDKs. Old Firebase, Facebook SDK, Alamofire or Flutter plugin versions predate privacy manifests, often with ITMS-91061 in the same email.
- A regenerated native project.
expo prebuild --clean, re-adding a Cordova platform or a Unity "Replace" build silently drops a hand-added manifest.
Rejected or stuck? Talk to an App Specialist – for free.
Book a free consultation call: we look at your rejection or setup, explain the fastest way forward and tell you honestly whether you need us. Prefer to hand it off? Book our AI-powered + human-powered service and we take care of it.
Required reason API categories and reason codes
As of October 2026, Apple lists five categories. The list changes from time to time, so check the official page before relying on these codes.
Category (NSPrivacyAccessedAPIType) | Typical APIs | Common reason codes |
|---|---|---|
NSPrivacyAccessedAPICategoryUserDefaults | UserDefaults | CA92.1 app-only data; 1C8F.1 shared within your App Group; C56D.1 SDK wrapper; AC6B.1 reading MDM managed app configuration |
NSPrivacyAccessedAPICategoryFileTimestamp | creationDate, modificationDate, contentModificationDateKey, stat/fstat/lstat, getattrlist | C617.1 files in your container, App Group or CloudKit container; 3B52.1 files the user granted access to; DDA9.1 showing timestamps to the user; 0A2A.1 SDK wrapper |
NSPrivacyAccessedAPICategorySystemBootTime | systemUptime, mach_absolute_time() | 35F9.1 measuring elapsed time between in-app events or for timers; 8FFB.1 absolute timestamps for in-app events |
NSPrivacyAccessedAPICategoryDiskSpace | volumeAvailableCapacityKey, volumeTotalCapacityKey, systemFreeSize, statfs/statvfs | E174.1 checking space before writing files or freeing space when low; 85F4.1 showing disk space to the user |
NSPrivacyAccessedAPICategoryActiveKeyboards | activeInputModes | 54BD.1 adapting the UI to the active keyboard; 3EC4.1 custom keyboard apps |
Apple also lists narrower reasons, for example for optional user-submitted bug reports (3D61.1 boot time, 7D9E.1 disk space) and health research apps (B728.1). The SDK wrapper reasons (C56D.1, 0A2A.1) may only be declared by third-party SDKs. Most reasons forbid sending the data, or anything derived from it, off the device, and E174.1 and 54BD.1 require behavior that visibly changes for the user. If no reason covers your use, use Apple's new reason request form instead of a code that "sort of" fits.
How to fix ITMS-91053 step by step
- List every flagged pair from the email: file path plus API category.
- Sort the paths. Your main executable (your app name,
RunnerorApp) means you fix your app's manifest. AFrameworks/…path means the SDK needs an updated version with its own manifest, unless it's a framework target you build yourself, which then needs its own manifest. - Create the app manifest if it's missing: in Xcode choose File → New → File from Template (File → New → File in older versions), pick App Privacy under Resource and tick your app target. Keep the default name
PrivacyInfo.xcprivacy. - Add one dictionary per category. Turn on Editor → Raw Keys and Values or edit the file as source:
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array><string>CA92.1</string></array>
</dict>
</array> - Cover statically linked code. If your main executable is flagged for a category your own code doesn't use, a static library compiled into it probably does. First update that library to a version that bundles its own manifest. If the email still names your main executable, do what React Native's and Expo's tooling does: add the category to your app's manifest with a reason that matches what the library actually does in your app.
- Give extensions their own manifest by repeating step 3 for every extension target the email names.
- Update flagged SDKs. Don't copy an SDK's declarations into your app's manifest to silence a framework path. Apple's DTS engineers say the app's manifest must describe only the app's own practices.
- Validate. Run
plutil -lint PrivacyInfo.xcprivacy. It only checks plist syntax, so also confirm every category string and reason code exactly matches Apple's list and no array is empty. Then archive, Control-click the archive in Window → Organizer and choose Generate Privacy Report to see which bundles declare what. - Increment the build number (
CFBundleVersion) and upload again. If no new ITMS-91053 (or ITMS-91056) email arrives after processing, the declarations were accepted.
Finding the API usage, including in dependencies
The email names a category, not a line of code. Search sources first, then binaries.
Search source code and vendored dependencies
grep -rnE "UserDefaults|systemUptime|mach_absolute_time|creationDate|modificationDate|volumeAvailableCapacity|systemFreeSize|statfs|activeInputModes|getattrlist" ios/ Pods/ --include=*.swift --include=*.m --include=*.mm --include=*.c --include=*.cpp
Add node_modules/, your Flutter .pub-cache plugin folders or Assets/Plugins/ depending on your stack.
Inspect the compiled binary
Export an IPA, unzip it and check the imported symbols of the flagged executable:
nm -u Payload/YourApp.app/YourApp | grep -E "NSUserDefaults|_stat|_fstat|_lstat|getattrlist|mach_absolute_time|NSFileModificationDate|NSFileCreationDate|NSFileSystemFreeSize|NSURLCreationDateKey|NSURLContentModificationDateKey|NSURLVolume.*CapacityKey"
Methods such as systemUptime and activeInputModes appear as selector strings, so also run strings -a on the binary and grep for them. Treat these patterns as a practical heuristic, not an official Apple list. find Payload -name PrivacyInfo.xcprivacy lists which bundles ship a manifest; a flagged framework missing from that list needs an SDK update.
Apple's email says your code references the APIs. In practice developers report that the check works on what the binary references, not what runs, so dead code from an unused SDK feature can still trigger it.
Fixes for Flutter, React Native, Capacitor, Cordova and Unity
Many frameworks are on Apple's list of commonly used SDKs, including Flutter, hermes, Capacitor, Cordova, UnityFramework and popular plugins such as shared_preferences_ios, path_provider and url_launcher. Old framework versions therefore cause both ITMS-91053 and ITMS-91061.
Flutter
Upgrade to a current stable Flutter release and run flutter pub upgrade (and flutter pub outdated to spot plugins stuck on old major versions); the official plugins added their own manifests in 2024. Then open ios/Runner.xcworkspace, add the manifest to the Runner target and declare exactly the categories the email reports for Runner, for example UserDefaults.
React Native and Expo
React Native 0.74.1 and later (plus later 0.72 and 0.73 patch releases) create ios/YourApp/PrivacyInfo.xcprivacy during pod install if it's missing and merge required-reason entries from your pods into it. Review the result. On Expo, declare everything under expo.ios.privacyManifests in app.json, including reasons from libraries' manifests, so prebuild and EAS Build regenerate it.
Capacitor
The Capacitor docs list minimum versions (4.8.2+, 5.7.4+, and any 6.x or 7.x release). Add the manifest to the App target in ios/App; for @capacitor/preferences the docs recommend UserDefaults with CA92.1. Check @capacitor/filesystem and community plugins for file timestamp and disk space usage.
Cordova
Use cordova-ios 7.1.0 or later and define the manifest in config.xml inside <platform name="ios"><privacy-manifest>…</privacy-manifest></platform>, then add the reasons your plugins document to that block.
Unity
Unity 2021.3.35f1, 2022.3.18f1, 2023.2.7f1 and later include the engine's reasons automatically. If your C# code uses PlayerPrefs (UserDefaults), file timestamps or disk space checks, save a manifest in Assets/Plugins so every Xcode export includes it.
Responding: there is no App Review to reply to
ITMS-91053 comes from automated processing, so there is no App Store Connect thread to answer and nothing to appeal to the App Review Board. The way forward is a corrected binary with a higher build number. A few situations still need a message:
- Your use isn't covered by any reason. Submit Apple's new-reason request form and ship a version without that API in the meantime.
- The email persists after a verified fix (manifest at the bundle root, lints cleanly, every flagged category covered). Contact Apple Developer Support using the template below.
- App Review rejects the build later for privacy labels that don't match your SDKs. That's a different issue. See our guides on Guideline 5.1.1 Data Collection and Storage and, if
NSPrivacyTrackingor tracking domains are involved, Guideline 5.1.2 Data Use and Sharing.
How to prevent ITMS-91053 next time
- Treat the manifest as source code and review it in every pull request that adds a dependency.
- Add CI checks. After archiving, unzip the IPA, lint every
PrivacyInfo.xcprivacy, fail if the app bundle has none, and diffnm -uoutput against a baseline so new required-reason symbols get noticed. - Upload to TestFlight early. A nightly CI upload catches ITMS-91053 days before release day.
- Keep SDKs current instead of jumping three major versions under deadline pressure.
- Use AI-assisted checks with care. They map symbols to categories well, but a human must confirm each reason code matches what the app really does.
If you'd rather not untangle manifests across native code, plugins and extensions yourself, appsubmitter.io sets up CI/CD pipelines with these checks and handles the submission. Code changes are discussed and quoted upfront. Book a free consultation call to go through your ITMS emails together.
Template: how to reply to App Review
Adapt this template to your situation. Keep it factual, short and specific – and only claim what you have actually changed.
Checklist before you resubmit
- Every API category named in the ITMS-91053 email has a matching NSPrivacyAccessedAPITypes dictionary in the manifest of the bundle the email names.
- The file is named exactly PrivacyInfo.xcprivacy, belongs to the app target and appears under Build Phases → Copy Bundle Resources.
- The unzipped IPA contains Payload/YourApp.app/PrivacyInfo.xcprivacy at the root of the app bundle.
- Each app extension whose executable uses a required reason API ships its own privacy manifest.
- Every reason code is listed for its category, e.g. CA92.1 only under UserDefaults and C617.1 only under FileTimestamp.
- No NSPrivacyAccessedAPITypes or NSPrivacyAccessedAPITypeReasons array is empty, and the file passes plutil -lint (otherwise expect ITMS-91056).
- The declared reasons match real behavior, and no data derived from these APIs leaves the device unless the reason allows it.
- Every SDK from Apple's commonly used list ships its own manifest, and binary XCFrameworks are signed.
- Cross-platform projects keep the manifest in app.json, config.xml or Assets/Plugins so it survives a regenerated native project.
- The build number (CFBundleVersion) is higher than the flagged upload.
Frequently asked questions
Is ITMS-91053 a warning or a rejection?
Which reason code should I use for UserDefaults?
CA92.1 if only your app reads and writes the values. Use 1C8F.1 if you share them with extensions, App Clips or apps in the same App Group. C56D.1 is only for third-party SDKs that wrap UserDefaults for the host app. AC6B.1 covers reading the MDM managed app configuration key com.apple.configuration.managed or writing com.apple.feedback.managed.I added PrivacyInfo.xcprivacy but still get ITMS-91053. Why?
Can I declare an SDK's API usage in my own app's privacy manifest?
Is there a Google Play equivalent of the privacy manifest?
Does the privacy manifest replace the App Privacy labels in App Store Connect?
Official source: Apple Developer Documentation – Describing use of required reason API. Store policies change regularly – always check the current version. This guide is independent advice and not affiliated with Apple or Google.