Webhook の使い方

Reserve Care は、予約を受け付けたときと、予約を取り消したときに、登録した送り先(Webhook)へ予約の内容を送ります。Google Apps Script、Make、Zapier、n8n、ご自身のシステムなどで受け取って、台帳への記録やメールの送信などに使えます。

送り先は、管理画面のフォームの「送り先」のタブで登録します。1つのフォームに3つまで登録できます(Free)。

送る内容

予約を受け付けたとき(booking.created)と、予約を取り消したとき(booking.cancelled)に、次の JSON を POST で送ります。

{
  "version": 1,
  "event": "booking.created",
  "event_id": "evt_0123456789abcdef0123456789abcdef",
  "occurred_at": "2026-11-06T14:03:21+09:00",
  "booking_id": "8f1c2d3e-4b5a-6789-abcd-ef0123456789",
  "form_id": "1a2b3c4d-5e6f-7a8b-9c0d-e1f2a3b4c5d6",
  "form_name": "初回相談",
  "start_at": "2026-11-10T10:00:00+09:00",
  "end_at": "2026-11-10T10:30:00+09:00",
  "customer": {
    "name": "山田太郎",
    "email": "test@example.com",
    "phone": "090-0000-0000",
    "memo": "駐車場はありますか"
  }
}
項目 内容
version 送る内容の形の版。形を変えるときに上げます
event booking.created(受け付け)か booking.cancelled(取り消し)
event_id 出来事ごとの ID。再送のときも同じ値です。重複を見分けるのに使ってください
occurred_at 受け付けや取り消しが起きた日時
booking_id、form_id、form_name 予約とフォーム
start_at、end_at 予約の日時
customer 予約者が入力した名前、メールアドレス、電話番号、メモ。電話番号とメモは、入力がなければ null

日時は日本時間で、+09:00 付きの ISO 8601 の形です。

管理画面の「テスト送信」では、架空の予約の内容に "test": true を付けて送ります。

届いたことの扱い

  • 送り先が 2xx を返したら成功とします。10秒以内に応答してください
  • 3xx(別の URL への転送)は失敗として扱い、転送先には送りません。ただし、Google Apps Script の URL(script.google.com)が返す 302 は成功とします
  • 失敗したら、5分後、30分後、2時間後の3回、自動で再送します。それでも失敗したものは、管理画面の「送信の結果」から手動で再送できます
  • 再送でも同じ event_id を送るので、同じ event_id が届いたら、2回目以降は処理しないでください

署名の確かめ方

汎用の送り先には、届いたものが Reserve Care から送られたものかを確かめるための署名を付けます。

X-CareCraft-Signature: t=1762405401,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
  • t は送った時刻(UNIX 時間の秒)です
  • v1 は、<t>.<届いた本文そのまま> という文字列を、送り先の秘密の値を鍵にして HMAC-SHA256 で計算し、16進数の小文字にしたものです
  • 秘密の値(whsec_ で始まる値)は、管理画面の送り先の編集で確かめられます。作り直すと、古い値はすぐに使えなくなります

受け取る側では、次のように確かめてください。

  1. 届いた本文を JSON に変換する前に、そのままの文字列で署名を計算して比べる。比べるときは、時間で差が出ない方法を使う
  2. t が今の時刻から5分以上ずれていたら受け付けない
  3. 同じ event_id が届いたら、2回目以降は処理しない

Node.js での例です。

import crypto from "node:crypto";

// rawBody: 届いた本文(文字列のまま)、header: X-CareCraft-Signature の値
export function verify(rawBody, header, secret) {
  const match = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header ?? "");
  if (!match) return false;
  const t = Number(match[1]);
  if (Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(match[2]));
}

Google Apps Script で受け取る

Google Apps Script は、届いたリクエストのヘッダーを読めないので、署名を確かめられません。代わりに、ご自身で決めた長い文字列を URL に付けて、それを確かめてください。

  1. Google スプレッドシートを作り、シートの名前を「予約」にする
  2. 「拡張機能」→「Apps Script」を開き、次のコードを貼る。TOKEN は、推測されにくい長い文字列に書き換える
  3. 「デプロイ」→「新しいデプロイ」で、種類は「ウェブアプリ」、アクセスできるユーザーは「全員」にしてデプロイする
  4. 表示された URL の末尾に ?token=<TOKEN の値> を付けて、Reserve Care の送り先(種類は「汎用」)に登録する
  5. 「テスト送信」を押し、シートに行が増えることを確かめる
const TOKEN = "ここを推測されにくい長い文字列に書き換える";

function doPost(e) {
  if (e.parameter.token !== TOKEN) {
    return ContentService.createTextOutput("forbidden");
  }
  const data = JSON.parse(e.postData.contents);
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("予約");

  // 同じ event_id は1回だけ記録する(再送で同じものが届くため)
  const ids = sheet.getRange("B:B").getValues().flat();
  if (ids.includes(data.event_id)) {
    return ContentService.createTextOutput("duplicate");
  }

  sheet.appendRow([
    new Date(),
    data.event_id,
    data.event,
    data.booking_id,
    data.form_name,
    data.start_at,
    data.end_at,
    data.customer.name,
    data.customer.email,
    data.customer.phone,
    data.customer.memo,
    data.test === true ? "テスト" : "",
  ]);
  return ContentService.createTextOutput("ok");
}

URL に付けた文字列は、秘密の値と同じように扱ってください。漏れたときは、TOKEN を書き換えてデプロイし直し、送り先の URL も直してください。

Discord に通知する

Discord には、予約者の名前、予約の日時、フォームの名前と、管理画面へのリンクだけを送ります。メールアドレスなどは送りません。

  1. Discord のサーバーの設定 →「連携サービス」→「ウェブフック」→「新しいウェブフック」
  2. 通知を出すチャンネルを選び、「ウェブフック URL をコピー」
  3. Reserve Care の送り先に、種類「Discord」で URL を登録し、「テスト送信」を押す

Slack に通知する

Slack にも、Discord と同じ内容を送ります。

  1. Slack の API のサイトで「Create New App」→「Pick features」を選ぶ
  2. アプリの名前とワークスペースを決める。機能は「Incoming Webhooks」を選び、イベントは選ばずに進む
  3. アプリの設定の「Incoming Webhooks」を On にし、「Add New Webhook」で通知を出すチャンネルを選ぶ
  4. できた URL(https://hooks.slack.com/services/…)を、Reserve Care の送り先に種類「Slack」で登録し、「テスト送信」を押す