---
type: reference
title: Méthodes et événements du widget
summary: Chaque méthode que tu peux appeler sur les éléments du widget Caputchin et chaque événement qu'ils émettent, avec la charge exacte de chacun, quel élément l'expose, et quand elle est valide.
---

Le widget Caputchin livre deux éléments personnalisés, et ta page interagit avec eux dans deux directions : tu **appelles des méthodes** sur l'élément pour le piloter, et tu **écoutes les événements** qu'il émet pour réagir. Cette page est la référence exhaustive des deux surfaces.

Chaque événement est un `CustomEvent` dépêché avec `bubbles: true` et `composed: true`, donc il échappe au shadow DOM du widget et tu peux l'écouter directement sur l'élément (ou sur n'importe quel ancêtre). Les données sont toujours sur `event.detail`.

## Les deux éléments d'un coup d'œil

| Élément | But | Méthodes |
|---|---|---|
| `<caputchin-widget>` | Vérification seulement (proof of work / case à cocher). | `start()` |
| `<caputchin-game>` | Hôte de jeu, avec vérification optionnelle. | `pass()`, `fail()` |

Le widget à case à cocher n'a que `start()` ; il n'expose **pas** `pass()` / `fail()`. L'hôte de jeu n'a pas de `start()` (sa manche devient active au montage pour inline, ou à la première ouverture de dialogue pour modal / fullscreen). Les deux éléments émettent `start`, `pass`, `error` et `degraded` ; l'hôte de jeu émet en plus `dialog-shown` et `dialog-hidden`. La couverture est dans la [table des événements](#events) ci-dessous.

## Méthodes

### `start()` (`<caputchin-widget>` uniquement)

Commence la vérification immédiatement. Son but est le **déclencheur manuel** : quand l'élément a `trigger="manual"`, tu appelles `start()` pour lancer la résolution du proof of work depuis ton propre geste (par exemple, à l'envoi de ton formulaire) au lieu de la case à cocher intégrée. Avec les déclencheurs `auto` / `click` par défaut, l'élément câble sa propre activation, donc tu n'appelles pas ceci.

```js
const widget = document.querySelector("caputchin-widget");
widget.start();
```

L'hôte de jeu n'a pas de `start()`. Vois [mode manuel](/docs/custom-game-development/manual-mode) pour la marche à suivre complète du pilote-le-toi-même.

### `pass(payload)` (`<caputchin-game>` uniquement)

Libère le gate de vérification : le visiteur a réussi. **Valide seulement quand `trigger="manual"`** ; l'appeler sur un jeu non manuel émet une `error` avec le code `invalid-call`. Le premier `pass()` échange et **verrouille** le verdict ; les appels ultérieurs sont silencieusement ignorés (une manche par session).

```js
const widget = document.querySelector("caputchin-game");
widget.pass({ trace: roundRecord });
```

| Champ de `payload` | Type | Signification |
|---|---|---|
| `trace` | `string` | L'enregistrement opaque de manche que ton jeu produit. Sur une manche gatée, le serveur la rejoue pour dériver le verdict faisant autorité ; sur une clé non gatée ou jeu-seul, elle est acceptée telle quelle. Passe une chaîne vide si ton interaction n'a pas d'enregistrement à rejouer. |

