> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/connectors/fr/custom-connector/installation-changed-extensibility.md).

# Hooks d’installation et de désinstallation de Carte

Créez un connecteur personnalisé qui appelle une API externe lorsqu’une carte est installée ou désinstallée dans Apple Wallet ou Google Wallet.

Il est possible de créer un **connecteur personnalisé** dans **The Wallet Crew** pour appeler une API externe chaque fois qu'une Carte est **installée** ou **désinstallée** sur Apple Wallet ou Google Wallet.

Cela permet aux marques de **synchroniser l'état d'installation** avec des systèmes externes tels qu'un CRM, un outil d'analyse ou une plateforme d'automatisation marketing.

<details>

<summary>Exemples concrets</summary>

* Une marque de vente au détail met à jour un champ CRM comme `hasWalletPass=true` juste après l'installation. Elle cesse ensuite d'envoyer des rappels « ajouter au Wallet ».
* Une marque de billetterie consigne les installations et désinstallations dans sa pile BI. Elle surveille l'adoption par événement, canal et type d'appareil.
* Une marque déclenche un parcours de bienvenue après l'installation. Elle utilise `registrationSource` pour segmenter par campagne UTM.
* Une marque détecte des pics inhabituels de désinstallation après une mauvaise version. Elle effectue rapidement un retour en arrière et communique de manière proactive.

</details>

### Hooks d'exécution

La plateforme expose les hooks suivants sur le `runtime.wallet.passUpdater` point de terminaison :

* **`OnPassInstalled`** → Déclenché lorsqu'une Carte est ajoutée à Apple/Google Wallet
* **`OnPassUninstalled`** → Déclenché lorsqu'une Carte est supprimée d'Apple/Google Wallet

La même `runtime.wallet.passUpdater` inscription expose également quatre hooks autour de la création et de la mise à jour de Carte — `OnPassCreating`, `OnPassCreated`, `OnPassUpdating`, `OnPassUpdated`. Ils ne sont pas traités sur cette page, qui se concentre sur le duo installation/désinstallation. Voir [Connecteurs personnalisés → Ce que fait cette inscription](/developers-guides/fr/integration-guides/custom-connectors.md) pour l'ensemble complet.

Les deux méthodes reçoivent les mêmes paramètres :

