Few things stall a release cycle faster than a vague rejection email from App Store Connect. If you have recently uploaded a Flutter build, you likely encountered ITMS-91053: Missing API declaration.
The email typically looks like this:
"The app references non-public selectors in Payload/Runner.app/Runner: ... Although the use of these APIs is not prohibited, you must provide a valid reason for their use in your app's privacy manifest."
This guide details exactly why this is happening to your Flutter application and provides the PrivacyInfo.xcprivacy configuration required to resolve it immediately.
The Architecture of the Error
Starting May 1, 2024, Apple enforces the declaration of "Required Reason APIs." These are standard iOS APIs (like UserDefaults, stat, fstat) that have legitimate uses but are frequently exploited for device fingerprinting.
In a native iOS context, you know exactly when you use UserDefaults. in Flutter, this abstraction is leaky. The error occurs because:
- Transitive Dependencies: You might not be writing Swift code, but your Flutter plugins are. Specifically,
shared_preferencesusesNSUserDefaults, and many caching or image loading libraries (likesqfliteorflutter_cache_manager) access file timestamps (fstat). - Static Analysis: App Store Connect statically analyzes your binary. If it finds symbols for these APIs but fails to find a corresponding justification in a
PrivacyInfo.xcprivacyfile, it flags the build. - The Manifest Merger: While plugin authors should include their own privacy manifests, many have not updated yet. As the app owner, the responsibility falls on you to declare these usages at the application level to ensure the binary is compliant.
The Fix: Implementing PrivacyInfo.xcprivacy
To fix this, you must explicitly declare the APIs used by your Flutter runtime and plugins.
1. Create the Privacy Manifest
- Open your Flutter project's
ios/Runner.xcworkspacein Xcode. - Right-click the Runner folder (the group, not the project root) and select New File.
- Search for App Privacy and select the App Privacy file type.
- Name it exactly
PrivacyInfo.xcprivacy. - CRITICAL: In the target selection dialog, ensure the Runner target is checked. If this file is not included in the bundle resources, the fix will fail.
2. Configure the API Declarations
You can edit this file using Xcode's Property List editor, but for precision and to avoid human error, it is safer to edit the source code directly.
Right-click PrivacyInfo.xcprivacy in Xcode, select Open As > Source Code, and replace the contents with the following XML. This covers the two most common Flutter violations: UserDefaults (used by shared_preferences) and FileTimestamp (used by various IO plugins).
<?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 for UserDefaults (shared_preferences) -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<!-- Declaration for FileTimestamp (file I/O, caching) -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
<!-- Add DiskSpace or SystemBootTime here if your specific plugins require it -->
</array>
</dict>
</plist>
3. Verify Inclusion
To ensure the file is actually packaged into your IPA:
- Click on your Project in the left navigator.
- Select the Runner Target.
- Go to the Build Phases tab.
- Expand Copy Bundle Resources.
- Verify
PrivacyInfo.xcprivacyis present in this list.
Why This Configuration Works
The XML above addresses the specific reason codes Apple validates against. Using generic or incorrect codes will result in a rejection for "Invalid Reason."
The UserDefaults Declaration
- API Category:
NSPrivacyAccessedAPICategoryUserDefaults - Reason Code:
CA92.1 - Explanation: This code declares that your app accesses
UserDefaultsto access app data strictly within the app itself. This is the standard use case for the Fluttershared_preferencesplugin (storing flags, settings, or simple key-value pairs).
The FileTimestamp Declaration
- API Category:
NSPrivacyAccessedAPICategoryFileTimestamp - Reason Code:
C617.1 - Explanation: This code declares that your app accesses file timestamps (
creationDate,modificationDate) to display files to the user or manage file contents (e.g., cache invalidation). This covers the majority of Flutter file system plugins that check if a file has changed or needs to be cleaned up.
Conclusion
The ITMS-91053 warning is not a bug in your code, but a compliance requirement of the modern iOS ecosystem. By adding a correctly configured PrivacyInfo.xcprivacy to your Runner target, you satisfy Apple's static analyzer and acknowledge the underlying APIs your Flutter plugins consume.
Once you have committed this file to your repository, bump your build number and resubmit. The warning will disappear.