コンテンツにスキップ
Hearl
Esc
↑↓移動↵開く⌘Jプレビュー
このページの内容

通知

対応が必要な会話のメールダイジェストと Webhook。署名の検証についても説明します。

Hearl は、会話に対応が必要になった時点でチームに知らせることができます。設定は通知ページで行います。この設定を変更できるのは、オーナーと管理者のみです。

通知が送られるタイミング

Hearl は15分ごとにチェックします。会話は、次の条件をすべて満たすと対象になります。

  • プラットフォームのステータスが未返信またはユーザーが再返信である
  • 進捗が未着手のままである
  • Hearl の AI が製品に関するものと判定していて、不確かな回答がない
  • 優先度が、設定した最低ラインと同じかそれ以上である。選べるのは、すべて、中以上、高のみのいずれかです

通知はステータスごとに、会話1件につき1回送られます。未返信として通知された会話で、その後ユーザーが再返信した場合は、ユーザーが再返信として改めて通知されます。

メール

メールを送信をオンにして、受信者を追加します。リストを空にすると、ワークスペースの全メンバーにメールが届きます。共有のサポート用アドレスなど、どのアドレスでも指定でき、最大20件までです。

チェックのたびに、最大10件の会話を載せたダイジェストを1通送ります。残りの会話は、受信トレイへのリンクから確認できます。言語で、英語か中国語を選べます。

Webhook

エンドポイントを入力します。公開された https の URL である必要があります。Hearl は、アドレスから一般的なチャットボットを判別し、それぞれが求める形式でメッセージを送ります。

アドレス 送信形式
hooks.slack.com Slack メッセージ
feishu.cn, larksuite.com Feishu テキストメッセージ
qyapi.weixin.qq.com WeCom Markdown メッセージ
oapi.dingtalk.com DingTalk Markdown メッセージ
discord.com, discordapp.com Discord メッセージ
その他の URL 汎用 JSON(下記)

ページには、検出された種類が表示されます。テスト送信でサンプルを送信でき、直近のプッシュの結果もページに表示されます。リクエストに8秒を超える時間がかかると、タイムアウトとして扱われます。

汎用 JSON

{
  "event": "conversations.needs_attention",
  "workspace": { "id": "org_123", "name": "Acme" },
  "text": "*2 conversations need attention* · Acme\n• [reddit] Sync stopped working after 2.3 — No reply yet <https://…>",
  "conversations": [
    {
      "id": "c_8f2a",
      "platform": "reddit",
      "product": "Acme",
      "title": "Sync stopped working after 2.3",
      "author": "some_user",
      "url": "https://www.reddit.com/r/…",
      "status": "待回复",
      "priority": "高",
      "category": "故障",
      "inbox_url": "https://hearl.org/app?c=c_8f2a"
    }
  ],
  "sent_at": "2026-11-08T09:15:00.000Z"
}
フィールド 説明
event conversations.needs_attention。テスト送信の場合は test。
workspace ワークスペースの id と name。
text そのまま投稿できる要約。Slack はこのフィールドだけを読み取ります。
conversations このプッシュに含まれるすべての会話。
sent_at プッシュを送信した日時(ISO 8601 形式)。

platform は x、reddit、hn のいずれかです。status、priority、category は中国語の固定コードです。ワークスペースの言語にかかわらず、コード側でこの値を使って判別できます。

フィールド コード 意味
status 待回复 未返信
status 用户有新回复 ユーザーが再返信
priority 高 / 中 / 低 高 / 中 / 低
category 故障 不具合
category 求助 質問
category 功能建议 機能要望
category 价格 料金
category 负面反馈 批判
category 正面反馈 称賛
category 购买咨询 購入検討
category 其他 その他

署名を検証する

Webhook のエンドポイントを保存すると、Hearl はそのエンドポイント用の署名シークレットを作成します。通知ページで、表示またはローテーションできます。リクエストには、次のヘッダーが付きます。

X-Hearloop-Signature: sha256=<hex>

<hex> は、リクエストボディ(生データ)の HMAC-SHA256 を、署名シークレットをキーとして計算し、小文字の16進数で表したものです。受信したバイト列をそのまま使い、JSON を解析する前に計算してください。比較は定数時間で行います。

import { createHmac, timingSafeEqual } from "node:crypto";
import express from "express";

const app = express();
const secret = process.env.HEARL_WEBHOOK_SECRET;

app.post("/hearl", express.raw({ type: "application/json" }), (req, res) => {
  const expected = "sha256=" + createHmac("sha256", secret).update(req.body).digest("hex");
  const received = req.get("x-hearloop-signature") ?? "";
  const ok =
    received.length === expected.length &&
    timingSafeEqual(Buffer.from(received), Buffer.from(expected));
  if (!ok) return res.status(401).end();

  const payload = JSON.parse(req.body.toString("utf8"));
  console.log(payload.event, payload.conversations.length);
  res.status(200).end();
});

app.listen(3000);
import hashlib
import hmac
import json
import os

from flask import Flask, abort, request

app = Flask(__name__)
SECRET = os.environ["HEARL_WEBHOOK_SECRET"].encode()


@app.post("/hearl")
def hearl():
    body = request.get_data()
    expected = "sha256=" + hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    received = request.headers.get("X-Hearloop-Signature", "")
    if not hmac.compare_digest(received, expected):
        abort(401)

    payload = json.loads(body)
    print(payload["event"], len(payload["conversations"]))
    return "", 200

プッシュを受け取ったことを知らせるには、任意の 2xx ステータスを返してください。

このページは役に立ちましたか?