Webhook 通知
汎用 Webhook を使って、任意の HTTPS エンドポイントにインシデント通知を JSON 形式で送信できます。自社のシステムや自動化ツールとの連携に便利です。
- HTTPS 必須: HTTP(非暗号化)の URL は使用できません
- パブリックエンドポイント: プライベートネットワークの URL はブロックされます
- 署名検証用シークレット: 1 文字以上の任意の文字列
Manako での設定
Section titled “Manako での設定”- ダッシュボードの「通知チャンネル」メニューを開く
- 「Add Channel」で Type に Webhook を選択
- 受信先の HTTPS URL を入力
- 署名検証用のシークレットを入力
- チャンネル名を入力して「Add Channel」をクリック
通知は POST リクエストとして送信されます。Content-Type は application/json です。
共通フィールド
Section titled “共通フィールド”すべてのイベントに含まれるフィールド:
| フィールド | 型 | 説明 |
|---|---|---|
event | string | イベント種別(incident.created, incident.resolved, webchange.detected) |
monitorName | string | モニター名 |
monitorId | string | null | モニター ID(モニター削除済みの場合は null) |
teamId | string | チーム ID |
incidentId | string | インシデント ID |
timestamp | string | ISO 8601 形式のタイムスタンプ |
イベント別追加フィールド
Section titled “イベント別追加フィールド”| イベント | フィールド | 型 | 説明 |
|---|---|---|---|
incident.created | monitorUrl | string | 監視対象の URL |
incident.created | severity | string | 重大度("critical" または "warning") |
incident.created / incident.resolved | title | string | undefined | 手動インシデントのタイトル(自動インシデントでは省略) |
webchange.detected | diffSummary | string | 変更差分の概要 |
ペイロード例
Section titled “ペイロード例”{ "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"}{ "event": "incident.resolved", "monitorName": "API Server", "monitorId": "01JWAB1234567890ABCDEF", "teamId": "01JWAB0987654321FEDCBA", "incidentId": "01JWABINCIDENT12345678", "timestamp": "2025-01-15T10:45:00.000Z"}{ "event": "webchange.detected", "monitorName": "Pricing Page", "monitorId": "01JWAB1234567890ABCDEF", "teamId": "01JWAB0987654321FEDCBA", "incidentId": "01JWABINCIDENT12345678", "diffSummary": "Price changed from $10 to $15", "timestamp": "2025-01-15T11:00:00.000Z"}通知リクエストには X-Manako-Signature ヘッダーが付与されます。リクエストボディの HMAC-SHA256 署名をシークレットで検証することで、リクエストが Manako から送信されたものであることを確認できます。
署名のフォーマットは sha256=\{hex_digest\} です。
検証コード例
Section titled “検証コード例”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");});import hashlibimport hmacimport os
def verify_signature(body: bytes, secret: str, signature: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature)
# Flask の例@app.route("/webhook", methods=["POST"])def webhook(): signature = request.headers.get("X-Manako-Signature", "") if not verify_signature( request.get_data(), os.environ["WEBHOOK_SECRET"], signature ): return "Invalid signature", 401 payload = request.get_json() print(f"Event: {payload['event']}, Monitor: {payload['monitorName']}") return "OK", 200