できること
フォームでお問い合わせを受け付けるたびに、登録した URL へ署名付きの JSON を POST します。Zapier や Make の「Webhook で受け取る」トリガー、CRM の受け口、自社のサーバーなどにつなげられます。
| 項目 | 内容 |
|---|---|
| プラン | 有料プラン(Lite・Standard・Business)だけ。Free プラン では使えません(契約が切れて Free と同じ扱いになったサイトも送りません) |
| 本数 | 1サイト5本まで。送るフォームを選べます(選ばなければ全フォーム) |
| 送り先 | https:// の URL だけ(送り先の制限) |
| 成功 | 10秒以内に 2xx が返ること |
| 再送 | 失敗したら 2・4・8・16・32・60・60分おきに送り直し、計8回で「失敗」(およそ3時間) |
| 操作 | 管理画面の「設定 → 詳細 → Webhook」、CLI の siteon webhooks、MCP の webhooks_*(CLI・MCP・API キー) |
追加・削除・テスト送信ができるのはサイトのオーナーだけです(スタッフは一覧を見るだけ)。お店へのメールや Slack の通知とは別に動き、Webhook が失敗してもお問い合わせは消えません。
追加する
管理画面の「設定 → 詳細 → Webhook」で送り先の URL と対象のフォームを選んで追加します。CLI なら:
siteon webhooks add https://hooks.example.com/siteon --site hanaya --form contact署名用の秘密(whsec_ で始まる文字列)は、追加したときに1回だけ表示されます。 受け取り側の環境変数などに保存してください。あとから見ることはできません。漏れたり失くしたりしたら、その Webhook を消して作り直します(新しい秘密が出ます)。
送る JSON
POST <登録した URL>、content-type: application/json で次を送ります。
{
"event": "form.submitted",
"site": "hanaya",
"form": "contact",
"submission_id": "…",
"submitted_at": "2026-10-04T09:30:00.000Z",
"data": { "name": "山田 花子", "email": "[email protected]", "message": "秋の花束を予約したいです" },
"attribution": {
"first": { "utm_source": "google", "utm_medium": "cpc", "gclid": "…", "landing": "/", "referrer": "…", "at": "…" },
"last": { "utm_source": "instagram", "landing": "/menu/", "at": "…" }
},
"test": false
}| キー | 中身 |
|---|---|
event | form.submitted(テスト送信は webhook.test) |
site / form | サイト ID / フォームのキー |
submission_id | 受付 ID。管理画面の一覧と同じ ID |
submitted_at | 受け付けた日時(ISO 8601・UTC) |
data | 入力内容(schema.json の fields[].key ごと) |
attribution | 流入元。first(最初に来たとき)と last(最後に来たとき)に utm_*・gclid・fbclid・着地ページ・参照元(流入元の記録) |
test | テスト送信なら true |
ヘッダ:
| ヘッダ | 中身 |
|---|---|
X-SiteKit-Signature | t=<UNIX 秒>,v1=<署名>。署名は HMAC-SHA256(秘密, t + "." + 本文) の16進 |
Idempotency-Key | 受付 ID(submission_id と同じ)。再送でも変わりません |
X-SiteKit-Event | event と同じ値 |
X-SiteKit-Delivery | 送信ごとの ID(調べるとき用) |
署名を確かめる
署名の形は Stripe の Webhook と同じです。受け取り側で次を確かめます。
- ヘッダから
tとv1を取り出す t + "." + 受け取った本文(そのままの文字列)を秘密で HMAC-SHA256 し、16進にしたものがv1と一致する(比べるときは時間が一定の比較を使う)tが今から5分以上ずれていたら拒否する(古い送信の使い回しを防ぐ)
本文は JSON として読み直す前の文字列で計算します。 読み直してから文字列に戻すと、空白や並びが変わって一致しません。
Node.js:
import crypto from "node:crypto";
// rawBody: 受け取ったままの本文(文字列)、header: X-SiteKit-Signature の値
export function verify(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((kv) => kv.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 ?? "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Python:
import hashlib, hmac, time
def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t = int(parts.get("t", "0"))
if not t or abs(time.time() - t) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))秘密は whsec_ を含めた文字列全体をそのまま鍵にします。
冪等性(同じ問い合わせが2回届いたとき)
応答が途中で切れた場合などに、同じお問い合わせが2回以上届くことがあります。Idempotency-Key(=submission_id)は再送でも同じなので、受け取り側で一度処理した ID は読み飛ばして 2xx を返してください。CRM に二重に登録されるのを防げます。
再送と失敗
- 受け付けた直後に1回目を送ります。失敗(2xx 以外・10秒を超えた・つながらない)したら、2・4・8・16・32・60・60分おきに送り直し、計8回で「失敗」として止めます
- リダイレクト(3xx)は追わず、失敗として扱います。 登録する URL はリダイレクトしない最終の URL にします
- 応答の本文は読みません。2xx を返すまでの時間を短くしたいときは、受け取り側でキューに積んでからすぐ 2xx を返します
- 送るたびに保存済みのお問い合わせから組み立てるので、再送の前にお問い合わせを消すと、その分はもう送りません
- 直近の送信結果は、管理画面の「設定 → 詳細 → Webhook」と
siteon webhooks listで見られます
送り先の制限
送り先は、追加するときと送るたびに確かめます。次のものは登録できず、送りません。
https://以外(http://など)。ポートの指定(既定の 443 以外)。user:pass@を含む URL- IP アドレスの直書き(公開の IP も不可)
- ドットの無い名前・
localhost・.local・.internal・.home.arpa・.test・.example・.invalidなどの内部向け・予約済みの名前 - Siteon 自身のホスト(API・管理画面・ホスティングの共通ドメインとそのサブドメイン)
社内のサーバーに送るときは、インターネットから https で届く公開の名前を用意してください。
テスト送信
管理画面の「設定 → 詳細 → Webhook」のテスト送信か、siteon webhooks test <id>(MCP の webhooks_test)で、保存済みの URL へ本物の秘密で署名したダミーを送り、結果(HTTP ステータス)を返します。
eventはwebhook.test、testはtrue、submission_idはtest_で始まります。dataは対象フォームの項目に合わせたダミー、attributionは空です- お問い合わせとしては保存されず、件数にも数えません
- 1本につき1分に1回まで(サイトの1日のテスト送信の枠にも数えます)
受け取り側では、test が true のものは署名だけ確かめて、本番の処理(CRM への登録など)はしないようにしておくと安全です。
API キーの権限
CLI・MCP から操作するときの鍵の権限です(CLI・MCP・API キー)。
| 操作 | 要る scope |
|---|---|
一覧(webhooks list / webhooks_list) | sites:read |
追加(webhooks add / webhooks_add) | sites:write と submissions:read の両方(入力内容を外に送れるようになるため) |
削除(webhooks remove / webhooks_remove) | sites:write |
テスト送信(webhooks test / webhooks_test) | forms:test |