コンテンツへスキップ
Wbiztool

製品ガイド

受信メッセージのWebhook(リスナー)

リスナーは、WhatsApp番号の1つをUniboxに接続し、受信メッセージのWebhookをお使いのサーバーに送信できます。ダッシュボードでは、リスナーは 着信トリガー ページで管理します。番号をリスナーにすると、そのチャットがUnibox受信トレイに同期され、Webhook URLを追加した場合は、Wbiztoolが新しいメッセージを1件ずつお使いのサーバーに送信します。Webhookは、CRMへの会話の記録、チームへの通知、自動返信の構築などに利用できます。

始める前に#

  • Uniboxアドオン。 料金はWhatsApp番号1つあたり月額$20または年額$200で、作成できるリスナーの数はアドオンの数量と同じです。ダッシュボード内の請求・プラン利用可能なアドオン から購入してください。アドオンがなくても 着信トリガー ページは開きますが、Add New Listener(新しいリスナーを追加)をクリックすると Unibox Add-on Required(Uniboxアドオンが必要です)と表示され、Subscribe to Unibox Add-on(Uniboxアドオンに登録)ボタンが表示されます。
  • WhatsApp設定接続済みのWhatsApp番号。追加できるのは、接続済みでまだリスナーになっていない番号のみです。
  • ワークスペースのオーナーまたは編集者である必要があります。
  • Webhookを使う場合:JSONボディの POST リクエストを受け付ける、100文字以内 の公開URL(https を使用してください)。

リスナーを追加する#

  1. 着信トリガーを開く

    サイドバーで Unibox を開いて 着信トリガー をクリックするか、着信トリガーにアクセスします。

  2. 新しいリスナーを開始する

    新しいリスナーを追加 カードをクリックします。

  3. 番号を選ぶ

    WhatsApp番号を選択 で番号を選びます。一覧に No available WhatsApp numbers(利用可能なWhatsApp番号がありません)と表示される場合は、接続済みの番号がすべてリスナーになっているか、接続済みの番号がありません。

  4. Webhookを追加する(任意)

    Webhook URL(任意) を入力します。URLを入力すると Webhook Events(Webhookイベント)が表示されるので、Incoming Messages(受信メッセージ)、Outgoing Messages(送信メッセージ)、または両方にチェックを入れたままにします。URLは後から追加・変更できます。

  5. 保存する

    リスナーを追加 をクリックします。リスナーが Active(有効)ステータスのカードとして表示されます。URLを入力した場合は、そのURL用のWebhookシークレットが作成されます。

リスナーを管理する#

各カードには、番号、ステータス、Webhook URL:(または 未設定)、最終アクティビティ:(番号のメッセージが最後に確認された日時、または なし)、Webhookシークレット:(目のアイコンのボタンをクリックするまで非表示)が表示されます。

カードの メニューを開くと、次の操作ができます。

アクション動作
編集Webhook URL、Webhookイベント、シークレットを変更します。番号は変更できません。
無効にする / 有効にする無効にするとリスナーが Inactive(無効)になり、番号の受信トレイへの同期が止まり、Webhookも送信されなくなります。有効にすると再び Active になります。
削除確認後にリスナーを削除します。すでに受信トレイにある会話は残ります。後で同じ番号を再度追加すると、リスナーが復元されます。再追加時にWebhook URLを入力すると、以前のWebhookシークレットがあれば、新しいシークレットは作成されずにそれが引き続き使われます。

リスナーのステータス#

ステータス意味
Active(有効)番号が接続されている間、メッセージが同期され、Webhookが送信されます。
Pending(保留中)Zapierなどでリスナーが作成されたときに、番号が接続されていませんでした。番号が接続されたら 有効にする をクリックしてください。
Inactive(無効)無効化されています。何も同期されず、Webhookも送信されません。

統計#

カード表示内容
アクティブリスナー無効化されたものを含む、ページ上のすべてのリスナー。
利用可能番号接続済みで、まだリスナーになっていない番号。リスナーを削除した番号もここでは使用済みとして数えられるため、実際に追加できる数より少なく表示されることがあります。
総制限Uniboxアドオンで作成できるリスナーの数。
今日のメッセージまだ集計されていません。常に 0 と表示されます。