| Paramètre               | Type                                    | Description                                                         |
| ----------------------- | --------------------------------------- | ------------------------------------------------------------------- |
| `passId`                | `chaîne`                                | Identifiant unique de la Carte                                      |
| `passType`              | `chaîne`                                | Type de Carte (fidélité, carte cadeau, billet d'événement…)         |
| `identifiers`           | `Record<string, any>`                   | Identifiants clé/valeur définis sur la Carte (par ex. `customerId`) |
| `appareil`              | `"apple"` ou `"google"`                 | Plateforme Wallet                                                   |
| `additionalInformation` | `AdditionalPassInstallationInformation` | Inclut les statistiques d'inscription                               |

### Exemple d'implémentation

Les scripts peuvent être placés dans le `server/scripts` dossier dans la configuration avancée.

```js
const API_URL = 'https://partner';
import { getSecret } from 'neo/secrets';

/** 
 * @typedef {Object} RegistrationInformation 
 * @property {number} activeRegistrationCount - Inscriptions actives. 
 * @property {number} totalRegistrationCount - Inscriptions totales. 
 **/ 

/**
 * @typedef {Object} RegistrationSource
 * @property {string[]} tags - liste des balises spécifiées par l'intégration SDK
 * @property {string} medium - support spécifié par l'intégration SDK ou utm_medium
 * @property {string} origin  - URL depuis laquelle la Carte est installée - peut être remplacée par l'intégration SDK
 * @property {string} userAgent - UserAgent facultatif utilisé pour installer la Carte
 */

/** 
 * @typedef {Object} AdditionalPassInstallationInformation
 * @property {RegistrationInformation} registrationInformation - Statistiques d'inscription. 
 * @property {RegistrationSource} registrationSource - Source de l'installation lorsqu'elle est disponible 
 */

/** méthodes déclenchées lorsqu'une Carte est installée 
 * @param {string} passId - identifiant unique de la Carte
 * @param {string} passType - type de Carte de la Carte actuelle
 * @param {Record<string, any>} identifiers - paires clé-valeur d'identifiants de la Carte
 * @param {"apple"|"google"} device - nom de l'appareil
 * @param {AdditionalPassInstallationInformation} additionalInformation - additionalInformation liée à cette installation de Carte */
 async function onPassInstalled(passId, passType, identifiers, device, additionalInformation) {
     await onPassInstallationStatusChanged(passId, passType, identifiers, device, true);
} 

/** méthodes déclenchées lorsqu'une Carte est désinstallée 
 * @param {string} passId - identifiant unique de la Carte 
 * @param {string} passType - type de Carte de la Carte actuelle
 * @param {Record<string, any>} identifiers - paires clé-valeur d'identifiants de la Carte
 * @param {"apple"|"google"} device - nom de l'appareil 
 * @param {AdditionalPassInstallationInformation} additionalInformation - additionalInformation liée à cette installation de Carte 
 */ 
async function onPassUninstalled(passId, passType, identifiers, device, additionalInformation) { 
    await onPassInstallationStatusChanged(passId, passType, identifiers, device, false); 
} 

async function onPassInstallationStatusChanged(passId, passType, identifiers, device, isInstalled) {
  const customerId = identifiers["customerId"]; // ou tout autre identifiant externe
  const API_SECRET = await getSecret('PARTNER-API-SECRET');

  // ⚠️ Remarque : fetch n'est pas standard ici. Il utilise des options en PascalCase et un Body basé sur des objets.
  await fetch(API_URL + '/wallet/installation', {
    Method: "POST",
    Headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "X-API-KEY": API_SECRET
    },
    Body: {
      customerId,
      isInstalled,
      appareil
    },
    ThrowOnError: false
  });
}

export default function (context) {
  context.register('runtime.wallet.passUpdater', {
    OnPassInstalled: onPassInstalled,
    OnPassUninstalled: onPassUninstalled
  });
}
```

### Exemple minimal

Pour les tests ou la journalisation uniquement :

```js
async function onPassInstalled(passId, passType, identifiers, device) {
  console.log(`Carte ${passId} installée sur ${device}`);
}

async function onPassUninstalled(passId, passType, identifiers, device) {
  console.log(`Carte ${passId} désinstallée de ${device}`);
}

export default function (context) {
  context.register('runtime.wallet.passUpdater', {
    OnPassInstalled: onPassInstalled,
    OnPassUninstalled: onPassUninstalled
  });
}
```

### Quand les événements sont-ils déclenchés ?

* **`OnPassInstalled`** → déclenché lorsqu'un client ajoute avec succès une Carte à Apple ou Google Wallet.
* **`OnPassUninstalled`** → déclenché lorsqu'un client retire la Carte de son Wallet.
* Les événements sont fiables : la plateforme garantit une remise correcte même en cas de forte charge.

### Remarques

* `fetch` est **pas le fetch standard du navigateur** — il accepte des options en PascalCase (`Method`, `Headers`, `Body`, `ThrowOnError`).
* L'authentification est flexible : les clés API (via `getSecret`) ou OAuth avec le custom `fetch` sont tous deux pris en charge.
* L'exécution s'effectue dans le même runtime sandboxé que chaque script de connecteur personnalisé : une limite d'exécution de 5 secondes par invocation, un ensemble restreint de bibliothèques approuvées et une validation automatisée avant qu'un script puisse être enregistré. Voir [Connecteurs personnalisés → Contraintes d'exécution](/developers-guides/fr/integration-guides/custom-connectors.md) pour la liste complète de ce qui est disponible dans un script.

### FAQ

<details>

<summary>Ces événements sont-ils en temps réel ?</summary>

Ils se déclenchent lorsque la Carte est ajoutée ou retirée du Wallet. En pratique, traitez-les comme quasi temps réel. Concevez l'API réceptrice pour qu'elle soit idempotente, afin que les nouvelles tentatives ne créent pas de doublons.

</details>

<details>

<summary>Que se passe-t-il si l'API externe est en panne ?</summary>

Le code du connecteur contrôle l'appel. Gérez les délais d'attente et les erreurs avec élégance. Si le système externe est critique, mettez en place des tentatives de reprise et une stratégie de lettres mortes côté récepteur.

</details>

<details>

<summary>Cela peut-il être utilisé pour déclencher des e-mails ou des campagnes push ?</summary>

Oui. Le schéma le plus courant consiste à appeler la plateforme d'automatisation marketing (directement ou via le backend de la marque) et à déclencher un parcours lors de l'installation. Utilisez les événements de désinstallation pour arrêter ou adapter les communications.

</details>

<details>

<summary>Que comprend <code>additionalInformation</code>?</summary>

Cela peut inclure des statistiques d'inscription et, lorsqu'elle est disponible, la source de l'installation. Utilisez-la pour mesurer l'adoption et attribuer les installations à une campagne ou à une intégration SDK.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.thewalletcrew.io/connectors/fr/custom-connector/installation-changed-extensibility.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
