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.
| Category value | Covers | Typical caller |
|---|---|---|
NSPrivacyAccessedAPICategoryUserDefaults | NSUserDefaults reads and writes | Almost every app and SDK |
NSPrivacyAccessedAPICategoryFileTimestamp | Creation and modification dates via NSFileManager, stat, NSURL resource values | Caching layers, file browsers |
NSPrivacyAccessedAPICategorySystemBootTime | systemUptime, kern.boottime | Performance measurement, session timing |
NSPrivacyAccessedAPICategoryDiskSpace | Free and total volume capacity | Downloaders, media caches |
NSPrivacyAccessedAPICategoryActiveKeyboards | The list of active keyboards | Custom 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.
<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>| Category | Code | Approved reason |
|---|---|---|
| User defaults | CA92.1 | Access values the app itself wrote |
| User defaults | 1C8F.1 | Access values in an App Group shared with apps from the same developer |
| User defaults | C56D.1 | Read managed app configuration set by an MDM profile |
| User defaults | AC6B.1 | An SDK wrapping the API on behalf of the host app |
| File timestamp | DDA9.1 | Display a file's timestamp to the person using the device |
| File timestamp | C617.1 | Timestamps of files inside the app or App Group container |
| File timestamp | 3B52.1 | Timestamps of files the user explicitly granted access to |
| Disk space | 85F4.1 | Display available space to the person using the device |
| Disk space | E174.1 | Check for sufficient space before writing |
| System boot time | 35F9.1 | Measure elapsed time between events within the app |
| Active keyboards | 3EC4.1 | The 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.
# 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| Caller | Action |
|---|---|
| Your own code | Add the category and the reason that truthfully describes the call |
| An SDK with a manifest | Nothing — its declaration covers its own bundle |
| An SDK without a manifest | Update it; the vendor must declare, you cannot declare for them |
| An abandoned SDK | Replace or vendor it — there is no workaround at submission |
| Code you can remove | Remove 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.
UserDefaultsaccess is normal and expected — every SDK that persists a first-launch flag declaresAC6B.1orCA92.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 Manifest — A 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 installs — An 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.