If you opened App Store Connect this morning and saw a red banner with ITMS-91053 next to your build number, the build did not fail for a code signing reason or a metadata reason. It failed because Apple's automated check found a call to one of the Required Reason APIs without a matching declaration in your privacy manifest. The fix is mechanical once you know which API and which reason code.
Short answer
ITMS-91053 means your build references at least one Required Reason API without an entry in a PrivacyInfo.xcprivacy file. The fix is to add (or update) the privacy manifest in Xcode, list the named API category under NSPrivacyAccessedAPITypes, and pair it with one of Apple's approved reason codes. The warning email names the API category so you do not have to guess. According to Apple's privacy manifest documentation, the file is a property list shipped at the root of the app bundle, and each third-party SDK on Apple's list must ship its own.
What you should know
- The deadline already passed. Since May 1, 2024, App Store Connect rejects new submissions that touch a Required Reason API without declaring it.
- The warning email names the category. Look for strings like NSPrivacyAccessedAPICategoryUserDefaults, NSPrivacyAccessedAPICategoryFileTimestamp, NSPrivacyAccessedAPICategorySystemBootTime, or NSPrivacyAccessedAPICategoryDiskSpace.
- Each SDK declares its own usage. Your app manifest covers your code; framework manifests cover the framework's code. You cannot declare reasons on behalf of a third-party SDK.
- The reason codes are short alphanumeric strings. Apple publishes the allowed list (examples: CA92.1, C617.1, 35F9.1, 1C8F.1). Custom strings are not accepted.
- Builds for TestFlight can slip through. Some builds reach internal testers with only a warning, then fail when promoted to the store. Treat any warning as blocking.
What is the Required Reason API list and why does Apple check for it?
The short answer is that Apple keeps a list of system APIs that have been abused for device fingerprinting, and any call to one of those APIs has to be paired with a documented reason. The categories in scope today are file timestamp APIs, system boot time APIs, disk space APIs, active keyboard APIs, and NSUserDefaults. Each has its own approved reasons, and Apple's Describing use of required reason API page is the authoritative list.
The check is automated and runs at upload time in App Store Connect. The reviewer machine scans the compiled binary, finds the symbols that map to Required Reason APIs, then looks for matching entries in every privacy manifest inside the app bundle (your app manifest plus one per included framework). If a symbol appears in the binary and no manifest declares it, App Store Connect emits ITMS-91053 with the missing category name. The check is symbol-based, not source-based, so Swift, Objective-C, Hermes-compiled JavaScript, and Flutter Dart all run through the same scanner once they reach the linker stage.
In practice, very few apps trigger this for first-party code. The usual offender is a transitive dependency that has not been updated since May 2024.
How do you decode the ITMS-91053 email into a fix?
The email follows a stable shape. Apple lists the API category once, then the symbol once, then the framework that contains the symbol. A typical message reads: "ITMS-91053: Missing API declaration: Your app's code references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryUserDefaults."
Three steps cover most cases.
- Open the email and write down each category named after "API categories:". There may be one, or there may be three or four. Each is a separate fix.
- For each category, decide whether it is your code or a dependency. Run
nm -gU $(find . -name '*.framework' -o -name '*.xcframework')inside the Xcode build artifacts and grep for the matching symbol. NSUserDefaults maps to__NSUserDefaultsandsetObject:forKey:. File timestamp maps tostat,fstat, andgetattrlist. System boot time maps tomach_absolute_timeandclock_gettime. Disk space maps tostatfs,volumeAvailableCapacity, andNSFileSystemFreeSize. - If the symbol lives in your code, add the category to your top-level PrivacyInfo.xcprivacy with the matching reason code. If it lives in a third-party framework, update the dependency to a version that ships its own manifest, or replace it.
The trap here is searching the source tree for the symbol name. Many of these calls live deep inside compiled .a static archives that ship with vendored SDKs, so grep on the source repo will return zero matches even when the binary clearly contains the call.
How do you create and fill in PrivacyInfo.xcprivacy?
In Xcode, choose File > New > File, type "privacy" in the filter, and pick App Privacy from the Resource list. Check the target you want to attach the file to, then click Create. Xcode writes a property list named PrivacyInfo.xcprivacy at the project root and adds it to the target's Copy Bundle Resources phase. As Antoine van der Lee's writeup on ITMS-91053 explains, the file ships at the root of the compiled app bundle and is the only place App Store Connect looks for first-party declarations.
For each Required Reason API category in scope, add an entry under the NSPrivacyAccessedAPITypes key. Each entry is a dictionary with two keys: NSPrivacyAccessedAPIType (the category string) and NSPrivacyAccessedAPITypeReasons (an array of approved reason codes). The reason codes are short identifiers like CA92.1 for "access information about the file or directory created or modified by the user" or 1C8F.1 for "access user defaults that read and write information shared in an App Group." Apple publishes the full list of allowed reasons for each category in TN3183: Adding required reason API entries to your privacy manifest.
A minimal manifest for an app that reads and writes NSUserDefaults inside an App Group, checks file timestamps for cache invalidation, and reads disk space for an offline mode looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array><string>1C8F.1</string></array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array><string>C617.1</string></array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array><string>85F4.1</string></array>
</dict>
</array>
</dict>
</plist>
Rebuild, archive, and re-upload. The check runs again at upload time, and the ITMS-91053 message disappears once every named symbol has a matching declaration.
Which APIs trigger which category?
This is the mapping that saves the most time when reading the warning email. The categories, the underlying functions, and one common approved reason for each look like this.
| Category string | Underlying APIs (symbols you will find with nm) | Typical legitimate reason | Sample reason code |
|---|---|---|---|
| NSPrivacyAccessedAPICategoryUserDefaults | NSUserDefaults, setObject:forKey:, objectForKey: | Read or write user preferences inside your own app or App Group | 1C8F.1 |
| NSPrivacyAccessedAPICategoryFileTimestamp | stat, fstat, getattrlist, NSFileCreationDate, NSURLContentModificationDateKey | Display file dates to the user or invalidate a local cache | C617.1 |
| NSPrivacyAccessedAPICategorySystemBootTime | mach_absolute_time, clock_gettime with CLOCK_UPTIME_RAW, systemUptime | Measure short intervals for performance instrumentation | 35F9.1 |
| NSPrivacyAccessedAPICategoryDiskSpace | statfs, statvfs, volumeAvailableCapacity, NSFileSystemFreeSize | Warn the user before downloading or writing a large file | 85F4.1 |
| NSPrivacyAccessedAPICategoryActiveKeyboards | UITextInputMode.activeInputModes | Provide a feature that requires knowledge of the user's active keyboards (rare) | 3EC4.1 |
The list is short because Apple kept the scope deliberately narrow. The full catalog of approved reasons is in TN3183 above; pick the one that matches how your code actually uses the API. Picking a reason that does not match (for example, claiming an analytics measurement reason for a UserDefaults call that is really storing a session token) is a Guideline 5.1.1 risk, not just a manifest hygiene risk.
How do you handle missing manifests in third-party SDKs?
The short answer is that you cannot fix a missing manifest from inside your app. The framework binary has to ship its own PrivacyInfo.xcprivacy at the root of its .framework or .xcframework bundle. If it does not, App Store Connect attributes the missing declaration to your app, even though the offending symbol lives in someone else's code.
The practical path is to update. As documented in the Firebase iOS SDK privacy manifest discussion, Firebase 10.22.1 was the version that drew ITMS-91053 reports across analytics, Crashlytics, and Firestore. The fix shipped in subsequent releases, and most major SDKs (AppsFlyer, OneSignal, Sentry, Bugsnag, Adjust, Branch) followed the same pattern by mid-2024. If a small or stale SDK still has no manifest, raise an issue on the repo, pin a fork with the manifest added, or replace the dependency.
For builders who want an external automated read of the binary before submission, PTKD.com (https://ptkd.com) is one of the platforms focused on pre-submission scanning aligned with OWASP MASVS for no-code and vibe-coded apps. The scan flags missing privacy manifests inside the IPA the same way App Store Connect does, but on demand and before the upload.
What to watch out for
A few details cost teams a resubmission cycle even after the manifest is added.
First, the manifest has to be inside the compiled bundle, not just in the Xcode project. If the file is not added to the target's Copy Bundle Resources phase, the archive ships without it and App Store Connect emits the same warning. Verify the IPA after archiving: unzip it, then check that Payload/<AppName>.app/PrivacyInfo.xcprivacy exists and contains the expected keys.
Second, CocoaPods and Carthage sometimes strip privacy manifests during dependency resolution if the podspec or Cartfile does not list the file as a resource. Pin to CocoaPods 1.15.2 or later, which added explicit support for shipping privacy manifests from pods. Run pod install again after the upgrade and confirm the file is present inside the framework bundle.
Third, dynamic frameworks built with use_frameworks! need the manifest inside the framework binary, not loose in the Pods directory. The build step that copies the manifest into the framework runs only when the resource is declared correctly in the podspec.
Fourth, the myth that turning off a feature avoids the check. Apple's scanner looks at symbols present in the binary. If the function is linked, the declaration is required, even if the code path is dead. Strip-unused symbol passes that depend on the linker (dead code stripping at the Swift level) help; conditional compilation that removes the import entirely is cleaner.
Key takeaways
- Read the email carefully. ITMS-91053 names the category in plain text; the fix starts there, not in your source tree.
- Audit your dependencies first. Most ITMS-91053 reports trace to a vendored SDK that has not shipped its own PrivacyInfo.xcprivacy. Update or replace before you touch your own manifest.
- Match reasons to actual usage. Approved reason codes like 1C8F.1, C617.1, 35F9.1, and 85F4.1 each map to a specific behavior; pick the one that describes what your code does.
- Verify the manifest is in the IPA. Unzip the archive and confirm
PrivacyInfo.xcprivacyis at the bundle root before resubmitting. - Some teams outsource the pre-submission scan. Platforms like PTKD.com (https://ptkd.com) check the compiled IPA for missing privacy manifests and Required Reason API mismatches before the build reaches App Store Connect, which shortens the loop on rejections like ITMS-91053.




