送信 Webhook
送信 Webhook とは、ホスティングアカウントに何かが起きたときに、パネルがお客様のアドレスへ送るメッセージです。 これにより、ご自身の請求システム、チャットチャンネル、スプレッドシート、プロビジョニングスクリプトなど、 別のシステムが反応できます。
Webhook を使えるのは 管理者 と リセラー です。管理者はすべてのアカウントについて通知を受け取ります。 リセラーが受け取るのは、そのリセラーに属するアカウントについてだけです。顧客と API トークンは作成できません。 Webhook はパネル自体で、本人のセッション内で設定します。これは、漏えいしたトークンがパネルのイベントを 恒久的に受け取り続ける手段にならないようにするためです。
追加する
アカウントのセキュリティページ(管理者: セキュリティ、リセラー: ログインセキュリティ)を開き、 API トークンの下にある Webhook を探します。
- アドレスを入力します。例:
https://example.com/hooks/panel - 受け取りたいイベントにチェックを入れます。
- Webhook を追加 を押します。
パネルは 署名用シークレット(whsec_ で始まります)を 1 回だけ 表示します。今すぐコピーしてください。
暗号化して保管されており、再表示できません。紛失した場合は、その Webhook を削除して新しく追加してください。
1 人あたり最大 10 件の Webhook を持てます。
アドレス
https://で始まる必要があります。呼び出しにはアカウントの詳細が含まれるため、プレーンなhttp://は拒否されます。- ユーザー名やパスワードを含めることはできません。代わりに署名を確認してください。
- 最大 500 文字です。
- 公開インターネット上にある必要があります。このサーバー上、プライベートネットワーク上、ループバック インターフェース上、またはクラウドプロバイダーのメタデータ範囲にあるアドレスは、アドレスを保存するときと、 パネルが接続する時点の両方で拒否されます(そのため、あとからホスト名がプライベートアドレスを指すように なっても動作しません)。
- リダイレクトには従いません。最終的なアドレスを指定してください。
イベント
| イベント | 送信されるタイミング |
|---|---|
account.created |
ホスティングアカウントが作成されたとき |
account.suspended |
アカウントが停止されたとき |
account.unsuspended |
停止されていたアカウントが再開されたとき |
account.deleted |
アカウントが削除されたとき |
account.activity |
アカウントでその他のアクティビティがあったとき |
各 Webhook の テスト ボタンは ping というイベントを送信するので、アドレスが応答することを確認できます。
同時に待機できるテストは 1 件だけです。
送信される内容
各呼び出しは、JSON 本文を持つ HTTP POST です。
{
"event": "account.created",
"at": "2026-10-23T08:15:00Z",
"account": { "id": 42, "username": "example", "domain": "example.com" },
"detail": "short text about what happened"
}
at は UTC の時刻です。ping イベントの形式は {"event":"ping","at":"…","webhook_id":7} です。
すべての呼び出しには、次のヘッダーが付きます。
| ヘッダー | 意味 |
|---|---|
X-Nimbopanel-Event |
イベント名。例: account.created |
X-Nimbopanel-Delivery |
この配信を識別する番号。同じ配信の再試行では同じ番号が保たれるので、重複の無視に使います |
X-Nimbopanel-Timestamp |
呼び出しに署名した時刻(Unix 秒) |
X-Nimbopanel-Signature |
sha256= に続く署名(下記) |
Content-Type |
application/json |
User-Agent |
Nimbopanel-Webhook/1 |
署名を確認する
お客様のアドレスには、誰でもリクエストを送れます。呼び出しがお客様のパネルから来たものだと確認する手段が、 署名です。
署名は、タイムスタンプ、ドット、そして 受信したままの生の本文 をつなげたものに対する HMAC-SHA256 の 16 進表記で、署名用シークレットを使って計算されます。
X-Nimbopanel-Signature == "sha256=" + hex( HMAC_SHA256( secret, X-Nimbopanel-Timestamp + "." + body ) )
次の順序で確認してください。
- 上記の値を、生のリクエスト本文(JSON の解析や整形の前のもの)から計算します。
- 定数時間 の比較で、ヘッダーと比べます。
- タイムスタンプがお客様の時計から 5 分 以上離れている場合は、呼び出しを拒否します。これにより、 古い呼び出しの再送を防げます。
X-Nimbopanel-Deliveryを使って、すでに処理した配信を無視します。
PHP の例:
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_NIMBOPANEL_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_NIMBOPANEL_SIGNATURE'] ?? '';
$want = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!hash_equals($want, $sig) || abs(time() - (int) $ts) > 300) {
http_response_code(401);
exit;
}
Node.js の例:
const crypto = require('crypto');
function valid(rawBody, headers, secret) {
const ts = headers['x-nimbopanel-timestamp'] || '';
const want = 'sha256=' + crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex');
const got = headers['x-nimbopanel-signature'] || '';
return got.length === want.length
&& crypto.timingSafeEqual(Buffer.from(got), Buffer.from(want))
&& Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
}
応答、再試行、一時停止
- 10 秒 以内に、任意の 2xx ステータスで応答してください。それ以外は失敗として扱われます。
- 失敗した呼び出しは、1 分 後、続いて 5 分、30 分、2 時間 後に再試行されます。合計 5 回の 試行で、約 2 時間半にわたり、その後その配信は失敗としてマークされます。
- 1 つのアドレスへの呼び出しは、古いものから順に 1 件ずつ送られます。再試行待ちの配信が、新しい配信を 止めることはないので、イベントが厳密な順序で届くことを前提にしないでください。遅いアドレスが止めるのは、 そのアドレス自身だけです。
- 50 回連続 で配信に失敗すると、その Webhook は 一時停止 し、新しいイベントはキューに入らなくなります。 テスト が成功するとカウントがリセットされ、イベントが再び流れます。
- 1 つの Webhook につき、未配信の呼び出しは最大 200 件まで待機します。それを超えると、いくつかが配信される か失敗するまで、その Webhook への新しいイベントはキューに入りません。
- パネルは、Webhook ごとに完了した配信の最新 50 件を、受け取った応答とともに保持するので、何が失敗したかを 確認できます。直近のものは Webhook の下に一覧表示されます。
パネルがステータスの代わりに理由を表示した場合は、次のいずれかです。アドレスが公開インターネット上にない、 10 秒以内に応答がない、ホスト名が存在しない、HTTPS 証明書が有効でない、またはパネルが接続できなかった。
良い習慣
- すぐに
200で応答し、実際の処理はそのあとで行ってください。受信側が 10 秒より長くかかると失敗に見え、 同じイベントが再度届きます。 - 同じ配信を 2 回処理しても問題が起きないようにしてください。再試行やネットワークエラーにより、重複が 起こり得ます。
- シークレットをコードリポジトリに入れないでください。漏えいした場合は、その Webhook を削除して新しく 追加してください。
関連: リセラーガイド · トラブルシューティング