> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rheel.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook

> チャットイベントをリアルタイムで受け取る

## Webhookとは

Webhookを使用すると、Rheel Chat APIで発生したイベント（メッセージ投稿、チャンネル作成など）を、あなたのサーバーにリアルタイムで通知できます。

## 主な用途

<CardGroup cols={2}>
  <Card title="通知連携" icon="bell">
    メッセージ投稿時にメール通知やプッシュ通知を送信
  </Card>

  <Card title="外部システム連携" icon="link">
    CRMやタスク管理ツールとの連携
  </Card>

  <Card title="ログ記録" icon="database">
    チャットログを外部データベースに保存
  </Card>

  <Card title="自動応答" icon="robot">
    特定のキーワードに反応するBot機能の実装
  </Card>
</CardGroup>

## Webhookの設定

### 1. エンドポイントURLの準備

Webhookを受け取るHTTPSエンドポイントを用意します。

<Warning>
  WebhookエンドポイントはHTTPSである必要があります。HTTPは使用できません。
</Warning>

### 2. Webhook URLの登録

管理画面からWebhook URLを登録します。

<img src="https://mintcdn.com/ecu-14ac9653/d6NZeQHBilluuhbg/images/register-webhook-url.png?fit=max&auto=format&n=d6NZeQHBilluuhbg&q=85&s=47e1ec7073c312986cf60e29fb9d62b8" alt="Register Webhook Url Pn" width="1996" height="672" data-path="images/register-webhook-url.png" />