Il n'y a pas de champ `score` sur cette méthode, le gate est le rejeu de la `trace` par le serveur, pas un score revendiqué par le client. (Un `score` apparaît bien sur l'[événement `pass`](#the-pass-event-and-the-token), qui est le widget qui te rapporte, pas toi qui rapportes au widget.)

Appeler `pass()` avant que la manche n'ait commencé (modal / fullscreen, dialogue pas encore ouvert) émet une `error` avec le code `invalid-call`. Sur une clé jeu-seul (pas de `sitekey`), il n'y a pas de gate à libérer, donc `pass()` émet simplement l'événement `pass` avec `token: null`.

### `fail(payload?)` (`<caputchin-game>` uniquement)

Abandonne la manche : une défaite définitive. **Valide seulement quand `trigger="manual"`** (sinon `invalid-call`). Optionnel, une manche inachevée est de toute façon traitée comme un non-pass. Il abandonne la vérification en cours (les vérifications de proof of work et d'instrumentation) et fait surgir un événement `error` avec le code `game-error-relayed`.

```js
widget.fail({ code: "out-of-moves", message: "no moves left" });
```

| Champ de `payload` | Type | Signification |
|---|---|---|
| `code` | `string` (optionnel) | Ton code de diagnostic ; remonté comme l'`originalCode` de l'événement `error`. Par défaut `game-failed`. |
| `message` | `string` (optionnel) | Raison lisible par un humain. |

## Événements [#events]

Écoute avec `addEventListener(type, handler)`. Chaque charge vit sur `event.detail`.

| Événement | Émis par | `event.detail` | Se déclenche quand |
|---|---|---|---|
| `start` | les deux | `{ gameId: string \| null }` | La vérification commence (auto au montage, à l'activation, ou via `start()`). `gameId` est réglé pour une manche de jeu, `null` pour le widget simple. |
| `pass` | les deux | `{ token: string \| null, score: number \| null, durationMs: number \| null }` | La vérification est libérée. `token` est le token enveloppé à envoyer à ton backend ; `null` sur une clé jeu-seul (pas de `sitekey`). |
| `error` | les deux | `{ code, message, severity, originalCode? }` | N'importe quoi d'un avertissement de config bénin à un échec dur. Vois [l'événement error](#the-error-event). |
| `degraded` | les deux | `{ reason: "timeout" \| "network" \| "http" \| "malformed" }` | Le widget n'a pas pu résoudre à temps la taille / le skin / la locale que tu as configurés, alors il a rendu avec ses valeurs par défaut empaquetées. Pas une erreur. Vois [l'événement degraded](#the-degraded-event). |
| `dialog-shown` | `<caputchin-game>` | `{ layout: "modal" \| "fullscreen" }` | Un dialogue de jeu en surcouche s'ouvre (programmatique ou premier clic). |
| `dialog-hidden` | `<caputchin-game>` | `{ layout: "modal" \| "fullscreen" }` | Un dialogue de jeu en surcouche se ferme (programmatique, Échap, ou clic sur le fond). |

### L'événement `pass` et le token [#the-pass-event-and-the-token]

L'événement `pass` est ton signal que la vérification a réussi, mais ce n'est **pas** la décision de confiance. La décision de confiance est ton backend confirmant `detail.token`. [Vérifie toujours le token sur ton backend](/docs/integration-guides/verify-on-your-backend) ; n'accorde jamais l'accès à partir du seul événement front-end. Dans un formulaire, le widget injecte aussi le token comme champ `caputchin-token` pour qu'un POST de formulaire normal le porte. Les `score` et `durationMs` sur cet événement sont des analytiques rapportées par le client et peuvent être `null` ; ne les traite jamais comme un signal de confiance.

### L'événement `error` [#the-error-event]

L'événement `error` porte un `code` stable, un `message` humain, une `severity`, et parfois un `originalCode`. Chaque code a une sévérité par défaut fixe pour que tu puisses filtrer les avertissements « a continué de tourner » des échecs « a réellement cassé » **sans** coder en dur une table code-vers-sévérité, lis juste `detail.severity`. L'ensemble complet des codes :

| `code` | `severity` | Signification |
|---|---|---|
| `invalid-config` | `warn` | Un attribut ou une combinaison que le widget a rejeté ; il se dégrade gracieusement et continue de tourner. |
| `invalid-call` | `warn` | Une méthode appelée quand elle n'était pas valide (par ex. `pass()` sur un jeu non manuel, ou avant que la manche ne commence). |
| `verification-failed` | `error` | La vérification de proof of work ou d'instrumentation (ou l'échange du token) a échoué ; aucun token émis. |
| `game-load-failed` | `error` | Le bundle du jeu n'a pas pu être résolu, chargé ou enregistré. |
| `gate-unavailable` | `error` | Le serveur a renvoyé un refus faisant autorité au bootstrap (une clé gatée n'a pas pu fournir un jeu valide). |
| `game-error-relayed` | `error` | Une erreur a surgi de l'intérieur du jeu (relayée depuis l'iframe, ou depuis un `fail()` manuel). |

`detail.originalCode` est présent quand le `code` public est une généralisation d'une raison interne plus précise (par exemple, un échec de chargement d'iframe relayé comme `game-load-failed` porte le `iframe-load-failed` / `iframe-script-blocked` / `game-not-registered` brut dans `originalCode`). Utilise `code` pour brancher et `originalCode` seulement pour le diagnostic.

### L'événement `degraded` [#the-degraded-event]

Au montage, le widget fait un court appel à Caputchin pour résoudre la taille, le skin et la locale que tu as configurés (et, pour un jeu du marketplace, son empreinte préférée). Si cet appel échoue ou est trop lent, le widget ne bloque ni ne casse : il rend avec les valeurs cuites dans le bundle et émet `degraded`, pour que le repli ne soit jamais silencieux. Le widget reste pleinement fonctionnel après un événement `degraded`, seule la présentation résolue peut différer de ce que tu as configuré (un jeu peut apparaître à sa taille par défaut, ou la case à cocher dans son thème par défaut). Le widget réessaie une résolution lente avant de se replier, donc `degraded` veut dire que les tentatives ont été épuisées, pas qu'une seule tentative était lente.

`detail.reason` te dit pourquoi la résolution s'est repliée, pour que tu puisses le faire remonter dans ta propre télémétrie :

| `reason` | Signification |
|---|---|
| `timeout` | La résolution n'a pas répondu dans son budget de temps (service lent ou injoignable). |
| `network` | La requête elle-même a échoué (hors ligne, DNS, bloquée, ou connexion réinitialisée). |
| `http` | Le service a répondu avec un statut d'erreur. |
| `malformed` | Le service a répondu, mais le corps n'était pas valide. |

`degraded` est un avis, pas un échec, donc c'est délibérément **pas** un événement `error` : une résolution lente ne devrait pas déclencher les handlers que tu câbles pour de vraies pannes. Écoute-le seulement si tu veux observer les rendus dégradés, par exemple pour alerter quand tes visiteurs voient la présentation de repli.

## Écouter, en pratique

```js
const widget = document.querySelector("caputchin-game");

const onPass = (e) => {
  // send e.detail.token to your backend to verify
};
const onError = (e) => {
  if (e.detail.severity === "error") {
    console.error(e.detail.code, e.detail.message);
  }
};

widget.addEventListener("pass", onPass);
widget.addEventListener("error", onError);

// Clean up when you tear down your view:
widget.removeEventListener("pass", onPass);
widget.removeEventListener("error", onError);
```

Ce sont des `CustomEvent`s DOM natifs, donc en React tu les attaches avec un `ref` et `addEventListener` (pas des props JSX `onPass`) ; les [exemples frontend](/docs/integration-guides/frontend-examples) montrent le câblage spécifique au framework. Parce que chaque événement bubble et est composé, tu peux aussi déléguer depuis un élément conteneur plutôt que de lier chaque widget individuellement.

## Voir aussi

- [Ajouter le widget](/docs/getting-started/add-the-widget) : les attributs de configuration que tu règles dans le balisage (le côté entrée de ce côté sortie).
- [Pilote la vérification toi-même avec le mode manuel](/docs/custom-game-development/manual-mode) : le tutoriel qui utilise `start()` / `pass()` / `fail()`.
- [Vérifier sur ton backend](/docs/integration-guides/verify-on-your-backend) : quoi faire avec le token de l'événement `pass`.
- [Exemples frontend](/docs/integration-guides/frontend-examples) : câbler ces événements en React, Vue et JS pur.
