Webhook
プロジェクトページで 1 つ以上の Webhook URL を設定します。有効な Webhook は、各イベントごとに HMAC-SHA256 で署名された JSON を POST で受け取ります。配信失敗 (5xx / 408 / 429 / ネットワークエラー) は指数バックオフで再試行 (30 秒 → 2 分 → 10 分 → 1 時間、最大 5 回)。再試行時は X-Nesh-Attempt ヘッダに試行回数が入ります。
各 Webhook はイベント種別の一部だけにフィルタできます。デフォルト (全チェックボックス選択) は全イベントを受信します。
イベント
notification.sent | 通知の送信完了後 (ダッシュボード / REST / cron)。 |
subscription.created | 新規エンドポイントの購読 (再購読は発火しません)。 |
subscription.removed | 購読が削除された — クライアントの DELETE か、push サービスが 404/410 を返した場合。 |
notification.sent
POST <your-webhook-url>
Content-Type: application/json
X-Nesh-Event: notification.sent
X-Nesh-Signature: sha256=<hex hmac of body>
{
"type": "notification.sent",
"notification": {
"id": "uuid",
"project_id": "uuid",
"title": "Hello",
"body": "From Nesh",
"url": "https://example.com",
"delivered": 11,
"removed": 1,
"failed": 0,
"target_user_ids": ["alice"],
"sent_at": "2026-05-05T18:00:00.000Z"
}
}subscription.created
X-Nesh-Event: subscription.created
{
"type": "subscription.created",
"subscription": {
"id": "uuid",
"project_id": "uuid",
"endpoint": "https://fcm.googleapis.com/...",
"external_user_id": "alice",
"created_at": "2026-05-05T18:00:00.000Z"
}
}subscription.removed
reason: "client" は SDK / ダッシュボードからの DELETE、reason: "expired" は送信時に push サービスが 404/410 を返し、Nesh が失効した購読を自動で削除したことを示します。
X-Nesh-Event: subscription.removed
{
"type": "subscription.removed",
"subscription": {
"project_id": "uuid",
"endpoint": "https://fcm.googleapis.com/...",
"external_user_id": "alice",
"reason": "client",
"removed_at": "2026-05-05T18:00:00.000Z"
}
}署名を検証する (Node.js)
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(body, signatureHeader, secret) {
const expected = "sha256=" + createHmac("sha256", secret).update(body).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader);
return a.length === b.length && timingSafeEqual(a, b);
}本文は生バイトで比較してください (JSON パースの前にリクエストボディを読む)。Webhook 配信は 5 秒タイムアウト、非 2xx レスポンスは最終配信エラーとして記録されダッシュボードに表示されます。