1. [Dashboard](https://developers.rheel.net/api/auth/login)にログイン
2. アプリケーション設定を開く
3. Webhook URLを入力して保存

### 3. イベントの選択

受け取りたいイベントを選択します：

**メッセージ系**

* `channel:message_send` - メッセージが投稿された
* `channel:message_update` - メッセージが編集された
* `channel:messages_delete` - メッセージが削除された
* `channel:mark_message_as_read` - メッセージが既読になった

**チャンネル系**

* `channel:create` - チャンネルが作成された
* `channel:update` - チャンネルが更新された
* `channel:delete` - チャンネルが削除された
* `channel:archive` - チャンネルがアーカイブされた
* `channel:unarchive` - チャンネルがアーカイブ解除された

**ユーザー系**

* `user:create` - ユーザーが作成された
* `user:update` - ユーザーが更新された
* `user:delete` - ユーザーが削除された

**チャンネル参加/退出系**

* `channel:users_join` - ユーザーがチャンネルに参加した
* `channel:users_leave` - ユーザーがチャンネルから退出した

**リアクション系**

* `channel:message_reaction_add` - リアクションが追加された
* `channel:message_reaction_remove` - リアクションが削除された

**添付ファイル系**

* `channel:message_attachment_delete` - 添付ファイルが削除された

## Webhookペイロード

### リクエストヘッダー

```http theme={null}
POST /your-webhook-endpoint
Content-Type: application/json
X-Rheel-Signature: sha256=...
```

### ペイロード例（channel:message\_send）

```json theme={null}
{
  "eventType": "channel:message_send",
  "application_id": "app_123",
  "occurred_at": "2025-03-21T10:00:00Z",
  "data": {
    "id": "msg_123",
    "channel_id": "ch_456",
    "user_id": "user_789",
    "text": "こんにちは",
    "created_at": "2025-03-21T10:00:00Z"
  }
}
```

### ペイロード例（channel:message\_update - 更新系）

更新系イベントには`changes`フィールドが追加されます：

```json theme={null}
{
  "eventType": "channel:message_update",
  "application_id": "app_123",
  "occurred_at": "2025-03-21T10:05:00Z",
  "data": {
    "id": "msg_123",
    "channel_id": "ch_456",
    "user_id": "user_789",
    "text": "こんにちは（編集済み）",
    "updated_at": "2025-03-21T10:05:00Z"
  },
  "changes": [
    {
      "key": "text",
      "old": "こんにちは",
      "new": "こんにちは（編集済み）"
    }
  ]
}
```

## 署名検証

セキュリティのため、Webhookリクエストの署名を検証することを推奨します。

署名の検証には**アプリケーションのAPI Key**を使用します。

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function verifyWebhookSignature(payload, signature, apiKey) {
    const hmac = crypto.createHmac('sha256', apiKey);
    const digest = 'sha256=' + hmac.update(payload).digest('hex');
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(digest)
    );
  }

  // Express.jsの例
  app.post('/webhook', (req, res) => {
    const signature = req.headers['x-rheel-signature'];
    const isValid = verifyWebhookSignature(
      JSON.stringify(req.body),
      signature,
      process.env.RHEEL_API_KEY  // アプリケーションのAPI Key
    );

    if (!isValid) {
      return res.status(401).send('Invalid signature');
    }

    // イベント処理
    const event = req.body;
    console.log('Received event:', event.eventType);

    res.status(200).send('OK');
  });
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook_signature(payload: str, signature: str, api_key: str) -> bool:
      expected_signature = 'sha256=' + hmac.new(
          api_key.encode(),
          payload.encode(),
          hashlib.sha256
      ).hexdigest()
      return hmac.compare_digest(signature, expected_signature)

  # Flaskの例
  from flask import Flask, request
  import os

  app = Flask(__name__)

  @app.route('/webhook', methods=['POST'])
  def webhook():
      signature = request.headers.get('X-Rheel-Signature')
      payload = request.get_data(as_text=True)

      # アプリケーションのAPI Keyを使用
      api_key = os.environ.get('RHEEL_API_KEY')
      if not verify_webhook_signature(payload, signature, api_key):
          return 'Invalid signature', 401

      # イベント処理
      event = request.json
      print(f"Received event: {event['eventType']}")

      return 'OK', 200
  ```
</CodeGroup>

<Warning>
  署名検証には、管理画面で発行したアプリケーションのAPI Keyを使用してください。
</Warning>

## レスポンス要件

Webhookエンドポイントは以下の要件を満たす必要があります：

* **HTTPステータスコード**: `200-299`の成功ステータスコードを返す（例: `200 OK`, `204 No Content`）
* **タイムアウト**: 5秒以内にレスポンスを返す
* **冪等性**: 同じイベントが複数回送信される可能性があるため、冪等な処理を実装する

<Note>
  ネットワークエラーなどで配信に失敗した場合、最大3回まで自動的に再送されます。
</Note>

## リトライポリシー

Webhookの配信に失敗した場合、以下のスケジュールで再送されます：

| 試行回数 | 待機時間 |
| ---- | ---- |
| 1回目  | すぐ   |
| 2回目  | 1分後  |
| 3回目  | 5分後  |

3回とも失敗した場合、そのイベントは破棄されます。

## ベストプラクティス

<AccordionGroup>
  <Accordion title="非同期処理を使用する">
    Webhookハンドラー内で重い処理を行うと、タイムアウトが発生する可能性があります。

    イベントをキューに入れて非同期で処理することを推奨します。
  </Accordion>

  <Accordion title="冪等性を保証する">
    同じイベントが複数回送信される可能性があるため、`event_id`などを使用して重複処理を防ぎます。
  </Accordion>

  <Accordion title="エラーログを記録する">
    処理に失敗した場合のデバッグのため、エラーログを記録してください。
  </Accordion>

  <Accordion title="署名を必ず検証する">
    悪意のあるリクエストを防ぐため、署名検証を必ず実装してください。
  </Accordion>
</AccordionGroup>

## トラブルシューティング

### Webhookが届かない

1. エンドポイントURLが正しいか確認
2. HTTPSを使用しているか確認
3. ファイアウォール設定を確認
4. サーバーログでエラーを確認

### 署名検証が失敗する

1. Webhook Secretが正しいか確認
2. ペイロードの文字列化が正しいか確認（改行、スペースなど）
3. 署名アルゴリズムが`sha256`であることを確認

## 次のステップ

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/api-reference/overview">
    Webhook設定APIの詳細を確認
  </Card>

  <Card title="リアルタイム通信" icon="plug" href="/development">
    WebSocketとの使い分けを理解
  </Card>
</CardGroup>
