Attachez un appAccountToken à chaque achat sur l'App Store, sinon vous ne pourrez pas défendre le remboursement
Apple envoie à votre serveur un CONSUMPTION_REQUEST quand un client demande un remboursement, mais la transaction ne dit jamais de qui il s'agit. appAccountToken est l'UUID qui relie un achat à votre utilisateur. Configurez-le et vous pourrez répondre à Apple avec de vraies données. Ignorez-le et vous devinez.

Points clés
- appAccountToken est un UUID que vous attachez à un achat sur l'App Store pour que la transaction résultante pointe vers l'utilisateur exact dans votre propre système. Apple le stocke sur la transaction et le renvoie partout où cette transaction apparaît.
- La seule règle de format qu'Apple impose est que la valeur soit un UUID valide. Passez autre chose, un id, un e-mail, une chaîne concaténée, et StoreKit l'abandonne en silence et renvoie appAccountToken à nil.
- Dans StoreKit 2, vous le configurez avec une seule option d'achat, Product.PurchaseOption.appAccountToken(_:), en utilisant un UUID stable que vous avez généré et stocké pour ce compte.
- Configurez-le une fois sur l'achat d'origine et Apple conserve le même token à travers chaque renouvellement, nouvelle tentative de facturation et mise à niveau de la chaîne d'abonnement.
- Depuis 2025, l'endpoint Set App Account Token permet à votre serveur d'attacher un token aux achats effectués en dehors de votre app, comme les codes promotionnels et les achats mis en avant, que le flux dans l'app ne pouvait jamais atteindre.
- appAccountToken est ce qui rend le CONSUMPTION_REQUEST d'Apple possible à traiter. Sans lui, vous ne pouvez pas relier le remboursement au client dont vous êtes censé décrire l'usage dans la fenêtre de 12 heures.
- Un remboursement que vous ne pouvez pas identifier est un remboursement que vous ne pouvez pas défendre. Vous rendez de l'argent sur des achats que vous aviez les preuves de conserver, en plus du calcul, des appels d'API et des versements que vous avez déjà dépensés pour les livrer.
Un client demande un remboursement à Apple, Apple envoie à votre serveur un CONSUMPTION_REQUEST, et vous avez douze heures pour répondre avec de vraies données sur la façon dont cette personne a utilisé le produit. Puis vous ouvrez la notification et vous réalisez que vous n'avez aucune idée de qui elle est. La transaction porte un originalTransactionId et un id de produit, mais rien qui pointe vers le compte dans votre propre base de données. C'est exactement cet écart que comble appAccountToken, et si vous ne l'avez pas configuré au moment de l'achat, vous ne pouvez pas le combler après coup pour cette vente.
appAccountToken est un UUID que vous attachez à un achat pour que la transaction App Store résultante porte un pointeur vers l'utilisateur exact dans votre système. Configurez-le, et chaque question de remboursement qu'Apple posera un jour sur ce client arrivera avec son identité attachée. Ignorez-le, et vous devinez. Voici ce qu'est ce champ, comment le configurer, le nouvel endpoint qui sauve les achats effectués en dehors de votre app, et ce que le lien manquant coûte réellement quand un remboursement tombe.
Ce qu'est réellement appAccountToken
appAccountToken est un UUID opaque que vous générez et passez à StoreKit au moment de l'achat. Apple le stocke sur la transaction et le renvoie dans les informations de transaction de cet achat, et il y reste. Selon les mots d'Apple, c'est "l'UUID qui associe la transaction au compte de l'utilisateur sur votre propre service". La seule règle de format est qu'il doit être un UUID. Apple ne le lit pas, ne valide pas ce vers quoi il pointe, et ne se soucie pas de ce qu'il signifie de votre côté. C'est un lien que vous contrôlez.
Parce qu'il vit sur la transaction, il revient partout où va la transaction. La transaction signée dans une notification de serveur, la réponse Get Transaction Info de l'App Store Server API, et chaque renouvellement d'une chaîne d'abonnement portent tous le même token si vous l'avez configuré sur l'achat d'origine. Un UUID, attaché une seule fois, suit la facturation du client pendant toute la durée de la relation.
Il doit être un vrai UUID, sinon il disparaît en silence
La seule règle qu'Apple impose est le format. StoreKit 2 exige un UUID RFC 4122. Si vous passez une chaîne concaténée, un id entier ou une adresse e-mail, StoreKit ne lève pas d'erreur. Il abandonne la valeur et la transaction revient avec appAccountToken à nil. Les développeurs tombent constamment sur ce problème, et le symptôme est toujours le même, une variante de "appAccountToken is missing in the transaction payload" sur les forums d'Apple eux-mêmes, presque toujours parce que la valeur passée n'était pas un UUID valide. Générez un vrai UUID côté serveur, stockez-le associé au compte, et ne donnez jamais autre chose à StoreKit.
Comment le configurer au moment de l'achat
Dans StoreKit 2, c'est une seule option d'achat. Générez l'UUID sur votre serveur quand l'utilisateur s'inscrit ou arrive pour la première fois au paiement, stockez-le sur l'enregistrement de son compte, et passez cette même valeur dans l'appel d'achat.
La signature est Product.PurchaseOption.appAccountToken(_ token: UUID), et un achat ressemble à try await product.purchase(options: [.appAccountToken(token)]). Quand la transaction revient, vérifiée via l'App Store Server API ou livrée par une notification de serveur, elle porte cet UUID, et votre serveur retrouve le client en une seule requête.
Utilisez un token stable par compte
Ne générez pas un nouveau token pour chaque achat du même utilisateur. Apple renvoie le token sur les renouvellements, les nouvelles tentatives de facturation et les mises à niveau de la même chaîne, donc un UUID stable par compte vous donne un fil propre depuis le premier achat jusqu'à chaque événement futur. Un token qui change à chaque achat casse ce fil et va à l'encontre de tout l'objectif. Un compte, un token, réutilisé à chaque fois que ce compte achète.
L'endpoint qui sauve les achats hors de l'app
Jusqu'en 2025, il y avait un trou. Si un client utilisait un code promotionnel ou effectuait un achat intégré mis en avant directement depuis l'App Store, votre app n'exécutait jamais le flux d'achat, il n'y avait donc nulle part où configurer appAccountToken. Ces transactions arrivaient anonymes et le restaient.
La WWDC 2025 a comblé l'écart avec l'endpoint Set App Account Token. Votre serveur appelle PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken sur l'App Store Server API avec l'UUID dans le corps, et Apple configure le token sur cette transaction. Cela fonctionne pour tous les types de produit, couvre les codes promotionnels et les achats mis en avant, et la valeur que vous envoyez remplace tout token déjà présent sur la transaction. Vous pouvez désormais associer un achat après coup, depuis votre serveur, sans qu'il passe jamais par votre app.