Webhook URLまたはイベントを変更する#

  1. リスナーを開く

    カードの をクリックし、編集 をクリックします。

  2. 設定を更新する

    Webhook URL (Optional)Webhook Events を変更します。この番号のWebhookを止めるには、URLを空にします。シークレットも削除され、URLを再度追加すると新しいシークレットが作成されます。

  3. 保存する

    Update Listener(リスナーを更新)をクリックします。

シークレットを再生成する#

Edit Listener(リスナーを編集)で、Webhook Secret(Webhookシークレット)の隣にある更新ボタンをクリックして確認します。新しいシークレットはすぐに保存され、その後 Update Listener をクリックせずにダイアログを閉じても保存されたままです。以降のリクエストは新しいシークレットで署名されます。サーバーの設定をすぐに新しいシークレットに更新してください。

Webhookの配信の仕組み#

Wbiztoolは、番号の同期時に見つかった新しいメッセージごとに、URLへ POST リクエストを1件送信します。同期は、番号が接続されていてメッセージ送信中でない間、数分ごとに行われます。

  • イベント: 相手からご自身の番号に届いたメッセージには message_received、その番号から送信されたメッセージ(スマートフォン、キャンペーン、APIから)には message_sent が使われます。送信されるのは、Webhook Events でチェックを入れたイベントのみです。
  • Unibox受信トレイからの返信 は、同期の実行時にはすでに受信トレイにあるため、通常は message_sent をトリガーしません。
  • レスポンス: 8秒以内にHTTP 200 を返してください。それ以外のレスポンスやタイムアウトは、配信失敗として扱われます。
  • 再試行なし: 各メッセージは1回だけ送信されます。サーバーがダウンしていた場合、そのWebhookは失われます。
  • 順序: リクエストは個別に送信されるため、順不同で届くことがあります。順序が重要な場合は message.timestamp で並べ替えてください。

ヘッダー#

ヘッダー
Content-Typeapplication/json
X-Wbiztool-Eventmessage_received または message_sent
X-Wbiztool-TimestampWebhookが送信された日時(ISO 8601、UTC)。ボディの timestamp と同じです。
X-Wbiztool-Webhook-IdリスナーのID。ボディの webhook_id と同じです。
X-Wbiztool-Signaturesha256= の後に署名が続きます。リスナーにシークレットがある場合に送信され、URLが設定されていれば常にシークレットがあります。

ペイロード#

Webhookボディの例
{
  "event": "message_received",
  "timestamp": "2026-09-16T10:31:12.482913+00:00",
  "webhook_id": 42,
  "whatsapp_client_id": "678",
  "whatsapp_phone": "919812345678",
  "message": {
    "id": "[email protected]_3EB0C1A2B3D4E5F60718",
    "type": "chat",
    "content": "Hi, is my order #4821 out for delivery?",
    "from": "919876543210",
    "from_name": "Aman",
    "to": "919812345678",
    "timestamp": "2026-09-16T10:29:58+00:00",
    "whatsapp_timestamp": 1789554598,
    "direction": "incoming",
    "status": "pending",
    "is_forwarded": false,
    "forwarding_score": 0
  },
  "contact": {
    "whatsapp_id": "[email protected]",
    "phone": "919876543210",
    "name": "Aman",
    "is_group": false,
    "is_business": false
  },
  "organisation": {
    "id": "10314",
    "name": "Acme Stores"
  }
}

上記の番号、ID、名前は例です。

トップレベルのフィールド#

フィールド説明
eventstringmessage_received または message_sent
timestampstringWebhookが送信された日時(ISO 8601、UTC)。
webhook_idintegerリスナーのID。
whatsapp_client_idstringWhatsApp設定に表示される、WhatsApp番号のID。
whatsapp_phonestringご自身のWhatsApp番号。
messageobjectメッセージ。下記をご覧ください。
contactobject会話の相手の個人またはグループ。下記をご覧ください。
organisationobjectワークスペースの id(string)と name
groupobjectグループチャットの場合のみ:name(グループ名)。

message のフィールド#

