コンテンツにスキップ

Webhook 通知

汎用 Webhook を使って、任意の HTTPS エンドポイントにインシデント通知を JSON 形式で送信できます。自社のシステムや自動化ツールとの連携に便利です。

  • HTTPS 必須: HTTP(非暗号化)の URL は使用できません
  • パブリックエンドポイント: プライベートネットワークの URL はブロックされます
  • 署名検証用シークレット: 1 文字以上の任意の文字列
  1. インターネットから到達できる HTTPS エンドポイントを用意し、POST の JSON ボディを受け取れるようにする
  2. Manako と受信側だけが共有する署名検証用シークレットを生成する
  3. 受信時に raw リクエストボディと X-Manako-Signature を使って HMAC-SHA256 署名を検証する
  4. 正常に受理したときは 2xx を返す。3xx リダイレクトは追従されません
  1. ダッシュボードで「設定」>「連携」を開き、Webhook の「設定」を選択
  2. 名前に識別しやすい名前を入力
  3. Webhook URL (HTTPS) に受信先 URL を入力
  4. Secret に受信側と共有するシークレットを入力
  5. 「追加」を選択

通知は POST リクエストとして送信されます。Content-Typeapplication/json です。

すべてのイベントに含まれるフィールド:

フィールド説明
eventstringイベント種別
teamIdstringチーム ID
timestampstringISO 8601 形式のタイムスタンプ

monitorNamemonitorIdincidentId はインシデントイベントに含まれます。メンテナンスイベントは代わりに monitorIdsmonitorNames を含みます。

イベントフィールド説明
incident.createdmonitorUrlstring監視対象の URL
incident.createdseveritystring重大度("critical" または "warning")
incident.created / incident.resolvedtitlestring | undefined手動インシデントのタイトル(自動インシデントでは省略)
maintenance.startedmonitorIds, monitorNames, maintenanceUntilstring[] / string対象モニターと終了予定時刻
maintenance.endedmonitorIds, monitorNamesstring[]対象モニター
{
"event": "incident.created",
"monitorName": "API Server",
"monitorId": "01JWAB1234567890ABCDEF",
"teamId": "01JWAB0987654321FEDCBA",
"incidentId": "01JWABINCIDENT12345678",
"monitorUrl": "https://api.example.com/health",
"severity": "critical",
"timestamp": "2025-01-15T10:30:00.000Z"
}

通知リクエストには X-Manako-Signature ヘッダーが付与されます。リクエストボディの HMAC-SHA256 署名をシークレットで検証することで、リクエストが Manako から送信されたものであることを確認できます。

署名のフォーマットは sha256=\{hex_digest\} です。

import crypto from "node:crypto";
function verifySignature(body, secret, signature) {
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(body).digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
);
}
// Express の例
app.post("/webhook", express.text({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-manako-signature"];
if (!verifySignature(req.body, process.env.WEBHOOK_SECRET, signature)) {
return res.status(401).send("Invalid signature");
}
const payload = JSON.parse(req.body);
console.log(`Event: ${payload.event}, Monitor: ${payload.monitorName}`);
res.status(200).send("OK");
});
  • 設定時に URL エラーになる: HTTPS で公開され、DNS 解決後もプライベート/予約済みアドレスに到達しない URL が必要です。
  • 受信側がリダイレクトする: Manako は redirect: "manual" で送信するため、最終受信 URL を直接設定してください。
  • 署名が一致しない: JSON を再シリアライズせず、受信した raw body に対して sha256={hex} を計算します。Manako に保存した Secret と同じ値を使ってください。
  • テストは届くが通常通知が届かない: テストの eventtest です。通常通知ではモニター個別の通知先関連付けも確認してください。関連付けがすべて無効でもチーム全体へはフォールバックしません。
  • 短時間の通知が途中から届かない: 同じモニターで 10 分以内に 3 回を超える状態変化があるとフラップ抑制が働きます。
  • 重複して見える: 同じインシデント・チャンネル・イベント種別の送信済み再試行はスキップされ、DB の UNIQUE 制約も重複記録を防ぎます。失敗または処理中の記録は再試行されます。

「Test」は実際に event: "test" の署名付きリクエストを送り、成功後は 60 秒のクールダウンがあります。1つの Webhook の失敗は他チャンネルの送信を止めません。

フラップ抑制とインシデント単位の送信済み判定はインシデント通知に適用されます。メンテナンス通知はこれらを使わず、有効かつ確認済みのチームチャンネルへ送信されます。