# Webhooks

WebhooksはMLOps関連の機能の基盤です。特定のリポジトリ、または特定のユーザー/組織に属するすべてのリポジトリ（自分のリポジトリだけでなく、任意のリポジトリ）での新しい変更を監視できます。

これらを使用して、モデルの自動変換、コミュニティボットの構築、またはモデル、データセット、Spaces、バケット（およびその他多くのもの）のCI/CDの構築を行うことができます。Webhooksは、リポジトリのイベントに応じて計算タスクを自動化するために、[Jobsをトリガー](./jobs-webhooks)することもできます。

Webhooksのドキュメントは以下の通りです。また、Webhooksのいくつかのユースケースを紹介する**ガイド**もご覧いただけます。
- [データセットが更新されるたびに新しいモデルをファインチューニングする（Python）](./webhooks-guide-auto-retrain)
- [LLM API（NodeJS）を使用して、Hubにディスカッションボットを作成する](./webhooks-guide-discussion-bot)
- [メタデータの品質レポートを作成する（Python）](./webhooks-guide-metadata-review)
- [Jobs (CLI) でバケット内の新しいファイルを処理する](./webhooks-guide-bucket-jobs)
- さらに続きます…

## Webhookを作成する

Webhooksの[設定](https://huggingface.co/settings/webhooks)で、新しいWebhookを作成したり、既存のWebhookを編集したりできます:

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

Webhooksは、リポジトリの更新、Pull Requests、ディスカッション、新しいコメントの監視を行うことができます。Webhooksに反応するためのSpaceを作成することも可能です。

## Webhookペイロード

Webhookを登録すると、指定されたターゲットURLに対して`HTTP POST`コールが送信され、新しいイベントについて通知されます。ペイロードはJSONでエンコードされます。

Webhook設定ページのアクティビティタブで、送信されたペイロードの履歴を確認できます。また、デバッグを容易にするために、過去のWebhookをリプレイすることも可能です。

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

例として、Pull Request がオープンされた場合の完全なペイロードを以下に示します。

```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
  }
}
```

### イベント

トップレベルのプロパティ`event`は常に指定され、イベントの性質を決定するために使用されます。

2つのサブプロパティがあります: `event.action`と`event.scope`。

`event.scope`は、以下のいずれかの値になります。

- `"repo"` - リポジトリに関するグローバルイベント。関連する`action`の値として指定可能なもの: `"create"`、`"delete"`、`"update"`、`"move"`。
- `"repo.content"` - リポジトリのコンテンツに関するイベント。新しいコミットやタグの作成などです。新しく作成されたリファレンス/コミットにより、新しい Pull Request でもトリガーされます。Buckets の場合は、Git リファレンスではなく、ファイルの追加または削除でトリガーされます。関連する `action` は常に `"update"` です。
- `"repo.config"` - 設定に関するイベント: Space シークレットの更新、設定の更新、DOI の更新、無効化の有無など。関連する `action` は常に `"update"` です。
- `"discussion"` - ディスカッションまたは Pull Request の作成、タイトルまたはステータスの更新、マージ。関連する `action` の取り得る値: `"create"`、`"delete"`、`"update"`。
- `"discussion.comment"` - コメントの作成、更新、非表示化。関連する`action`の可能な値: `"create"`、`"update"`。

将来、さらに多くのスコープが追加される可能性があります。不明なイベントを処理するために、Webhookハンドラーでは、狭いスコープに対するあらゆるアクションを、より広いスコープに対する`"update"`アクションとみなすことができます。

例えば、将来`"repo.config.dois"`スコープが追加された場合、そのスコープを持つイベントは、`"repo.config"`スコープに対する`"update"`アクションとして、Webhookハンドラーによって処理できます。

### リポジトリ

現在のwebhooksのバージョンでは、イベントは常にリポジトリに関連付けられるため、トップレベルのプロパティ`repo`は常に指定されます。例えば、次のような値を考慮してください。

```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` は、リポジトリの `main` ブランチの最新コミットの sha です。これは `event.scope` が `"repo"` で始まる場合のみ送信され、ディスカッションやコメントなどのコミュニティイベントでは送信されません。また、Git の履歴を持たないバケットでも送信されません。

### コードの変更

コード変更について、リポジトリイベントではトップレベルのプロパティ`updatedRefs`が指定されます。これは更新されたリファレンスの配列です。値の例を以下に示します。

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

新規作成されたリファレンスには、`oldSha`が`null`に設定されます。削除されたリファレンスには、`newSha`が`null`に設定されます。

特定のプルリクエスト、新しいタグ、または新しいブランチへの新しいコミットに対して、リアクションを設定できます。

### バケット

[Buckets](./storage-buckets)はGitリポジトリではありません。コミット、ブランチ、タグを持ちません。ライフサイクルイベント（`create`、`delete`、`move`、および可視性などの設定更新）は、他のリポジトリタイプと同様に、`"repo"` / `"repo.config"`スコープを使用します。

ファイルの変更は`"repo.content"`を使用しますが、ペイロードには`updatedRefs`の代わりに`updatedFiles`プロパティがあります。既存のファイルを上書きすることは`"add"`として報告されます。1つのファイルが追加され、別のファイルが削除された後のペイロードの例を以下に示します。

```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
  }
}
```

10,000 件を超える場合、リストは短縮され、`updatedFilesTruncated` が `true` に設定されます。その場合は、バケットをリスト表示して全体像を確認してください。

BucketsにはディスカッションやPull Requestが存在しないため、それらに関する`"discussion"`および`"discussion.comment"`イベントは受信されません。

クライアントが独自のサーバーへのコールバックを介さず、バケットのファイル変更を直接追跡できるようにしたい場合は、バケットは[ライブフォローストリーム](./storage-buckets#live-follow)も公開しています。

### 設定の変更

トップレベルのプロパティ`event.scope`が`"repo.config"`の場合、`updatedConfig`プロパティが指定されます。これは更新された設定を含むオブジェクトです。値の例を以下に示します。

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

更新された設定キーがWebhookによってサポートされていない場合、オブジェクトは空になります:

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

現時点では`private`のみがサポートされています。ここに他の設定キーが存在すると有用な場合は、website@huggingface.co までお知らせください。

### ディスカッションとプルリクエスト

トップレベルのプロパティ`discussion`は、コミュニティイベント（ディスカッションとPull Request）で指定されます。`discussion.isPullRequest`プロパティは、そのディスカッションがPull Requestでもあるかどうかを示すブール値です（Hubでは、PRはディスカッションの特殊なタイプです）。値の例を以下に示します。

```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`は、コメントが作成（ディスカッションの作成を含む）または更新されたときに指定されます。値の例を以下に示します。

```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"
	}
}
```

## Webhookシークレット

Webhookシークレットを設定することで、WebhookハンドラーURLに送信されたペイロードが実際にHugging Faceからのものであることを確認できます。

Webhookにシークレットを設定すると、すべてのリクエストで`X-Webhook-Secret` HTTPヘッダーとして送信されます。ASCII文字のみがサポートされています。

> [!TIP]
> ハンドラーのURLにシークレットを直接追加することも可能です。例えば、クエリパラメータとして設定します: https://example.com/webhook?secret=XXX。
>
> WebhookハンドラーでリクエストのHTTPヘッダーへのアクセスが複雑な場合、これは役立ちます。

## 配信とリトライ

Webhookペイロードは、Hub上でイベントが発生した直後に非同期で配信されます。順序は保証されません。複数のイベントが短時間の間に発生した場合、到着順序が入れ替わる可能性があります。

ハンドラーは、`2xx`ステータスコードで配信を承認する必要があります。その他のステータスコードは、接続エラーと同様に配信失敗とみなされ、バックオフを伴って再試行されます。処理が遅い場合は、配信が失敗とみなされないように、すぐに`2xx`で応答し、処理を非同期で実行してください。

各配信には一意の`Webhook-Id` HTTP ヘッダーが付与されます。失敗した配信のリトライでは同じ ID が再利用されるため、これを冪等性キーとして扱い、各イベントを一度だけ処理できます。

Webhook への配信が繰り返し失敗すると、Webhook は自動的に停止され、所有者にメールで通知されます。[設定](https://huggingface.co/settings/webhooks)からトラブルシューティングを行い、再度有効にできます。

## レート制限

各Webhookは24時間あたり1,000回のトリガーに制限されています。使用状況は、Webhook設定ページの「Activity」タブで確認できます。

Webhook のトリガー数を増やす必要がある場合は、PRO、Team、Enterprise にアップグレードし、website@huggingface.co までご連絡ください。

## Webhookの開発

HTTPS エンドポイント/URL をお持ちでない場合は、Webhook のテスト用の公開ツールを試すことができます。これらのツールは、送信されたすべてのリクエストをキャッチオール（キャプチャ）し、200 OK ステータスコードを返します。[Beeceptor](https://beeceptor.com/) は、一時的な HTTP エンドポイントを作成し、受信したペイロードを確認するために使用できるツールの一つです。同様のツールとして、[Webhook.site](https://webhook.site/) もあります。

さらに、開発中にローカルマシンで実行されているコードに実際のWebhookペイロードをルーティングできます。これは、より迅速な統合のためにテストやデバッグを行うのに最適な方法です。この方法を実行するには、localhostのポートをインターネットに公開します。このアプローチを取るには、[ngrok](https://ngrok.com/)または[localtunnel](https://theboroer.github.io/localtunnel-www/)を使用できます。

## Webhookのデバッグ

Webhookの最近生成されたイベントを簡単に確認できます。Webhookのアクティビティタブを開くと、最近のイベントの一覧が表示されます。

![image.png](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/webhook-payload.png)
 
ここでは、生成されたイベントのHTTPステータスコードとペイロードを確認できます。さらに、`Replay`ボタンをクリックすることで、これらのイベントを再生成できます。

Note: WebhookのターゲットURLまたはシークレットを変更した場合、イベントのリプレイではペイロードが更新されたURLに送信されます。

注: リプレイされたイベントは、元の配信と同じ`Webhook-Id`で送信されます。

## よくある質問

##### 組織とユーザーアカウントのどちらにWebhookを定義できますか?

いいえ、現在これはサポートされていません。

##### HF全体（またはモデルなど特定のリポジトリタイプ全体）のすべてのイベントにどのように購読できますか？

現在、これはエンドユーザーには公開されていませんが、website@huggingface.co へメールを送っていただければ、こちらで切り替えることができます。

