Deeplinkly

Glossary/iOS platform and privacy

Required Reason API

Definition

A required reason API is an iOS API that Apple has designated as usable only if the calling bundle declares an approved reason for using it in its privacy manifest.

Apple singled out a small set of APIs that had been used for device fingerprinting and required every caller to say, in machine-readable form, why they call them. The APIs themselves still work exactly as before — nothing is blocked at runtime — but a build that uses one without a declared reason in its privacy manifest is rejected automatically at submission.

The five categories

Each category covers a group of APIs, and each has its own set of approved reason codes. You declare the category plus one or more codes from that category's list.

Required reason API categories and the calls each one covers.
Category valueCoversTypical caller
NSPrivacyAccessedAPICategoryUserDefaultsNSUserDefaults reads and writesAlmost every app and SDK
NSPrivacyAccessedAPICategoryFileTimestampCreation and modification dates via NSFileManager, stat, NSURL resource valuesCaching layers, file browsers
NSPrivacyAccessedAPICategorySystemBootTimesystemUptime, kern.boottimePerformance measurement, session timing
NSPrivacyAccessedAPICategoryDiskSpaceFree and total volume capacityDownloaders, media caches
NSPrivacyAccessedAPICategoryActiveKeyboardsThe list of active keyboardsCustom keyboard apps

Why these five

Each one was a durable, permission-free signal usable for device fingerprinting: boot time and free disk space are near-unique per device, and file timestamps and keyboard lists narrow an identity fast. Apple did not remove them — they have legitimate uses — it required an on-record reason, which makes fingerprinting a declarable act rather than a silent one.

The declaration

It goes in NSPrivacyAccessedAPITypes, one dictionary per category. Reason codes are short strings of the form XXXX.1, and each one is only valid inside its own category.

PrivacyInfo.xcprivacy — the required-reason section
<key>NSPrivacyAccessedAPITypes</key>
<array>
  <dict>
    <key>NSPrivacyAccessedAPIType</key>
    <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
    <key>NSPrivacyAccessedAPITypeReasons</key>
    <array>
      <!-- Reading values this app itself wrote -->
      <string>CA92.1</string>
    </array>
  </dict>

  <dict>
    <key>NSPrivacyAccessedAPIType</key>
    <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
    <key>NSPrivacyAccessedAPITypeReasons</key>
    <array>
      <!-- Timestamps of files inside the app's own container -->
      <string>C617.1</string>
    </array>
  </dict>

  <dict>
    <key>NSPrivacyAccessedAPIType</key>
    <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
    <key>NSPrivacyAccessedAPITypeReasons</key>
    <array>
      <!-- Checking there is room before writing -->
      <string>E174.1</string>
    </array>
  </dict>
</array>
Frequently used reason codes, by category.
CategoryCodeApproved reason
User defaultsCA92.1Access values the app itself wrote
User defaults1C8F.1Access values in an App Group shared with apps from the same developer
User defaultsC56D.1Read managed app configuration set by an MDM profile
User defaultsAC6B.1An SDK wrapping the API on behalf of the host app
File timestampDDA9.1Display a file's timestamp to the person using the device
File timestampC617.1Timestamps of files inside the app or App Group container
File timestamp3B52.1Timestamps of files the user explicitly granted access to
Disk space85F4.1Display available space to the person using the device
Disk spaceE174.1Check for sufficient space before writing
System boot time35F9.1Measure elapsed time between events within the app
Active keyboards3EC4.1The app is itself a custom keyboard

Verify the codes against Apple's current list

Apple maintains the authoritative table under "Describing use of required reason API" in the developer documentation and has extended it since launch. Codes are also category-specific — a valid code in the wrong category is rejected as ITMS-91054. Treat the table above as a starting point, not a substitute for the source.

Finding the caller

The API call is frequently inside a dependency, which is why an app that uses none of these APIs in its own source gets rejected for one. Both halves are findable.

Locate required-reason API use
# Your own code
grep -rn "UserDefaults\|systemUptime\|volumeAvailableCapacity" Sources/

