# ITMS-91053: исправляем «Missing API declaration» в Expo

> ITMS-91053: билд использует API с обязательной причиной без декларации. Добавь категорию и код в ios.privacyManifests и пересобери билд.

Оригинальная страница: [ITMS-91053: исправляем «Missing API declaration» в Expo](https://devoria.fr/ru/blog/itms-91053-missing-api-declaration-expo)
Автор: [Mehdi Azizi](https://devoria.fr/ru/mehdi-azizi)
Опубликовано: 2026-10-25
Последняя правка контента: 2026-10-25


ITMS-91053 это автоматическая проверка Apple, которая приходит письмом после [отправки твоего билда](https://devoria.fr/ru/blog/eas-submit-ios-publish-expo-app-store). Она сообщает, что код твоего приложения использует API «с обязательной причиной» (настройки, даты файлов, время с момента загрузки, место на диске или клавиатуры) и не объясняет зачем в манифесте конфиденциальности. **В Expo это исправляется в `ios.privacyManifests`: категория, которую назвала Apple, код, описывающий твоё реальное использование, и новый билд.**

В Solys, моём будильнике с мини-играми, эти причины задекларированы в конфигурации приложения. Ниже его настоящая декларация, команда, которая показывает, что используют твои зависимости, и проверка итогового файла перед отправкой.

## Что значит ошибка ITMS-91053?

Письмо называется «ITMS-91053: Missing API declaration». В нём сказано, что код конкретного файла твоего билда обращается к одному или нескольким API, которым нужна причина. Дальше идёт список категорий, например `NSPrivacyAccessedAPICategoryUserDefaults`.

Эти API не запрашивают у пользователя никакого разрешения. Но с их помощью можно опознать устройство, Apple называет это fingerprinting. Это запрещено, даже если пользователь согласился на отслеживание. Apple объясняет это на странице про [API с обязательной причиной](https://developer.apple.com/documentation/bundleresources/describing-use-of-required-reason-api): каждое приложение и каждый SDK должны декларировать, зачем они их используют.

Там же закреплено правило: **с 1 мая 2024 года App Store Connect не принимает приложение, которое не описывает это использование в своём манифесте.** Некоторые разработчики получали это письмо как простое предупреждение, при принятом билде. Не рассчитывай на это: считай его блокером и исправь до следующей отправки.

Как и другие ошибки ITMS, это не отказ ревьюера. Никто не открывал твоё приложение: Apple проанализировала бинарник.

## Privacy manifest в iOS: файл PrivacyInfo.xcprivacy

Манифест конфиденциальности это файл `PrivacyInfo.xcprivacy` в корне бандла приложения. Согласно [документации Apple о privacy manifests](https://developer.apple.com/documentation/bundleresources/privacy-manifest-files), он описывает собираемые данные, отслеживание и API с обязательной причиной. Последние идут в массив `NSPrivacyAccessedAPITypes`: одна запись на категорию, с её типом и списком причин.

Главная ловушка: **манифест покрывает только свой собственный бандл.** Apple пишет прямо: каждый исполняемый файл или динамическая библиотека, использующие эти API, должны иметь манифест в своём бандле. Манифест твоего приложения не покрывает встроенный фреймворк, а SDK не может полагаться на манифест твоего приложения.

Не путай его со строками в Info.plist, которых требует [ITMS-90683](https://devoria.fr/ru/blog/itms-90683-missing-purpose-string-expo). Те показываются пользователю в запросе разрешения. Манифест же читает только Apple.

## 5 категорий API и их коды причин

Полное имя категории начинается с `NSPrivacyAccessedAPICategory`. Список API и причин есть на странице ключа [NSPrivacyAccessedAPIType](https://developer.apple.com/documentation/bundleresources/app-privacy-configuration/nsprivacyaccessedapitypes/nsprivacyaccessedapitype), прочитанной 15 октября 2026 года.

| Категория       | Типичный API                 | Частая причина |
| --------------- | ---------------------------- | -------------- |
| UserDefaults    | `UserDefaults`               | CA92.1         |
| FileTimestamp   | `creationDate`               | C617.1         |
| SystemBootTime  | `systemUptime`               | 35F9.1         |
| DiskSpace       | `volumeAvailableCapacityKey` | E174.1         |
| ActiveKeyboards | `activeInputModes`           | 54BD.1         |

Коды, которые ты будешь встречать чаще всего:

- **CA92.1**: приложение читает и пишет свои собственные настройки, недоступные другим приложениям.
- **1C8F.1**: настройки, общие с виджетом или расширением из той же App Group.
- **C617.1**: даты или размер файлов, лежащих в контейнере приложения.
- **3B52.1**: файлы, выбранные пользователем, например в окне выбора документов.
- **35F9.1**: измерить время между двумя событиями в приложении или запустить таймер.
- **E174.1**: проверить свободное место перед записью файлов, с видимым для пользователя эффектом.
- **85F4.1**: показать пользователю место на диске.

**Декларируй причину, которая соответствует твоему реальному использованию, а не ту, что выглядит самой широкой.** Apple уточняет, что эти API и их данные служат только задекларированным причинам и никогда не используются для отслеживания. Два кода зарезервированы для сторонних SDK: C56D.1 и 0A2A.1. В манифесте твоего приложения им не место.

## Декларируем privacy manifest в Expo

В Expo ты не пишешь файл сам. Ты описываешь его в `expo.ios.privacyManifests`, в app.json или app.config, а prebuild генерирует `PrivacyInfo.xcprivacy`. Это способ из [документации Expo о privacy manifests](https://docs.expo.dev/guides/apple-privacy/).

Вот реальный фрагмент конфигурации Solys. В ключе есть ещё отслеживание и собираемые данные, здесь я их убрал:

```json
{
  "expo": {
    "ios": {
      "privacyManifests": {
        "NSPrivacyAccessedAPITypes": [
          {
            "NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryUserDefaults",
            "NSPrivacyAccessedAPITypeReasons": ["CA92.1", "1C8F.1"]
          },
          {
            "NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryFileTimestamp",
            "NSPrivacyAccessedAPITypeReasons": ["C617.1"]
          },
          {
            "NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategorySystemBootTime",
            "NSPrivacyAccessedAPITypeReasons": ["35F9.1"]
          }
        ]
      }
    }
  }
}
```

CA92.1, C617.1 и 35F9.1 повторяют то, что декларируют React Native и модули Expo в приложении. 1C8F.1 идёт от самого Solys: приложение делится настройками со своим виджетом через App Group.

Ловушка, о которой стоит знать: если папка `ios` генерируется и игнорируется git, **`PrivacyInfo.xcprivacy`, написанный руками в этой папке, никогда не попадёт в билд.** EAS заново запускает prebuild и перегенерирует папку. Я убедился в этом на одном из своих проектов 9 сентября 2026 года: написанный вручную манифест пропал после prebuild. Декларация должна жить в конфигурации.

И последнее: манифест является частью бинарника. Обновление по воздуху его не меняет. Нужно пересобрать билд и отправить его заново.

## Сторонние SDK со своим манифестом

Большинство свежих библиотек поставляют свой манифест. У пакетов Expo, использующих эти API, есть `PrivacyInfo.xcprivacy` в папке `ios`, как и у React Native. Проблема в том, как они линкуются с твоим приложением.

Документация Expo предупреждает: Apple не всегда правильно читает манифесты зависимостей CocoaPods, слинкованных статически, а пакеты Expo линкуются именно так. Поэтому их причины, возможно, придётся скопировать в конфигурацию твоего приложения.

Чтобы сократить эту работу, настройка `ios.privacyManifestAggregationEnabled` в [expo-build-properties](https://docs.expo.dev/versions/latest/sdk/build-properties/) объединяет манифесты зависимостей CocoaPods в один файл. В Podfile, который Expo генерирует в моих проектах (SDK 57), это объединение включено, если ты его не отключишь.

У объединения есть предел: оно видит только зависимости, у которых есть манифест. Старая библиотека без манифеста остаётся невидимой. **Поэтому читай путь к файлу, указанный в письме**: он говорит, где исправлять.

| Указанный файл              | Где исправлять         |
| --------------------------- | ---------------------- |
| Исполняемый файл приложения | `ios.privacyManifests` |
| `.framework`                | Обновить SDK           |
| Расширение `.appex`         | Манифест расширения    |

## Проверка перед отправкой

Expo предлагает дождаться письма от Apple после отправки. Это работает, но каждая итерация стоит билда. Вот четыре проверки, которые я делаю заранее.

**1. Составь список того, что декларируют твои зависимости.** Из корня проекта:

```bash
find node_modules -name PrivacyInfo.xcprivacy -not -path '*/example/*' \
  -exec grep -ho "NSPrivacyAccessedAPICategory[A-Za-z]*" {} + | sort | uniq -c
```

На Solys 15 октября 2026 года команда находит 13 манифестов и четыре категории: даты файлов, настройки, время с момента загрузки и место на диске. Каждая найденная категория должна оказаться в итоговом манифесте приложения или в манифесте фреймворка, который её использует.

**2. Поищи в своём нативном коде.** Свои модули, плагины, таргеты вроде виджета: этот код ни один SDK за тебя не задекларирует.

```bash
grep -rlE "UserDefaults|systemUptime|mach_absolute_time|creationDate|modificationDate|volumeAvailableCapacity|activeInputModes" \
  --include='*.swift' --include='*.m' --include='*.mm' modules plugins targets
```

Подставь папки своего проекта. На Solys именно этот поиск выявляет настройки, общие через App Group, отсюда код 1C8F.1.

**3. Прочитай сгенерированный манифест.** Запусти `npx expo prebuild -p ios`, затем открой `ios/<YourAppName>/PrivacyInfo.xcprivacy`. Внимание: эта команда может удалить и пересоздать папку `ios`. Если ты вносил туда правки руками, работай с копией проекта.

**4. Проверь итоговый билд.** Это единственное доказательство, которое имеет значение. Скачай IPA со страницы билда на expo.dev и запусти на своём Mac:

```bash
unzip -q MyApp.ipa -d ipa
find ipa/Payload -name PrivacyInfo.xcprivacy
plutil -p ipa/Payload/*.app/PrivacyInfo.xcprivacy
```

Вторая строка выводит все встроенные манифесты: приложения и фреймворков. Третья показывает манифест приложения, его нужно сравнить со списком из шага 1.

## Манифест должен совпадать с твоей карточкой

Манифест не существует сам по себе. Если он декларирует отслеживание или собираемые данные, твоя карточка в App Store и политика конфиденциальности должны говорить то же самое. Расхождение между ними тремя может потом обернуться отказом от живого ревьюера по [guideline 5.1.1](https://devoria.fr/ru/blog/guideline-5-1-1-app-store-rejection-fix). Что именно нужно согласовать, подробно описано в статье [политика конфиденциальности приложения](https://devoria.fr/ru/blog/privacy-policy-ios-app-guide).

## Отправь билд без неприятных сюрпризов

Ошибки ITMS исправляются быстро, если умеешь их читать. Отказы, которые приходят потом, требуют больше вдумчивости: порядок действий есть на странице [приложение отклонено Apple](https://devoria.fr/ru/expertise/app-rejected-by-apple), а самые частые причины в статье [почему Apple отклоняет приложение](https://devoria.fr/ru/blog/otkaz-apple-app-store-prichiny).

Чтобы проверить всё перед отправкой, в [Apple Review Kit](https://devoria.fr/ru/kits/review-apple) собраны мой чек-лист и skills для Claude Code, которые проверяют твой проект. Если отправка застряла и тебе нужен взгляд живого человека, [забронируй час со мной](https://devoria.fr/ru/coaching): разберём твой проект по видеосвязи, на твоём экране. А если готовишь свой первый релиз, [пройди бесплатную диагностику](https://devoria.fr/ru/diagnostic): она расставит шаги по порядку и пришлёт тебе мой чек-лист против отказов Apple.

## Частые вопросы

### Блокирует ли ITMS-91053 отправку билда?

Apple пишет, что с 1 мая 2024 года App Store Connect не принимает приложения, которые не описывают использование этих API. При этом некоторые разработчики получали письмо при принятом билде, как предупреждение. В обоих случаях исправь манифест до следующего билда.

### Какой код причины выбрать для UserDefaults?

CA92.1, если приложение только читает и пишет свои собственные настройки. Добавь 1C8F.1, если оно делится ими с виджетом или расширением через App Group. C56D.1 зарезервирован для сторонних SDK: не добавляй его в манифест своего приложения.

### Нужно ли копировать манифест каждого SDK в app.json?

Не обязательно. Если объединение манифестов включено, манифесты зависимостей CocoaPods собираются вместе при установке pods. Копируй категорию, только если её нет в итоговом манифесте, с причиной, описывающей реальное использование.

### Нужен ли моему виджету или расширению свой манифест?

По словам Apple, каждый бандл с исполняемым файлом, который использует эти API, должен иметь свой манифест. Расширение это отдельный исполняемый файл в собственном бандле: манифест приложения его не покрывает.

### Можно ли исправить ITMS-91053 без нового билда?

Нет. Манифест конфиденциальности является частью бинарника. Исправь конфигурацию, пересобери билд и протестируй его в [TestFlight](https://devoria.fr/ru/blog/testflight-testirovanie-iphone-prilozheniya), прежде чем отправлять на ревью.


## Твой проект

[Apple Review Kit](https://devoria.fr/ru/kits/review-apple): Мой чек-лист для ревью App Store, исправленные отказы Apple, заметки для ревьюера и два skills для Claude Code, которые проверяют твоё приложение. 29 €.

[iOS Kit](https://devoria.fr/ru/kits/ios): Создай приложение для iPhone с Claude Code: стартовый код моих приложений, skills для проверки его работы и наборы Apple Review Kit, App Store Screenshots Kit и ASO Kit. 129,99 €.
