# ITMS-91053: rezolvă „Missing API declaration” cu Expo

> ITMS-91053: build-ul tău folosește un API cu motiv obligatoriu fără să-l declare. Adaugă categoria și codul în ios.privacyManifests, apoi refă build-ul.

Pagina originală: [ITMS-91053: rezolvă „Missing API declaration” cu Expo](https://devoria.fr/ro/blog/itms-91053-missing-api-declaration-expo)
Autor: [Mehdi Azizi](https://devoria.fr/ro/mehdi-azizi)
Publicare: 2026-10-25
Ultima revizuire a conținutului: 2026-10-25


ITMS-91053 este o verificare automată de la Apple, trimisă pe e-mail după [livrarea build-ului tău](https://devoria.fr/ro/blog/eas-submit-ios-publicare-aplicatie-expo-app-store). Îți spune că în codul aplicației tale se folosește un API „cu motiv obligatoriu” (preferințe, datele fișierelor, timpul de la pornire, spațiul pe disc sau tastaturile) fără să explici de ce în manifestul de confidențialitate. **Cu Expo, corectura se face în `ios.privacyManifests`: categoria citată de Apple, codul care descrie folosirea ta reală, apoi un build nou.**

Pe Solys, alarma mea cu mini-jocuri, aceste motive sunt declarate în configurația aplicației. Mai jos găsești declarația ei reală, comanda care listează ce folosesc dependențele tale și verificarea de făcut pe fișierul final înainte de trimitere.

## Ce înseamnă eroarea ITMS-91053?

Mesajul se intitulează „ITMS-91053: Missing API declaration”. Îți spune că codul dintr-un anumit fișier din build face referire la unul sau mai multe API-uri care cer un motiv. Apoi listează categoriile în cauză, de exemplu `NSPrivacyAccessedAPICategoryUserDefaults`.

Aceste API-uri nu cer nicio permisiune utilizatorului. Dar pot fi folosite ca să recunoască un dispozitiv, ceea ce Apple numește fingerprinting. Asta e interzis, chiar și când utilizatorul acceptă urmărirea. Apple explică totul în pagina despre [API-urile cu motiv obligatoriu](https://developer.apple.com/documentation/bundleresources/describing-use-of-required-reason-api): fiecare aplicație și fiecare SDK trebuie să declare de ce le folosește.

Aceeași pagină stabilește regula: **din 1 mai 2024, App Store Connect nu mai acceptă o aplicație care nu descrie aceste utilizări în manifestul ei.** Unii dezvoltatori au raportat acest e-mail ca simplu avertisment, pe un build acceptat. Nu te baza pe asta: tratează-l ca pe un blocaj și corectează înainte de următoarea trimitere.

Ca celelalte erori ITMS, nu e respingerea unui reviewer. Nimeni nu ți-a deschis aplicația: Apple a analizat binarul.

## Privacy manifest pe iOS: fișierul PrivacyInfo.xcprivacy

Manifestul de confidențialitate este un fișier numit `PrivacyInfo.xcprivacy`, pus la rădăcina bundle-ului aplicației. Conform [documentației Apple despre privacy manifests](https://developer.apple.com/documentation/bundleresources/privacy-manifest-files), el descrie datele colectate, urmărirea și API-urile cu motiv obligatoriu. Acestea din urmă intră în tabloul `NSPrivacyAccessedAPITypes`: o intrare pe categorie, cu tipul ei și lista motivelor.

Capcana: **un manifest acoperă doar propriul bundle.** Apple o scrie clar: fiecare executabil sau bibliotecă dinamică ce folosește aceste API-uri trebuie să aibă un manifest în bundle-ul său. Cel al aplicației tale nu acoperă un framework inclus, iar un SDK nu se poate baza pe cel al aplicației tale.

Nu-l confunda cu frazele din Info.plist cerute de [ITMS-90683](https://devoria.fr/ro/blog/itms-90683-missing-purpose-string-expo). Acelea îi apar utilizatorului într-o cerere de permisiune. Manifestul e citit doar de Apple.

## Cele 5 categorii de API și codurile lor de motiv

Numele complet al unei categorii începe cu `NSPrivacyAccessedAPICategory`. Lista API-urilor și a motivelor se află pe pagina cheii [NSPrivacyAccessedAPIType](https://developer.apple.com/documentation/bundleresources/app-privacy-configuration/nsprivacyaccessedapitypes/nsprivacyaccessedapitype), citită pe 15 octombrie 2026.

| Categorie       | API tipic                    | Motiv uzual |
| --------------- | ---------------------------- | ----------- |
| UserDefaults    | `UserDefaults`               | CA92.1      |
| FileTimestamp   | `creationDate`               | C617.1      |
| SystemBootTime  | `systemUptime`               | 35F9.1      |
| DiskSpace       | `volumeAvailableCapacityKey` | E174.1      |
| ActiveKeyboards | `activeInputModes`           | 54BD.1      |

Codurile pe care le vei întâlni cel mai des:

- **CA92.1**: aplicația citește și scrie propriile preferințe, inaccesibile altor aplicații.
- **1C8F.1**: preferințe partajate cu un widget sau o extensie din același App Group.
- **C617.1**: datele sau dimensiunea fișierelor stocate în containerul aplicației.
- **3B52.1**: fișiere alese de utilizator, de exemplu într-un selector de documente.
- **35F9.1**: măsurarea timpului scurs între două evenimente din aplicație sau rularea unui cronometru.
- **E174.1**: verificarea spațiului liber înainte de a scrie fișiere, cu efect vizibil pentru utilizator.
- **85F4.1**: afișarea spațiului pe disc pentru utilizator.

**Declară motivul care corespunde folosirii tale reale, nu pe cel care pare cel mai larg.** Apple precizează că aceste API-uri și datele lor servesc doar motivelor declarate și niciodată urmăririi. Două coduri sunt rezervate SDK-urilor terțe: C56D.1 și 0A2A.1. N-au ce căuta în manifestul aplicației tale.

## Declararea privacy manifest în Expo

Cu Expo, nu scrii fișierul tu. Îl descrii sub `expo.ios.privacyManifests`, în app.json sau app.config, iar prebuild-ul generează `PrivacyInfo.xcprivacy`. Asta e metoda din [documentația Expo despre privacy manifests](https://docs.expo.dev/guides/apple-privacy/).

Iată extrasul real din configurația Solys. Cheia conține și urmărirea și datele colectate, scoase aici:

```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 și 35F9.1 reiau ce declară React Native și modulele Expo din aplicație. 1C8F.1 vine chiar de la Solys: aplicația partajează setări cu widgetul ei printr-un App Group.

O capcană de știut: dacă folderul `ios` e generat și ignorat de git, **un `PrivacyInfo.xcprivacy` scris de mână în acest folder nu ajunge niciodată în build.** EAS relansează prebuild-ul și regenerează folderul. Am constatat asta pe unul dintre proiectele mele pe 9 septembrie 2026: manifestul scris de mână dispăruse după un prebuild. Declarația trebuie să stea în configurație.

Ultimul punct: manifestul face parte din binar. O actualizare la distanță nu-l modifică. Trebuie să refaci un build și să-l retrimiți.

## SDK-urile terțe care vin cu propriul manifest

Majoritatea bibliotecilor recente își aduc manifestul. Pachetele Expo care folosesc aceste API-uri au un `PrivacyInfo.xcprivacy` în folderul lor `ios`, la fel ca React Native. Problema vine din felul în care sunt legate de aplicația ta.

Documentația Expo avertizează: Apple nu citește corect toate manifestele dependențelor CocoaPods legate static, cum e cazul pachetelor Expo. S-ar putea deci să trebuiască să copiezi motivele lor în configurația aplicației tale.

Ca să reduci munca asta, setarea `ios.privacyManifestAggregationEnabled` din [expo-build-properties](https://docs.expo.dev/versions/latest/sdk/build-properties/) unește manifestele dependențelor CocoaPods într-un singur fișier. În Podfile-ul generat de Expo pe proiectele mele (SDK 57), această unire e activă, dacă nu o dezactivezi.

Unirea are o limită: vede doar dependențele care au un manifest. O bibliotecă veche fără manifest rămâne invizibilă. **Citește deci calea fișierului menționat în e-mail**: îți spune unde să corectezi.

| Fișier menționat        | Unde corectezi         |
| ----------------------- | ---------------------- |
| Executabilul aplicației | `ios.privacyManifests` |
| Un `.framework`         | Actualizează SDK-ul    |
| O extensie `.appex`     | Manifestul extensiei   |

## Verifică înainte de trimitere

Expo propune să aștepți e-mailul de la Apple după o trimitere. Merge, dar fiecare dus-întors costă un build. Iată cele patru verificări pe care le fac înainte.

**1. Listează ce declară dependențele tale.** Din rădăcina proiectului:

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

Pe Solys, pe 15 octombrie 2026, comanda găsește 13 manifeste și patru categorii: datele fișierelor, preferințe, timpul de la pornire și spațiul pe disc. Fiecare categorie listată trebuie să apară în manifestul final al aplicației sau în cel al framework-ului care o folosește.

**2. Caută în propriul cod nativ.** Module proprii, plugin-uri, target-uri ca un widget: pe acest cod, niciun SDK nu-l declară în locul tău.

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

Adaptează folderele la proiectul tău. Pe Solys, tocmai această căutare scoate la iveală preferințele partajate prin App Group, de unde și codul 1C8F.1.

**3. Citește manifestul generat.** Rulează `npx expo prebuild -p ios`, apoi deschide `ios/<NumeleAplicatiei>/PrivacyInfo.xcprivacy`. Atenție: comanda poate șterge și recrea folderul `ios`. Dacă ai făcut modificări de mână acolo, lucrează pe o copie a proiectului.

**4. Verifică build-ul final.** E singura dovadă care contează. Descarcă IPA-ul de pe pagina build-ului de pe expo.dev, apoi rulează pe Mac:

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

A doua linie listează toate manifestele incluse, al aplicației și ale framework-urilor. A treia îl afișează pe cel al aplicației, de comparat cu lista de la pasul 1.

## Ce trebuie să spună manifestul în acord cu fișa ta

Manifestul nu trăiește singur. Dacă declară urmărire sau date colectate, fișa ta din App Store și politica de confidențialitate trebuie să spună același lucru. O diferență între cele trei te poate costa apoi o respingere umană, în baza [guideline 5.1.1](https://devoria.fr/ro/blog/guideline-5-1-1-refuz-app-store). Ce trebuie aliniat e detaliat în [politica de confidențialitate a unei aplicații](https://devoria.fr/ro/blog/politica-confidentialitate-aplicatie-ios).

## Trimite-ți build-ul fără surprize neplăcute

Erorile ITMS se rezolvă repede când știi să le citești. Respingerile care vin după cer mai multă distanță: pașii sunt pe pagina [aplicație respinsă de Apple](https://devoria.fr/ro/expertise/aplicatie-respinsa-de-apple), iar motivele cele mai frecvente sunt în [de ce respinge Apple o aplicație](https://devoria.fr/ro/blog/aplicatie-respinsa-apple-cazuri-reale).

Ca să-ți verifici dosarul înainte de trimitere, [Apple Review Kit](https://devoria.fr/ro/kits/review-apple) adună checklist-ul meu și skills Claude Code care îți recitesc proiectul. Dacă trimiterea ți se blochează și vrei o privire umană, [rezervă o oră cu mine](https://devoria.fr/ro/coaching): reluăm proiectul tău pe video, pe ecranul tău. Iar dacă îți pregătești prima lansare, [fă diagnosticul gratuit](https://devoria.fr/ro/diagnostic): pune pașii în ordine și îți trimite checklist-ul meu anti-respingere Apple.

## Întrebări frecvente

### ITMS-91053 blochează trimiterea build-ului meu?

Apple scrie că din 1 mai 2024 App Store Connect nu mai acceptă aplicațiile care nu descriu folosirea acestor API-uri. Totuși, unii dezvoltatori au primit e-mailul pe un build acceptat, ca avertisment. În ambele cazuri, corectează manifestul înainte de următorul build.

### Ce cod de motiv aleg pentru UserDefaults?

CA92.1 dacă aplicația citește și scrie doar propriile preferințe. Adaugă 1C8F.1 dacă le partajează cu un widget sau o extensie printr-un App Group. C56D.1 e rezervat SDK-urilor terțe: nu-l pune în manifestul aplicației tale.

### Trebuie să copiez manifestul fiecărui SDK în app.json?

Nu neapărat. Dacă unirea manifestelor e activă, cele ale dependențelor CocoaPods sunt reunite la instalarea pod-urilor. Copiază o categorie doar dacă lipsește din manifestul final, cu motivul care descrie folosirea reală.

### Widgetul sau extensia mea are nevoie de propriul manifest?

Conform Apple, fiecare bundle care conține un executabil ce folosește aceste API-uri trebuie să aibă propriul manifest. O extensie e un executabil separat, în propriul bundle: manifestul aplicației nu o acoperă.

### Pot rezolva ITMS-91053 fără să refac build-ul?

Nu. Manifestul de confidențialitate face parte din binar. Corectează configurația, refă build-ul, apoi testează-l în [TestFlight](https://devoria.fr/ro/blog/testflight-testare-aplicatie-iphone) înainte să-l trimiți la review.


## Proiectul tău

[Apple Review Kit](https://devoria.fr/ro/kits/review-apple): Checklistul de review App Store pe care îl folosesc, respingerile mele de la Apple corectate, notele pentru tester și două skill-uri Claude Code care îți verifică aplicația. 29 €.

[iOS Kit](https://devoria.fr/ro/kits/ios): Creează-ți aplicația iPhone cu Claude Code: codul de pornire al aplicațiilor mele, skill-urile care îi verifică munca și Apple Review Kit, App Store Screenshots Kit și ASO Kit. 129,99 €.