# Symbols in a prebuilt framework
nm -u SomeSDK.framework/SomeSDK 2>/dev/null | \
  grep -iE "userdefaults|systemuptime|statfs|activeInputModes"

# Which dependencies ship a manifest at all
find . -name "PrivacyInfo.xcprivacy"

# Authoritative answer: Xcode > Product > Archive >
# Organizer > Generate Privacy Report
What to do once you know the caller.
CallerAction
Your own codeAdd the category and the reason that truthfully describes the call
An SDK with a manifestNothing — its declaration covers its own bundle
An SDK without a manifestUpdate it; the vendor must declare, you cannot declare for them
An abandoned SDKReplace or vendor it — there is no workaround at submission
Code you can removeRemove the call; the cheapest fix when the use is incidental

Declare the true reason, not the convenient one

ITMS-91055 exists specifically for reason codes that do not match observed behaviour. Picking a code because it is the shortest path through review is the one approach that turns a mechanical fix into a review conversation.

What this means for attribution SDKs

Attribution is the category of SDK this rule was aimed at, because boot time, disk space and file timestamps are the classic inputs to a device fingerprint. The practical consequences for anyone choosing an SDK are worth stating plainly.

  • An SDK that reads boot time and free disk space and cannot explain why is building a fingerprint, whatever its marketing says.
  • UserDefaults access is normal and expected — every SDK that persists a first-launch flag declares AC6B.1 or CA92.1.
  • A dependency with no manifest blocks your submission, so manifest support is a hard requirement when evaluating vendors, not a nice-to-have.
  • Declared reasons are visible in your own privacy report, so you can audit what a closed-source SDK admits to before shipping it.

Our position on the underlying technique is in what-is-fingerprint-attribution: we do not ship it, which is why our required-reason declarations are short. When a deterministic signal genuinely does not exist, the honest outcome is an unattributed install rather than a guess assembled from these APIs.

iOS SDK documentation

Our iOS SDK documentation states what the SDK reads on the device and why, so you can see the required-reason declarations before integrating rather than discovering them in a rejection email. Deterministic signals only — no boot time, no disk space, no fingerprint.

Open the ios sdk documentation

Frequently asked questions

What is a required reason API?
It is an iOS API that Apple has designated as usable only with a declared reason in the calling bundle's privacy manifest. There are five categories: user defaults, file timestamps, system boot time, disk space and active keyboards. The APIs still function normally at runtime; the requirement is enforced when you submit a build to App Store Connect.
Which APIs require a declared reason?
NSUserDefaults access, file creation and modification timestamps through NSFileManager, stat or NSURL resource values, system boot time through systemUptime or kern.boottime, free and total disk space through volume capacity keys, and the list of active keyboards. Each category has its own set of approved reason codes, and a code is only valid inside its own category.
What does ITMS-91053 mean?
It means the uploaded build calls an API in a required-reason category without a matching NSPrivacyAccessedAPITypes entry in any privacy manifest. The rejection names the category and often the responsible bundle. If that bundle is a dependency rather than your own code, the fix is updating the dependency — you cannot declare a reason on another bundle's behalf.
Do I need to declare reasons for APIs called by a third-party SDK?
No, and you cannot. Each bundle declares for itself, so an SDK with its own privacy manifest covers its own API use. The problem arises when a dependency ships no manifest: the gap is attributed to your submission, and the only real remedies are updating to a version that includes one or replacing the dependency.
Why did Apple restrict these particular APIs?
Because each was a permission-free signal useful for device fingerprinting. Boot time and free disk space are close to unique per device and stable over time, and combined with file timestamps and keyboard lists they can re-identify a user with no advertising identifier at all. Requiring a declared reason makes that use visible rather than silent.

Related terms

  • Privacy ManifestA privacy manifest is a PrivacyInfo.xcprivacy property list inside an app or SDK that declares the data it collects, the domains it uses for tracking, and its reasons for calling APIs Apple designates as requiring one.
  • Unattributed installsAn install is unattributed when no signal linking it to a prior ad click or link tap survived the journey through the app store, which can mean the install was organic or that the signal existed and was lost.