Few things disrupt a release pipeline like an unexpected rejection email from App Store Connect. Recently, the most common blocker is ITMS-91053: Missing API declaration.
This error occurs when your application—or a third-party SDK it consumes—uses specific Apple APIs that are now classified as "Required Reason APIs," but fails to declare them in a PrivacyInfo.xcprivacy file.
This guide details the root cause of this policy enforcement, how to audit your codebase (including Flutter and React Native projects), and provides the exact XML structure required to resolve the rejection.
The Root Cause: API Fingerprinting
Historically, Apple relied on self-reported "Privacy Nutrition Labels." However, bad actors continued to use benign system APIs to create unique device fingerprints for tracking users without consent.
To enforce privacy at the binary level, Apple now scans your uploaded .ipa for symbols associated with specific APIs. These include:
- File Timestamp APIs (e.g.,
fstat,getattrlist) - System Boot Time (e.g.,
systemUptime) - Disk Space (e.g.,
statfs) - Active Keyboard (e.g.,
activeInputModes) - User Defaults (e.g.,
NSUserDefaults)
If static analysis detects the symbol for NSUserDefaults in your binary, but your app bundle lacks a PrivacyInfo.xcprivacy file explicitly declaring why you use it, the build is flagged.
The Solution
To fix ITMS-91053, you must add a Property List file named PrivacyInfo.xcprivacy to your Xcode target resources. This file must map the API category to an approved "Reason Code."
1. Audit Your Usage
Before creating the file, determine which APIs are triggering the warning. Run the following command in your project root (works for Native, Flutter, and React Native) to search for the most common culprit, User Defaults:
# Search recursively for UserDefaults usage in your code
grep -r "UserDefaults" .
# If you use 3rd party libraries (CocoaPods), search there too
grep -r "UserDefaults" ./Pods
Note: If a third-party SDK is triggering this, the ideal fix is upgrading that SDK to a version that includes its own manifest. However, if you are stuck on an older version or use the API in your own bridging code, you must declare it in your app's manifest.
2. Create the Privacy Manifest
- Open your project in Xcode.
- Go to File > New > File.
- Search for "App Privacy" and select App Privacy File.
- Name it exactly
PrivacyInfo.xcprivacy. - Ensure your main app target is checked in "Targets".
3. Configure the Manifest (The Code)
While you can edit this file using Xcode's Property List visual editor, it is error-prone. The safest method is to edit the source XML directly to ensure the keys match Apple's strict schema.
Right-click PrivacyInfo.xcprivacy > Open As > Source Code.
Paste the following configuration. This example covers User Defaults and Disk Space, the two most common triggers for rejection.
<?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>
<!-- DECLARATION 1: User Defaults -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<!-- CA92.1: Access defaults for app functionality (most common) -->
<string>CA92.1</string>
</array>
</dict>
<!-- DECLARATION 2: Disk Space -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<!-- E174.1: Check disk space to write files -->
<string>E174.1</string>
</array>
</dict>
<!-- DECLARATION 3: File Timestamp -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<!-- C617.1: Inside app bundle/sandbox access -->
<string>C617.1</string>
</array>
</dict>
</array>
<!-- Tracking Usage: Set to true only if you use IDFA -->
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
</dict>
</plist>
4. Selecting the Correct Reason Codes
You cannot simply pick any code; it must match your logic. If you use the wrong code, Apple Review may reject the binary upon manual inspection.
User Defaults (
NSPrivacyAccessedAPICategoryUserDefaults)- CA92.1: Your app reads/writes defaults to store app state, user preferences, or login info. (Use this for 99% of cases).
- 1C8F.1: Apps accessing defaults from an App Group (e.g., sharing data between an App and a Widget).
System Boot Time (
NSPrivacyAccessedAPICategorySystemBootTime)- 35F9.1: Used to measure the elapsed time of events (e.g., calculating session duration).
File Timestamp (
NSPrivacyAccessedAPICategoryFileTimestamp)- C617.1: Accessing timestamps for files inside your app container.
- DDA9.1: Displaying file timestamps to the user (e.g., a file manager app).
Implementation for Cross-Platform Frameworks
Flutter and React Native developers often encounter this issue because the generated Xcode projects do not include this file by default.
Flutter Implementation
Place the file in ios/Runner/PrivacyInfo.xcprivacy. Ensure the file is included in the project via Xcode project references.
- Open
ios/Runner.xcworkspace. - Drag
PrivacyInfo.xcprivacyinto theRunnerfolder in the project navigator. - In the dialog, ensure "Copy items if needed" is unchecked and "Target: Runner" is checked.
React Native Implementation
Place the file in ios/PrivacyInfo.xcprivacy.
- Open
ios/YourApp.xcworkspace. - Right-click your main app group (usually named after your app).
- Select Add Files to "YourApp"...
- Select
PrivacyInfo.xcprivacy. - Ensure targets include your main application build.
Why This Fix Works
When you build your application, Xcode processes the PrivacyInfo.xcprivacy file and embeds it into the root of your application bundle.
Upon upload to TestFlight or the App Store, Apple's ingestion servers perform a symbol check.
- They detect
NSUserDefaultssymbols in the binary. - They look for
NSPrivacyAccessedAPICategoryUserDefaultsin the embedded plist. - If the key exists and contains a valid reason code (like
CA92.1), the check passes.
Conclusion
The ITMS-91053 error is not a bug; it is a mandatory compliance step for modern iOS development. By adding the PrivacyInfo.xcprivacy file and accurately declaring your API usage, you satisfy the static analysis requirements and prevent future rejections.
Ensure you audit your third-party dependencies regularly. While the solution above fixes the immediate rejection, the long-term best practice is for every SDK to bundle its own privacy manifest, which Xcode will automatically aggregate into a single report during the archive process.