# Webhooks

Les webhooks constituent un socle pour les fonctionnalités liées au MLOps. Ils vous permettent de surveiller les nouvelles modifications sur des dépôts spécifiques ou sur l’ensemble des dépôts appartenant à un ensemble donné d’utilisateurs/organisations (pas seulement vos dépôts, mais n’importe quel dépôt).

Vous pouvez les utiliser pour convertir automatiquement des modèles, créer des bots communautaires ou mettre en place du CI/CD pour vos modèles, jeux de données, Spaces et buckets (et bien plus encore !). Les Webhooks peuvent également [déclencher des Jobs](./jobs-webhooks) pour automatiser les tâches de calcul en réponse aux événements de dépôt.

La documentation relative aux Webhooks se trouve ci-dessous – vous pouvez également consulter nos **guides** qui présentent quelques cas d’utilisation possibles des Webhooks :
- [Ajuster finement un nouveau modèle à chaque mise à jour d'un jeu de données (Python)](./webhooks-guide-auto-retrain)
- [Créer un bot de discussion sur le Hub à l'aide d'une API LLM (NodeJS)](./webhooks-guide-discussion-bot)
- [Créer des rapports de qualité des métadonnées (Python)](./webhooks-guide-metadata-review)
- [Traiter de nouveaux fichiers dans un bucket avec Jobs (CLI)](./webhooks-guide-bucket-jobs)
- et d'autres à venir…

## Créer votre Webhook

Vous pouvez créer de nouveaux Webhooks et modifier les existants dans les [paramètres](https://huggingface.co/settings/webhooks) de vos Webhooks :

![Settings of an individual webhook](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/webhook-settings.png)

Les Webhooks peuvent surveiller les mises à jour des dépôts, les Pull Requests, les discussions et les nouveaux commentaires. Il est même possible de créer un Space pour réagir à vos Webhooks !

## Webhook Payloads

Après l’enregistrement d’un Webhook, vous serez notifié des nouveaux événements via un appel `HTTP POST` à l’URL cible spécifiée. La charge utile est encodée en JSON.

Vous pouvez consulter l’historique des charges utiles envoyées dans l’onglet Activité de la page de configuration du webhook. Il est également possible de rejouer des webhooks passés pour faciliter le débogage :

![image.png](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/webhook-activity.png)

À titre d’exemple, voici la charge utile complète lorsqu’une Pull Request est ouverte :

```json
{
  "event": {
    "action": "create",
    "scope": "discussion"
  },
  "repo": {
    "type": "model",
    "name": "openai-community/gpt2",
    "id": "621ffdc036468d709f17434d",
    "private": false,
    "url": {
      "web": "https://huggingface.co/openai-community/gpt2",
      "api": "https://huggingface.co/api/models/openai-community/gpt2"
    },
    "owner": {
      "id": "628b753283ef59b5be89e937"
    }
  },
  "discussion": {
    "id": "6399f58518721fdd27fc9ca9",
    "title": "Update co2 emissions",
    "url": {
      "web": "https://huggingface.co/openai-community/gpt2/discussions/19",
      "api": "https://huggingface.co/api/models/openai-community/gpt2/discussions/19"
    },
    "status": "open",
    "author": {
      "id": "61d2f90c3c2083e1c08af22d"
    },
    "num": 19,
    "isPullRequest": true,
    "changes": {
      "base": "refs/heads/main"
    }
  },
  "comment": {
    "id": "6399f58518721fdd27fc9caa",
    "author": {
      "id": "61d2f90c3c2083e1c08af22d"
    },
    "content": "Add co2 emissions information to the model card",
    "hidden": false,
    // Note: when `hidden` is `true`, `content` will be undefined
    "url": {
      "web": "https://huggingface.co/openai-community/gpt2/discussions/19#6399f58518721fdd27fc9caa"
    }
  },
  "webhook": {
    "id": "6390e855e30d9209411de93b",
    "version": 3
  }
}
```

### Événement

La propriété de premier niveau `event` est toujours spécifiée et sert à déterminer la nature de l'événement.

Elle possède deux sous-propriétés : `event.action` et `event.scope`.

`event.scope` aura l'une des valeurs suivantes :

- `"repo"` - Événements globaux sur les dépôts. Valeurs possibles pour l'`action` associée : `"create"`, `"delete"`, `"update"`, `"move"`.
- `"repo.content"` - Événements sur le contenu du dépôt, tels que de nouveaux commits ou tags. Il se déclenche également sur de nouvelles Pull Requests en raison de la référence/commit nouvellement créée. Pour les Buckets, il se déclenche sur l’ajout ou la suppression de fichiers plutôt que sur les références Git. L’`action` associée est toujours `"update"`.
- `"repo.config"` - Événements sur la configuration : mise à jour des secrets de l’espace, mise à jour des paramètres, mise à jour des DOI, désactivation ou non, etc. L’`action` associée est toujours `"update"`.
- `"discussion"` - Création d’une discussion ou d’une Pull Request, mise à jour du titre ou du statut, et fusion. Valeurs possibles pour l’`action` associée : `"create"`, `"delete"`, `"update"`.
- `"discussion.comment"` - Création, mise à jour et masquage d'un commentaire. Valeurs possibles pour l'`action` associée : `"create"`, `"update"`.

D’autres périmètres pourront être ajoutés à l’avenir. Pour gérer les événements inconnus, votre gestionnaire de webhook peut considérer toute action sur un périmètre restreint comme une action `"update"` sur le périmètre plus large.

Par exemple, si l’étendue `"repo.config.dois"` est ajoutée à l’avenir, tout événement portant cette étendue peut être considéré par votre gestionnaire de webhook comme une action `"update"` sur l’étendue `"repo.config"`.

### Dépôt

Dans la version actuelle des webhooks, la propriété de premier niveau `repo` est toujours spécifiée, car les événements peuvent toujours être associés à un dépôt. Par exemple, considérez la valeur suivante :

```json
"repo": {
	"type": "model",
	"name": "some-user/some-repo",
	"id": "6366c000a2abcdf2fd69a080",
	"private": false,
	"url": {
		"web": "https://huggingface.co/some-user/some-repo",
		"api": "https://huggingface.co/api/models/some-user/some-repo"
	},
	"headSha": "c379e821c9c95d613899e8c4343e4bfee2b0c600",
	"owner": {
		"id": "61d2000c3c2083e1c08af22d"
	}
}
```

`repo.headSha` est le sha du dernier commit sur la branche `main` du dépôt. Il n’est envoyé que lorsque `event.scope` commence par `"repo"`, et non pour les événements communautaires tels que les discussions et les commentaires, ni pour les buckets, qui n’ont pas d’historique Git.

### Modifications du code

En cas de modifications de code, la propriété de premier niveau `updatedRefs` est spécifiée sur les événements de dépôt. Il s’agit d’un tableau de références qui ont été mises à jour. Voici un exemple de valeur :

```json
"updatedRefs": [
  {
    "ref": "refs/heads/main",
    "oldSha": "ce9a4674fa833a68d5a73ec355f0ea95eedd60b7",
    "newSha": "575db8b7a51b6f85eb06eee540738584589f131c"
  },
  {
    "ref": "refs/tags/test",
    "oldSha": null,
    "newSha": "575db8b7a51b6f85eb06eee540738584589f131c"
  }
]
```

Les références nouvellement créées auront `oldSha` défini sur `null`. Les références supprimées auront `newSha` défini sur `null`.

Vous pouvez réagir à de nouveaux commits sur des pull requests spécifiques, de nouveaux tags ou de nouvelles branches.

### Buckets

[Buckets](./storage-buckets) ne sont pas des dépôts Git : ils ne comportent ni commits, ni branches, ni tags. Les événements de cycle de vie (`create`, `delete`, `move` et les mises à jour de configuration telles que la visibilité) utilisent les mêmes étendues `"repo"` / `"repo.config"` que les autres types de dépôts.

Les modifications de fichiers utilisent `"repo.content"`, mais la charge utile possède une propriété `updatedFiles` au lieu de `updatedRefs`. L'écrasement d'un fichier existant est signalé comme un `"add"`. Voici un exemple de charge utile après l'ajout d'un fichier et la suppression d'un autre :

```json
{
  "event": {
    "action": "update",
    "scope": "repo.content"
  },
  "repo": {
    "type": "bucket",
    "name": "some-user/some-bucket",
    "id": "6366c000a2abcdf2fd69a080",
    "private": false,
    "url": {
      "web": "https://huggingface.co/buckets/some-user/some-bucket",
      "api": "https://huggingface.co/api/buckets/some-user/some-bucket"
    },
    "owner": {
      "id": "61d2000c3c2083e1c08af22d"
    }
  },
  "updatedFiles": [
    {
      "path": "data/train.txt",
      "action": "add",
      "xetHash": "55faef2f2f80cd1a087c35b729f228960739441d38073cd5aa4320751e137166",
      "size": 20
    },
    {
      "path": "data/old.txt",
      "action": "delete"
    },
    ...
  ],
  "updatedFilesTruncated": true,
  "webhook": {
    "id": "6390e855e30d9209411de93b",
    "version": 3
  }
}
```

Au-delà de 10 000 entrées, la liste est tronquée et `updatedFilesTruncated` est défini sur `true`. Dans ce cas, listez le bucket pour obtenir une vue d'ensemble.

Les buckets n'ont ni discussions ni Pull Requests, vous ne recevrez donc jamais d'événements `"discussion"` et `"discussion.comment"` pour eux.

Si vous souhaitez qu'un client suive directement les modifications des fichiers d'un bucket plutôt que via un rappel vers votre propre serveur, les buckets exposent également un [flux de suivi en direct](./storage-buckets#live-follow).

### Modifications de configuration

Lorsque la propriété de premier niveau `event.scope` est `"repo.config"`, la propriété `updatedConfig` est spécifiée. Il s’agit d’un objet contenant la configuration mise à jour. Voici un exemple de valeur :

```json
"updatedConfig": {
  "private": false
}
```

Lorsque la clé de configuration mise à jour n'est pas prise en charge par le webhook, l'objet sera vide :

```json
"updatedConfig": {}
```

Pour le moment, seul `private` est pris en charge. Si vous pensez que la présence de clés de configuration supplémentaires ici vous serait utile, merci de nous en informer à website@huggingface.co.

### Discussions et Pull Requests

La propriété de premier niveau `discussion` est spécifiée sur les événements de la communauté (discussions et Pull Requests). La propriété `discussion.isPullRequest` est un booléen indiquant si la discussion est également une Pull Request (sur le Hub, une PR est un type spécial de discussion). Voici un exemple de valeur :

```json
"discussion": {
	"id": "639885d811ae2bad2b7ba461",
	"title": "Hello!",
	"url": {
		"web": "https://huggingface.co/some-user/some-repo/discussions/3",
		"api": "https://huggingface.co/api/models/some-user/some-repo/discussions/3"
	},
	"status": "open",
	"author": {
		"id": "61d2000c3c2083e1c08af22d"
	},
	"isPullRequest": true,
	"changes": {
		"base": "refs/heads/main"
	}
	"num": 3
}
```

### Comment

La propriété de premier niveau `comment` est spécifiée lors de la création d'un commentaire (y compris lors de la création d'une discussion) ou de sa mise à jour. Voici un exemple de valeur :

```json
"comment": {
	"id": "6398872887bfcfb93a306f18",
	"author": {
		"id": "61d2000c3c2083e1c08af22d"
	},
	"content": "This adds an env key",
	"hidden": false,
	"url": {
		"web": "https://huggingface.co/some-user/some-repo/discussions/4#6398872887bfcfb93a306f18"
	}
}
```

## Secret de webhook

Définir un secret de Webhook est utile pour s’assurer que les charges utiles envoyées à l’URL de votre gestionnaire de Webhook proviennent bien de Hugging Face.

Si vous définissez un secret pour votre Webhook, il sera envoyé en tant qu'en-tête HTTP `X-Webhook-Secret` sur chaque requête. Seuls les caractères ASCII sont pris en charge.

> [!TIP]
> Il est également possible d'ajouter le secret directement dans l'URL du handler. Par exemple, en le définissant comme un paramètre de requête : https://example.com/webhook?secret=XXX.
>
> Cela peut être utile si l'accès aux en-têtes HTTP de la requête est complexe pour votre gestionnaire de Webhook.

## Livraison et nouvelles tentatives

Les charges utiles des webhooks sont livrées de manière asynchrone, peu après que l'événement se produit sur le Hub. L'ordre n'est pas garanti : si plusieurs événements se produisent à court intervalle, ils peuvent arriver dans le désordre.

Votre gestionnaire doit accuser réception d’une livraison avec un code de statut `2xx`. Tout autre code de statut est considéré comme une livraison échouée, tout comme une erreur de connexion : elle est réessayée avec un backoff. Si votre traitement est lent, répondez immédiatement avec un `2xx` et effectuez le travail de manière asynchrone, afin que la livraison ne soit pas considérée comme échouée.

Chaque livraison possède un en-tête HTTP `Webhook-Id` unique. Les nouvelles tentatives d’une livraison échouée réutilisent le même identifiant, ce qui permet de le considérer comme une clé d’idempotence et de traiter chaque événement une seule fois.

Lorsque les livraisons vers un Webhook échouent de manière répétée, le Webhook est automatiquement suspendu et son propriétaire est notifié par e-mail. Vous pouvez le diagnostiquer et le réactiver depuis les [paramètres](https://huggingface.co/settings/webhooks) de vos Webhooks.

## Limitation de débit

Chaque Webhook est limité à 1 000 déclenchements par 24 heures. Vous pouvez consulter votre utilisation dans l’onglet « Activity » de la page des paramètres Webhook.

Si vous devez augmenter le nombre de déclencheurs pour votre Webhook, passez à PRO, Team ou Enterprise et contactez-nous à website@huggingface.co.

## Développer vos Webhooks

Si vous ne disposez pas d’un point de terminaison/URL HTTPS, vous pouvez essayer des outils publics de test de webhook. Ces outils agissent comme des pièges à requêtes (capturent toutes les requêtes) qui leur sont envoyées et renvoient le code de statut 200 OK. [Beeceptor](https://beeceptor.com/) est un outil que vous pouvez utiliser pour créer un point de terminaison HTTP temporaire et examiner la charge utile entrante. Un autre outil de ce type est [Webhook.site](https://webhook.site/).

De plus, vous pouvez acheminer une charge utile Webhook réelle vers le code exécuté localement sur votre machine pendant le développement. C'est une excellente façon de tester et de déboguer pour des intégrations plus rapides. Vous pouvez le faire en exposant le port de votre localhost à Internet. Pour pouvoir suivre cette voie, vous pouvez utiliser [ngrok](https://ngrok.com/) ou [localtunnel](https://theboroer.github.io/localtunnel-www/).

## Débogage des Webhooks

Vous pouvez facilement trouver les événements générés récemment pour vos webhooks. Ouvrez l’onglet Activité de votre webhook. Vous y verrez la liste des événements récents.

![image.png](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/webhook-payload.png)
 
Vous pouvez ici consulter le code de statut HTTP et la charge utile des événements générés. De plus, vous pouvez rejouer ces événements en cliquant sur le bouton `Replay` !

Note : lors de la modification de l’URL cible ou du secret d’un Webhook, la rejouance d’un événement enverra la charge utile à l’URL mise à jour.

Note : Un événement rejoué est envoyé avec le même `Webhook-Id` que la livraison d'origine.

## FAQ

##### Puis-je définir des webhooks sur mon organisation plutôt que sur mon compte utilisateur ?

Non, ce n'est pas pris en charge pour le moment.

##### Comment puis-je m'abonner à tous les événements sur HF (ou à l'ensemble d'un type de dépôt, comme sur tous les modèles) ?

Cela n'est pas actuellement exposé aux utilisateurs finaux, mais nous pouvons l'activer pour vous si vous envoyez un e-mail à website@huggingface.co.

