Fix ITMS-91053: Missing API Declaration in PrivacyInfo.xcprivacy

Content edited . This editorial update does not represent a new runtime test.

On this page

ITMS-91053: Missing API declaration identifies a required-reason API category used by an app or included SDK. Trace the reported category to the responsible code, choose an approved reason that fits that use, and inspect the manifest in the actual submitted bundle. Adding a plist that parses successfully is only one part of the fix.

Identify the category and the code owner

  1. Save the full App Store Connect message, including the category, affected binary or bundle path if supplied, app version and build number.
  2. Inspect your code and dependencies for that API. For a UserDefaults warning, search for UserDefaults, NSUserDefaults and any wrappers or SDKs that access preferences. Text search does not prove a compiled dependency is free of the API.
  3. Decide whether the use belongs to the app, an extension or an SDK. Inspect that target or dependency’s manifest and version.
  4. Read the current approved reasons, and document how the actual behavior fits the selected reason. Do not add unrelated categories to silence a warning.

The historical 2024 case involved NSPrivacyAccessedAPICategoryUserDefaults. Apple’s required-reason guidance separates app and SDK responsibilities. Permission prompts and tracking consent do not replace these declarations.

A complete UserDefaults manifest example

This example assumes the app reads and writes its own private preference information. CA92.1 is not a blanket reason for App Group, managed preferences or SDK use; compare those cases with Apple’s current approved reasons. Review the entire usage, not just one convenient call site.

<?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>CA92.1</string>
            </array>
        </dict>
    </array>
</dict>
</plist>

Save as PrivacyInfo.xcprivacy. This is a standalone plist example for this one declaration, not a complete assessment of your app’s privacy practices. If a manifest already exists, merge the entry into its existing array and retain other API, tracking and data-collection declarations. Do not create a second root dictionary, duplicate a category or overwrite the existing manifest with this example.

Original Xcode privacy manifest configuration

Add it to the right target and inspect the archive

Use Xcode’s App Privacy file template if needed, then check the file’s target membership and resource build phase for the intended product. Archive the same scheme/configuration you will submit. A file in the project navigator alone does not establish that it was bundled.

For an iOS app, the app manifest belongs at Example.app/PrivacyInfo.xcprivacy. A macOS or Mac Catalyst app uses Example.app/Contents/Resources/PrivacyInfo.xcprivacy. Framework and package locations depend on their bundle layout; consult Apple’s packaging guide and inspect the SDK’s own product.

These read-only macOS commands inspect a real archive after you replace the example paths:

audit_archive='/absolute/path/Example.xcarchive'
find "$audit_archive/Products/Applications" -name PrivacyInfo.xcprivacy -print

No output means this search found no manifest under that directory; first check that the archive path exists. Multiple results are normal when dependencies or extensions contain their own manifests. Match each path to its bundle owner; finding one file does not cover every executable.

# Example iOS app manifest; use the actual path from the search.
audit_manifest="$audit_archive/Products/Applications/Example.app/PrivacyInfo.xcprivacy"
plutil -lint "$audit_manifest"
plutil -extract NSPrivacyAccessedAPITypes json -o - "$audit_manifest"

For the example, the extracted array should contain the UserDefaults category and the reason array ["CA92.1"]. For a real app it may contain other justified declarations. Syntax errors, missing keys, wrong types and an absent bundle file are distinct failures. plutil -lint does not check whether a reason is eligible for the code’s behavior.

Close the loop with the submitted build

  1. Check every manifest found in the archive for valid plist syntax and intended declarations. Record archive path, scheme, configuration, version/build number and SDK versions.
  2. If the reported use belongs to an SDK, obtain its correct manifest or an appropriate SDK update from its maintainer. The SDK must declare its own required-reason API use; the app declaration is not a substitute.
  3. Upload the inspected archive through your usual workflow and inspect the resulting App Store Connect messages. Compare category and bundle path if ITMS-91053 remains.
  4. Keep the upload receipt or new warning as evidence. Successful syntax validation or removal of this warning does not guarantee approval for unrelated review issues.

Verification evidence for this editorial update (2026-10-14): the complete XML example passed macOS plutil -lint; extraction returned the stated UserDefaults category and reason. The archive-search commands also found and inspected the manifest in a synthetic iOS bundle fixture. That fixture was not an Xcode archive or a signed app. No app was archived, uploaded or accepted during this update; actual target integration and submission remain unverified.

Related: Subscription policy and EULA links concern visible documents rather than required-reason declarations.

← All articles