ITMS-91053: risolvere “Missing API declaration” con Expo
Di Mehdi Azizi
Pubblicato il , 8 min
ITMS-91053: la tua build usa un'API a motivazione obbligatoria senza dichiararla. Aggiungi categoria e codice in ios.privacyManifests e rifai la build.
ITMS-91053 è un controllo automatico di Apple, inviato via e-mail dopo la consegna della tua build. Ti dice che il codice della tua app usa un'API "a motivazione obbligatoria" (preferenze, date dei file, tempo dall'avvio, spazio su disco o tastiere) senza spiegare perché nel suo manifest della privacy. Con Expo la correzione si fa in ios.privacyManifests: la categoria citata da Apple, il codice che descrive il tuo uso reale, poi una nuova build.
Su Solys, la mia sveglia con minigiochi, queste motivazioni sono dichiarate nella configurazione dell'app. Qui trovi la sua dichiarazione reale, il comando che elenca cosa usano le tue dipendenze e il controllo da fare sul file finale prima dell'invio.
Cosa significa l'errore ITMS-91053?
Il messaggio si intitola "ITMS-91053: Missing API declaration". Indica che il codice di un file preciso della tua build fa riferimento a una o più API che richiedono una motivazione. Poi elenca le categorie in questione, per esempio NSPrivacyAccessedAPICategoryUserDefaults.
Queste API non chiedono nessuna autorizzazione all'utente. Però possono servire a riconoscere un dispositivo, quello che Apple chiama fingerprinting. È vietato, anche quando l'utente accetta il tracciamento. Apple lo spiega nella sua pagina sulle API a motivazione obbligatoria: ogni app e ogni SDK deve dichiarare perché le usa.
La stessa pagina fissa la regola: dal 1° maggio 2024 App Store Connect non accetta più un'app che non descrive questi usi nel suo manifest. Alcuni sviluppatori hanno segnalato questa e-mail come un semplice avviso, su una build accettata. Non contarci: trattala come un blocco e correggi prima del prossimo invio.
Come gli altri errori ITMS, non è il rifiuto di un reviewer. Nessuno ha aperto la tua app: Apple ha analizzato il binario.
Il privacy manifest iOS: il file PrivacyInfo.xcprivacy
Il manifest della privacy è un file chiamato PrivacyInfo.xcprivacy, posizionato nella radice del bundle dell'app. Secondo la documentazione di Apple sui privacy manifest, descrive i dati raccolti, il tracciamento e le API a motivazione obbligatoria. Queste ultime vanno nell'array NSPrivacyAccessedAPITypes: una voce per categoria, con il suo tipo e l'elenco delle sue motivazioni.
Il punto che frega: un manifest copre solo il proprio bundle. Apple lo scrive: ogni eseguibile o libreria dinamica che usa queste API deve avere un manifest nel proprio bundle. Quello della tua app non copre un framework incorporato, e un SDK non può contare su quello della tua app.
Non confonderlo con le frasi dell'Info.plist richieste da ITMS-90683. Quelle vengono mostrate all'utente in una richiesta di autorizzazione. Il manifest invece lo legge solo Apple.
Le 5 categorie di API e i loro codici di motivazione
Il nome completo di una categoria inizia con NSPrivacyAccessedAPICategory. L'elenco delle API e delle motivazioni si trova nella pagina della chiave NSPrivacyAccessedAPIType, consultata il 15 ottobre 2026.
| Categoria | API tipica | Motivazione comune |
|---|---|---|
| UserDefaults | UserDefaults | CA92.1 |
| FileTimestamp | creationDate | C617.1 |
| SystemBootTime | systemUptime | 35F9.1 |
| DiskSpace | volumeAvailableCapacityKey | E174.1 |
| ActiveKeyboards | activeInputModes | 54BD.1 |
I codici che incontrerai più spesso:
- CA92.1: l'app legge e scrive le proprie preferenze, inaccessibili alle altre app.
- 1C8F.1: preferenze condivise con un widget o un'estensione dello stesso App Group.
- C617.1: date o dimensioni di file salvati nel container dell'app.
- 3B52.1: file scelti dall'utente, per esempio in un selettore di documenti.
- 35F9.1: misurare il tempo trascorso tra due eventi dell'app, o far girare un timer.
- E174.1: verificare lo spazio libero prima di scrivere file, con un effetto visibile per l'utente.
- 85F4.1: mostrare lo spazio su disco all'utente.
Dichiara la motivazione che corrisponde al tuo uso reale, non quella che sembra più ampia. Apple precisa che queste API e i loro dati servono solo alle motivazioni dichiarate, e mai al tracciamento. Due codici sono riservati agli SDK di terze parti: C56D.1 e 0A2A.1. Non vanno nel manifest della tua app.
Dichiarare il privacy manifest in Expo
Con Expo il file non lo scrivi tu. Lo descrivi sotto expo.ios.privacyManifests, in app.json o app.config, e il prebuild genera PrivacyInfo.xcprivacy. È il metodo della documentazione di Expo sui privacy manifest.
Ecco l'estratto reale della configurazione di Solys. La chiave contiene anche il tracciamento e i dati raccolti, qui rimossi:
{
"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 e 35F9.1 riprendono quello che dichiarano React Native e i moduli Expo dell'app. 1C8F.1 viene da Solys stessa: l'app condivide impostazioni con il suo widget tramite un App Group.
Una trappola da conoscere: se la tua cartella ios è generata e ignorata da git, un PrivacyInfo.xcprivacy scritto a mano in quella cartella non arriva mai nella build. EAS rilancia il prebuild e rigenera la cartella. L'ho verificato su uno dei miei progetti il 9 settembre 2026: il manifest scritto a mano era sparito dopo un prebuild. La dichiarazione deve stare nella configurazione.
Ultimo punto: il manifest fa parte del binario. Un aggiornamento remoto non lo modifica. Devi rifare una build e reinviarla.
Gli SDK di terze parti che includono il proprio manifest
La maggior parte delle librerie recenti fornisce il proprio manifest. I pacchetti Expo che usano queste API hanno un PrivacyInfo.xcprivacy nella loro cartella ios, proprio come React Native. Il problema sta nel modo in cui sono collegati alla tua app.
La documentazione di Expo avverte: Apple non legge correttamente tutti i manifest delle dipendenze CocoaPods collegate staticamente, ed è il caso dei pacchetti Expo. Quindi potresti dover ricopiare le loro motivazioni nella configurazione della tua app.
Per limitare questo lavoro, l'impostazione ios.privacyManifestAggregationEnabled di expo-build-properties unisce i manifest delle dipendenze CocoaPods in un unico file. Nel Podfile che Expo genera sui miei progetti (SDK 57), questa unione è attiva, a meno che tu non la disattivi.
L'unione ha un limite: vede solo le dipendenze che forniscono un manifest. Una libreria vecchia che non ce l'ha resta invisibile. Leggi quindi il percorso del file citato nell'e-mail: ti dice dove correggere.
| File citato | Dove correggere |
|---|---|
| L'eseguibile dell'app | ios.privacyManifests |
Un .framework | Aggiornare l'SDK |
Un'estensione .appex | Manifest dell'estensione |
Verificare prima dell'invio
Expo propone di aspettare l'e-mail di Apple dopo un invio. Funziona, ma ogni andata e ritorno costa una build. Ecco i quattro controlli che faccio prima.
1. Elenca cosa dichiarano le tue dipendenze. Dalla radice del progetto:
find node_modules -name PrivacyInfo.xcprivacy -not -path '*/example/*' \
-exec grep -ho "NSPrivacyAccessedAPICategory[A-Za-z]*" {} + | sort | uniq -c
Su Solys, il 15 ottobre 2026, il comando trova 13 manifest e quattro categorie: date dei file, preferenze, tempo dall'avvio e spazio su disco. Ogni categoria elencata deve comparire nel manifest finale dell'app, o in quello del framework che la usa.
2. Cerca nel tuo codice nativo. Moduli tuoi, plugin, target come un widget: questo codice nessun SDK lo dichiara al posto tuo.
grep -rlE "UserDefaults|systemUptime|mach_absolute_time|creationDate|modificationDate|volumeAvailableCapacity|activeInputModes" \
--include='*.swift' --include='*.m' --include='*.mm' modules plugins targets
Adatta le cartelle al tuo progetto. Su Solys è questa ricerca a far emergere le preferenze condivise tramite App Group, da cui il codice 1C8F.1.
3. Leggi il manifest generato. Lancia npx expo prebuild -p ios, poi apri ios/<NomeDellaTuaApp>/PrivacyInfo.xcprivacy. Attenzione: questo comando può cancellare e ricreare la cartella ios. Se ci hai fatto modifiche a mano, lavora su una copia del progetto.
4. Controlla la build finale. È l'unica prova che conta. Scarica l'IPA dalla pagina della build su expo.dev, poi lancia sul tuo Mac:
unzip -q MyApp.ipa -d ipa
find ipa/Payload -name PrivacyInfo.xcprivacy
plutil -p ipa/Payload/*.app/PrivacyInfo.xcprivacy
La seconda riga elenca tutti i manifest inclusi, quello dell'app e quelli dei framework. La terza mostra quello dell'app, da confrontare con l'elenco del passaggio 1.
Cosa deve raccontare il manifest insieme alla tua scheda
Il manifest non vive da solo. Se dichiara tracciamento o dati raccolti, la tua scheda App Store e la tua privacy policy devono dire la stessa cosa. Una differenza tra i tre può poi costarti un rifiuto umano, ai sensi della guideline 5.1.1. Cosa allineare è spiegato in dettaglio in privacy policy di un'app.
Inviare la tua build senza brutte sorprese
Gli errori ITMS si correggono in fretta quando sai leggerli. I rifiuti che arrivano dopo richiedono più distacco: il procedimento è nella pagina app rifiutata da Apple, e i motivi più frequenti sono in perché Apple rifiuta un'app.
Per verificare il tuo progetto prima dell'invio, l'Apple Review Kit raccoglie la mia checklist e delle skill di Claude Code che rileggono il tuo progetto. Se il tuo invio è bloccato e vuoi uno sguardo umano, prenota un'ora con me: riprendiamo il tuo progetto in videochiamata, sul tuo schermo. E se stai preparando la tua prima uscita, fai il tuo diagnostico gratuito: rimette i passaggi in ordine e ti manda la mia checklist anti-rifiuto Apple.
Domande frequenti
ITMS-91053 blocca l'invio della mia build?
Apple scrive che dal 1° maggio 2024 App Store Connect non accetta più le app che non descrivono il loro uso di queste API. Eppure alcuni sviluppatori hanno ricevuto l'e-mail su una build accettata, come un avviso. In entrambi i casi, correggi il manifest prima della prossima build.
Quale codice di motivazione scegliere per UserDefaults?
CA92.1 se l'app legge e scrive solo le proprie preferenze. Aggiungi 1C8F.1 se le condivide con un widget o un'estensione tramite un App Group. C56D.1 è riservato agli SDK di terze parti: non metterlo nel manifest della tua app.
Devo ricopiare il manifest di ogni SDK in app.json?
Non per forza. Se l'unione dei manifest è attiva, quelli delle dipendenze CocoaPods vengono riuniti durante l'installazione dei pod. Ricopia una categoria solo se manca nel manifest finale, con la motivazione che descrive l'uso reale.
Il mio widget o la mia estensione ha bisogno di un proprio manifest?
Secondo Apple, ogni bundle che contiene un eseguibile che usa queste API deve avere il proprio manifest. Un'estensione è un eseguibile a parte, nel suo bundle: il manifest dell'app non la copre.
Si può correggere ITMS-91053 senza rifare una build?
No. Il manifest della privacy fa parte del binario. Correggi la configurazione, rifai una build, poi testala su TestFlight prima di inviarla in revisione.