Skip to main content

Solved: ITMS-91053 "Missing API Declaration" for Flutter iOS Apps

 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 UserDefaultsstatfstat) 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:

  1. Transitive Dependencies: You might not be writing Swift code, but your Flutter plugins are. Specifically, shared_preferences uses NSUserDefaults, and many caching or image loading libraries (like sqflite or flutter_cache_manager) access file timestamps (fstat).
  2. 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.xcprivacy file, it flags the build.
  3. 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

  1. Open your Flutter project's ios/Runner.xcworkspace in Xcode.
  2. Right-click the Runner folder (the group, not the project root) and select New File.
  3. Search for App Privacy and select the App Privacy file type.
  4. Name it exactly PrivacyInfo.xcprivacy.
  5. 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:

  1. Click on your Project in the left navigator.
  2. Select the Runner Target.
  3. Go to the Build Phases tab.
  4. Expand Copy Bundle Resources.
  5. Verify PrivacyInfo.xcprivacy is 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 UserDefaults to access app data strictly within the app itself. This is the standard use case for the Flutter shared_preferences plugin (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 (creationDatemodificationDate) 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.