| Canal d'achat | Où vous configurez appAccountToken | Notes |
|---|---|---|
| Achat intégré | Option d'achat StoreKit au moment de l'achat | Product.PurchaseOption.appAccountToken(UUID) |
| Utilisation d'un code promotionnel | Endpoint Set App Account Token, côté serveur | Aucun flux dans l'app à accrocher, alors configurez-le après coup |
| Achat intégré mis en avant depuis l'App Store | Endpoint Set App Account Token, côté serveur | L'achat se produit en dehors de votre app |
| Renouvellement d'abonnement | Rien à faire | Repris automatiquement de l'achat d'origine |
Là où le lien manquant vous coûte de l'argent
L'intérêt du token n'est pas d'avoir des registres bien rangés. C'est que la seule question de remboursement qu'Apple pose aux développeurs, le CONSUMPTION_REQUEST, n'a de réponse possible que si vous pouvez retrouver le client qu'elle concerne.
Quand un acheteur demande un remboursement sur un consommable ou un abonnement non renouvelable, Apple envoie à votre serveur une notification CONSUMPTION_REQUEST et vous donne douze heures pour répondre avec Send Consumption Information. Votre réponse, ce sont des données sur ce client précis : quelle part du produit il a consommée, l'ancienneté de son compte, ses dépenses totales, son statut de livraison. appAccountToken est lui-même l'un des champs de cette requête, et surtout, c'est ainsi que la transaction de la notification correspond au compte dont vous vous apprêtez à décrire l'usage. Pas de token, pas de recherche, pas de réponse exacte.
Ce que coûte réellement une réponse vide
Un remboursement non identifié force un mauvais choix. Vous pouvez répondre à la requête de consommation avec rien, ce qui se lit comme une faible consommation et pousse Apple à accorder le remboursement, y compris à des clients qui ont beaucoup utilisé le produit. Ou vous pouvez deviner. Dans les deux cas, vous remboursez des achats que vous aviez les preuves de défendre, et vous avez déjà payé le coût réel de leur livraison.
Ce coût n'est pas le prix de vente. Un consommable qui a lancé un lot d'appels à l'API d'un modèle, généré des images, exporté une vidéo ou déclenché un versement à un créateur a dépensé de l'argent réel au moment où il a été livré. Le remboursement rend le paiement du client. Il ne rend pas la facture du fournisseur. Multipliez un client non identifiable par chaque remboursement qu'il dépose, et par chaque fraudeur en série qui compte sur le fait que vous ignorez qui il est, et le token que vous avez négligé devient la ligne de code la plus chère que vous n'avez jamais écrite.
La même idée existe sur Android, sous un autre nom
Google Play résout le problème identique avec setObfuscatedAccountId, qui attache un identifiant de compte à un achat pour que l'examen des rétrofacturations de Google via orders.reviewrefund puisse être traité face à un vrai utilisateur. Store différent, mécanique différente, la même leçon : attachez l'identité au moment de l'achat ou vous ne pourrez pas défendre le litige plus tard. Sur l'App Store, cet outil est appAccountToken, et il doit être un UUID.
Trois habitudes qui gardent le token en place
- Générez un UUID par compte et stockez-le. Un token stable par client, créé quand il s'inscrit ou au premier paiement, enregistré sur sa fiche et réutilisé pour chaque achat.
- Validez avant de le passer. Confirmez que la valeur est un vrai UUID dans votre code d'achat, pour qu'un id malformé ne puisse jamais devenir en silence un token nil sur la transaction.
- Complétez les achats hors de l'app. Quand une notification de serveur arrive pour un code promotionnel ou un achat mis en avant sans token, appelez l'endpoint Set App Account Token pour attacher le bon.
Faites ces trois choses et chaque transaction qu'Apple vous enverra, demandes de remboursement comprises, arrivera déjà liée au client à qui elle appartient.
C'est le socle sur lequel RefundHalt s'appuie. Nous lisons appAccountToken sur chaque transaction et notification de serveur, nous le relions à l'usage que nous suivons déjà pour ce compte, et nous répondons à la requête de consommation d'Apple dans la fenêtre de douze heures avec les vrais chiffres du client. Le token est le fil. Configurez-le une fois et votre défense de remboursement aura quelque chose à quoi se raccrocher.
Questions fréquentes
- Qu'est-ce qu'appAccountToken sur l'App Store ?
- appAccountToken est un UUID que vous générez et attachez à un achat via StoreKit pour que la transaction App Store résultante pointe vers un compte utilisateur précis dans votre propre système. Apple le stocke sur la transaction et le renvoie dans les informations de transaction, les notifications de serveur et chaque renouvellement de la même chaîne, ce qui vous permet de relier tout événement futur, y compris une demande de remboursement, au bon client.
- Pourquoi mon appAccountToken est-il nil ou absent ?
- Presque toujours parce que la valeur que vous avez passée n'était pas un UUID valide. StoreKit 2 exige un UUID RFC 4122 et abandonne en silence tout le reste, donc une chaîne concaténée, un id entier ou un e-mail reviennent comme un appAccountToken nil alors que l'achat réussit quand même. L'autre cause fréquente est un achat effectué en dehors de votre app, comme un code promotionnel, où aucun flux dans l'app n'a été exécuté pour configurer le token.
- Puis-je configurer appAccountToken après l'achat, pour les codes promotionnels ?
- Oui, depuis 2025. L'endpoint Set App Account Token de l'App Store Server API permet à votre serveur d'attacher ou d'écraser le token sur une transaction existante en appelant PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken avec l'UUID dans le corps. Cela fonctionne pour tous les types de produit et est conçu pour les achats effectués en dehors de votre app, comme les codes promotionnels et les achats intégrés mis en avant.
- appAccountToken doit-il être un UUID ?
- Oui. La seule règle de format qu'Apple impose est que la valeur soit un UUID valide. Il est par ailleurs opaque, donc il peut correspondre à la clé de compte que vous voulez de votre côté, mais s'il n'est pas un UUID, StoreKit ne le stockera pas et la transaction reviendra avec appAccountToken à nil.
- Comment appAccountToken aide-t-il avec les remboursements ?
- Quand un client demande un remboursement, Apple envoie un CONSUMPTION_REQUEST et vous donne douze heures pour répondre avec des données sur cet acheteur précis. appAccountToken est ce qui vous permet de faire correspondre la transaction de la notification au compte dont vous devez rapporter l'usage, et c'est l'un des champs de la requête de consommation elle-même. Sans lui, vous ne pouvez pas répondre avec l'usage réel, alors Apple penche pour accorder des remboursements que vous aviez les preuves de contester.
- appAccountToken doit-il être différent pour chaque achat ?
- Non. Utilisez un seul UUID stable par compte et réutilisez-le pour chaque achat que fait cet utilisateur. Apple conserve le token à travers les renouvellements et les mises à niveau d'une chaîne d'abonnement, donc un token stable vous donne un lien propre dans le temps. Un token qui change à chaque achat casse ce lien et rend plus difficile le rattachement des transactions au même client.
Sources et lectures complémentaires
- Apple Developer: appAccountToken (StoreKit Transaction)
- Apple Developer: Product.PurchaseOption.appAccountToken(_:)
- Apple Developer: Set App Account Token (App Store Server API)
- Apple Developer: appAccountToken (App Store Server API)
- Apple Developer: ConsumptionRequest (Send Consumption Information)
- Apple Developer: Send Consumption Information
- WWDC25: Dive into App Store server APIs for In-App Purchase
RefundHalt
Le pilote automatique des remboursements pour l'App Store et Google Play
Poursuivre la lecture
Ne confirmez pas un achat Google Play sous trois jours et Google le rembourse, voici ce que cela vous coûte
Google Play rembourse et révoque automatiquement tout achat que votre serveur ne confirme pas sous trois jours. C'est un échec d'intégration, pas une décision du client, et c'est entièrement évitable. Voici la règle exacte, pourquoi elle se déclenche et ce que coûte réellement chaque vente perdue.
L'abus répété de remboursements vous coûte deux fois, voici comment les stores vous laissent riposter
Le client qui se fait rembourser encore et encore n'est pas un hasard. L'abus de remboursements vous coûte l'argent rendu plus le calcul que vous avez déjà dépensé, et les deux stores vous donnent un signal d'identité, l'appAccountToken d'Apple et l'ID de compte obfusqué de Google, pour relier le schéma.