フィールド説明
idstringWhatsAppにおけるメッセージのID。重複を無視するために使用します。
typestringテキストの場合は chat。それ以外はWhatsAppの種類で、imagevideoaudioptt(ボイスメッセージ)、documentstickerlocation などです。
contentstringchat メッセージの場合はテキスト。メディアの場合は代わりにラベルが入ります:📸 Image🎥 Video🎵 Audio🎤 Voice Message😊 StickerDocument: の後にドキュメントのテキスト(テキストがない場合は Document)、それ以外は Location のように先頭を大文字にした種類の名前。キャプションは含まれません。
fromstring送受信のどちらでも、常に連絡先の番号(またはグループのID)です。
from_namestring連絡先またはグループの名前。空の場合もあります。
tostring送受信のどちらでも、常にご自身のWhatsApp番号 です。
timestampstringWhatsAppでメッセージが送信された日時(ISO 8601、UTC)。
whatsapp_timestampinteger同じ日時を秒単位のUnixタイムスタンプで表したもの。
directionstringincoming または outgoing。方向の判定には、fromto ではなくこのフィールドを使用してください。
statusstring現在は常に pending です。配信状況や既読状況の判定には使わないでください。
is_forwardedbooleanメッセージが転送されたものかどうか。
forwarding_scoreinteger転送された回数。
mediaobject詳細が取得できる場合のメディアメッセージ:filenamemimetypesize(バイト単位)。ファイル自体は含まれません。
quoted_message_idstringメッセージが別のメッセージへの返信である場合のみ。

contact のフィールド#

フィールド説明
whatsapp_idstringWhatsApp ID。個人の場合は [email protected]、グループの場合は …@g.us のような形式です。
phonestring+ なしの番号。グループの場合はグループのID。
namestringWbiztoolが保持している連絡先の名前、またはグループ名。空の場合もあります。
is_groupbooleanグループチャットの場合は true
is_businessbooleanWhatsApp Businessアカウントであることがわかっている場合は true

署名を検証する#

各リクエストは、リスナーのシークレットを使ってHMAC-SHA256で署名されます。署名は 受信したままの生のリクエストボディ に対して計算され、sha256= と小文字の16進ダイジェストをつなげた値として X-Wbiztool-Signature で送信されます。

署名は必ず、JSONをパースする前の生のバイト列から計算してください。ボディをパースして再エンコードすると内容が変わり(たとえば、英語以外の文字や絵文字は \uXXXX としてエスケープされた状態で届きます)、署名が一致しなくなります。

// Express: keep the raw body for this route
import crypto from "node:crypto";
import express from "express";

const app = express();
const SECRET = process.env.WBIZTOOL_WEBHOOK_SECRET;

app.post("/wbiztool/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");
  const received = req.get("X-Wbiztool-Signature") || "";

  const valid =
    received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
  if (!valid) return res.status(401).send("Invalid signature");

  const data = JSON.parse(req.body.toString("utf8"));
  if (data.event === "message_received") {
    console.log(`New message from ${data.contact.phone}: ${data.message.content}`);
  }
  res.sendStatus(200); // reply quickly; do slow work in the background
});

app.listen(3000);

署名はタイムスタンプのヘッダーを対象にしていないため、リクエストのリプレイ(再送)攻撃は防げません。これが問題になる場合は、処理済みの message.id を保存し、重複したものを無視してください。

トラブルシューティング#

メッセージまたは問題対処方法
Add New Listener(新しいリスナーを追加)をクリックすると Unibox Add-on Required(Uniboxアドオンが必要です)と表示されるワークスペースにUniboxアドオンがありません。ダッシュボード内の請求・プラン利用可能なアドオン から購入してください。
You have reached your unibox numbers limit不要になったリスナーを削除するか、アドオンの数量を増やしてください。
No available WhatsApp numbers別の番号を接続してください。または、その番号はすでにリスナーになっています。
This WhatsApp number is already a listener代わりに既存のカードを編集してください。
Invalid WhatsApp client番号が切断されています。WhatsApp設定で再接続し、ページを再読み込みしてください。
保存時に value too long を含むエラーが表示されるWebhook URLが100文字を超えています。より短いURLを使用してください。
Webhookが届かないリスナーが Active であること、番号が接続されていること、イベントの種類にチェックが入っていること、URLが有効な証明書を持つ公開の https URLであることを確認してください。メッセージは次回の同期(数分後)の後にのみ送信されます。
一部のWebhookが届かないサーバーが 200 以外を返したか、8秒以上かかったか、到達できませんでした。失敗した配信は再試行されません。
署名が一致しない再エンコードしたJSONではなく生のボディと、現在のシークレットを使用してください。シークレットを再生成するか、Zapierを接続すると、シークレットは置き換えられます。
最終アクティビティ:なし のまま番号がまだ確認されていません。番号が接続されていて、メッセージ送信中でない必要があります。

関連情報#