Documentation

Privacy Manifest

Generate the PrivacyInfo.xcprivacy file Apple requires inside iOS app bundles since iOS 17. Avoids ITMS-91053 / ITMS-91055 rejections by validating data types, purposes, and Required Reason API codes against Apple's allowlists.

OrbitKit generates the PrivacyInfo.xcprivacy file Apple requires inside the app bundle since iOS 17 / macOS 14. Unlike everything else OrbitKit hosts, this is a downloadable file you drop into your Xcode project — Apple scans the bundled binary at submission time and cross-references this manifest. Missing or invalid declarations cause ITMS-91053 (missing) and ITMS-91055 (invalid) rejections.

What the manifest declares

The file has up to four top-level keys:

Key Purpose
NSPrivacyTracking true only if your app links data to third-party data for ads or data brokers (Apple’s specific tracking definition).
NSPrivacyTrackingDomains Required when NSPrivacyTracking is true. Domains your app contacts for tracking — iOS blocks these network requests unless ATT permission is granted.
NSPrivacyCollectedDataTypes Array describing every category of data your app collects, whether it’s linked to user identity, whether it’s used for tracking, and the purposes for collection.
NSPrivacyAccessedAPITypes Array describing every Required Reason API category your app uses, with Apple-defined reason codes.

Data collection

OrbitKit’s privacy wizard asks the same questions Apple asks. On first read of your manifest, OrbitKit derives a starter configuration directly from your wizard answers — you can refine it from there. Wizard updates do not auto-mutate the manifest after the first save; use the “Sync from Wizard” button to deliberately re-derive when you change your data practices.

The manifest supports 33 data types (matching Apple’s nutrition-label categories), each with three flags:

  • linked — true if the data can be tied to the user’s identity
  • tracking — true if the data is shared with third parties for ad targeting or data brokers (per Apple’s App Tracking Transparency definition)
  • purposes — at least one of: ThirdPartyAdvertising, DeveloperAdvertising, Analytics, ProductPersonalization, AppFunctionality, Other

Required Reason APIs

Apple defines five categories of “required reason” APIs. If your app or any SDK in your bundle uses one, you must declare which Apple-defined reason code applies. The wizard does not derive these — you must declare them explicitly because they’re orthogonal to data collection.

NSPrivacyAccessedAPICategoryFileTimestamp

For accessing file modification, creation, or attribute timestamps.

Code Meaning
DDA9.1 Display file timestamps to the user. Cannot be sent off-device.
C617.1 Access timestamps/metadata of files inside your app container, app group, or your app’s CloudKit container.
3B52.1 Access timestamps/metadata of files the user explicitly granted access to (e.g., via document picker).
0A2A.1 Third-party SDK wrapping file timestamp APIs called only when the host app calls the wrapper.

NSPrivacyAccessedAPICategorySystemBootTime

For reading systemUptime and related boot-time APIs.

Code Meaning
35F9.1 Measure elapsed time between events / timer calculations. Cannot be sent off-device.
8FFB.1 Include boot time in optional bug reports the user explicitly submits.
3D61.1 Calculations to provide functionality visible to the user — non-uptime use.

NSPrivacyAccessedAPICategoryDiskSpace

For reading available or total disk space.

Code Meaning
85F4.1 Display available disk space to the user.
E174.1 Verify sufficient disk space before writing files.
7D9E.1 Include disk space info in optional bug reports the user explicitly submits.
B728.1 Health-research apps detecting low disk space affecting health-data collection.

NSPrivacyAccessedAPICategoryActiveKeyboards

For reading the user’s active input methods (keyboards).

Code Meaning
3EC4.1 Your app is itself a custom keyboard.
54BD.1 Customize UI based on the user’s active keyboards (e.g., layout direction).

NSPrivacyAccessedAPICategoryUserDefaults

For reading or writing NSUserDefaults / UserDefaults.

Code Meaning
CA92.1 Read/write app-only UserDefaults.
1C8F.1 Read/write UserDefaults shared with apps in the same App Group.
C56D.1 Third-party SDK wrapping UserDefaults APIs called only when the host app calls the wrapper.

OrbitKit validates every reason code against the category it’s declared under. A reason code from the wrong category produces a save error — preventing the kind of bug that would otherwise only surface as an ITMS-91055 rejection mid-submission.

Adding the file to your Xcode project

After downloading PrivacyInfo.xcprivacy from your dashboard:

  1. Drag the file into your Xcode project (alongside Info.plist is the convention).
  2. In the Add to targets sheet, ensure the file is added to your app target. If you ship multiple targets (e.g., a Watch extension or App Clip), add it to each one independently.
  3. Verify the file is in the Copy Bundle Resources phase under your target’s Build Phases tab.
  4. Build and submit. Apple’s static analyzer scans your bundled binary and cross-references the manifest at submission time.

If you ship a third-party SDK, the same file goes inside your framework bundle and your SDK customers don’t need to re-declare what’s in your manifest.

One file per target Apple checks each target's manifest independently. The Watch app's manifest is separate from the iOS app's. Plan to have a manifest in each target that uses any required-reason API.

API endpoints

Method Path Description
GET /api/apps/:appId/privacy-manifest JSON config — derives a starter from the wizard if no config saved yet.
PUT /api/apps/:appId/privacy-manifest Save config. Validates against Apple’s allowlists; rejects unknown enum values and cross-category reason-code mismatches.
POST /api/apps/:appId/privacy-manifest/sync-from-wizard Returns a freshly-derived starter from the privacy wizard. Does not save — caller must PUT to persist.
GET /api/apps/:appId/privacy-manifest.xcprivacy Downloads the rendered XML plist. Content-Type: application/xml, Content-Disposition: attachment.
GET /api/privacy-manifest/reference Returns the canonical allowlists (data types, purposes, reason codes per category). Useful for building dashboards or CLIs that need to render valid options.

Common pitfalls

ITMS-91053: Missing API declaration

Your binary uses one of the five Required Reason API categories but the manifest doesn’t declare it. Most common offenders are UserDefaults (almost every app) and FileTimestamp (anything that does file I/O with attributesOfItem(atPath:)).

Run nm on your built .app to find which symbols are present, then declare the corresponding category. Or just declare them all upfront — Apple doesn’t penalize over-declaration.

ITMS-91055: Invalid API reason declaration

You declared a reason code that doesn’t exist or isn’t valid for the category. OrbitKit prevents this at save time; if you got this error, you’re likely uploading a hand-edited manifest.

Privacy label and manifest disagree

The manifest’s NSPrivacyCollectedDataTypes and the App Privacy Details you enter in App Store Connect must agree. App Review flags inconsistencies. OrbitKit derives both from the same wizard data, so they don’t drift unless you’ve manually edited one.

Third-party SDKs need their own manifests

If you ship an SDK, you produce your own PrivacyInfo.xcprivacy inside your framework. The host app’s manifest only declares what the host app’s code does. Your manifest is on top of the host’s, not redundant with it.

Apple references