Webhook入力検証で200または422を返す
Webhook入力検証では、Universal Webhook、JSON Operations(JQ)、Verification Router、2つのWebhook Responseノードを使ってJSONイベントを検証します。本番実行では、正規化した入力を返す200レスポンス、または理由を含む422レスポンスが返されました。このテンプレートでは、AIモデル、Google Sheetsノード、サードパーティーの有料APIを使用しません。
ステータス:2026年10月9日にAI Flowi Workflow 1.9.2で本番テスト済み(28件中28件に合格)
執筆:Ai Flowi · 公開日 · 更新日
作業内容
4つの必須テキストフィールドを確認し、前後の空白を除去して、メールアドレスのASCII英字を小文字に変換します。返す入力値はこの4つのフィールドのみです。検証に失敗した場合は、固定の理由を返します。200レスポンスが示すのは検証の成功だけであり、データベースへの書き込みやその他の処理の成功を示すものではありません。
対象者
他の処理に接続する前に、認証付きWebhookの入出力仕様をテストする開発者や自動化の構築担当者向けです。送信側はPlatform API Keyを送信できる必要があります。このテンプレートは、プロバイダーの署名を検証するものではありません。
入力例
{
"event_id": " evt-demo-001 ",
"name": " Demo Sender ",
"email": " DEMO@EXAMPLE.COM ",
"request": " Validate this event "
}
設定
- AI Flowi Workflowで独立したフローを作成します。Universal Webhook、JSON Operationsノード1つ、Verification Router、Webhook Responseノード2つを追加します。
- Universal Webhookを
POSTに、認証をPlatform API Keyに、POST Response ModeをFrom Flowに設定します。保存済みの本文、フォームフィールド、ファイル、レスポンスヘッダーは空にしておきます。 - JSON Operationsで
JQ Expressionを選択し、以下の検証クエリを貼り付けます。Path Selectionの値はすべて消去します。 - 次のセクションに従ってポートを接続します。レスポンスコードを
200 OKと422 Unprocessable Entityに設定します。どちらもapplication/jsonを使用し、レスポンスヘッダーとResponse Definitionを空にします。 - 自分のフローから本番Webhook URLをコピーします。合成したテストデータを
x-api-keyヘッダーとContent-Type: application/jsonを付けて送信します。実行には本番エンドポイントを使用してください。リクエストの取得のみを行うテストエンドポイントでは、グラフの動作を検証できません。
ノードの接続とフィールドのマッピング
| 接続元 | 出力 → 接続先の入力 | 目的 |
|---|---|---|
| Universal Webhook → JSON Operations | request_data → data | リクエストエンベロープのbodyを検証します。 |
| JSON Operations → Verification Router | data_output → verification_result | 最上位の真偽値verifiedに基づいて分岐します。 |
| Verification Router → 200 Webhook Response | verified → body_data | 検証結果全体を変更せずに返します。 |
| Verification Router → 422 Webhook Response | rejected → body_data | 拒否した値を返さず、固定の理由を返します。 |
| 入力フィールド | ルール | 正規化後の出力 |
|---|---|---|
body.event_id | テキスト、1~100文字 | data.event_id:前後の空白を除去し、大文字・小文字は保持 |
body.name | テキスト、1~120文字 | data.name:前後の空白を除去 |
body.email | テキスト、1~254文字。基本的なメールアドレス形式 | data.email:前後の空白を除去し、ASCII英字を小文字に変換 |
body.request | テキスト、1~2,000文字 | data.request:前後の空白を除去 |
検証用のJQ式
def trim: gsub("^\\s+|\\s+$"; "");
def text_ok($v; $max):
if ($v|type) != "string" then false
else ($v|trim|length) as $n | ($n > 0 and $n <= $max) end;
.body as $b
| if ($b|type) != "object" then
{verified: false, error: "Validation failed", reasons: ["body must be a JSON object"]}
else [
(if text_ok($b.event_id; 100) then empty else "event_id must be text of 1 to 100 characters after trimming" end),
(if text_ok($b.name; 120) then empty else "name must be text of 1 to 120 characters after trimming" end),
(if text_ok($b.email; 254) then
if ($b.email|trim|test("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$")) then empty else "email must have a basic address format" end
else "email must be text of 1 to 254 characters after trimming" end),
(if text_ok($b.request; 2000) then empty else "request must be text of 1 to 2000 characters after trimming" end)
] as $reasons
| if ($reasons|length) > 0 then {verified: false, error: "Validation failed", reasons: $reasons}
else {verified: true, data: {event_id: ($b.event_id|trim), name: ($b.name|trim),
email: ($b.email|trim|ascii_downcase), request: ($b.request|trim)}} end
end機密情報を除いたリクエストとレスポンスの例
リクエストコマンドの説明用の例です。URLを置き換え、キーは非公開の状態で指定してください。以下の例は意図する入出力仕様を示すものであり、記録されたテストレスポンスではありません。
curl -X POST "https://workflow.aiflowi.com/api/v1/webhook/YOUR_FLOW_ID" \
-H "Content-Type: application/json" \
-H "x-api-key: $FLOWI_API_KEY" \
--data '{"event_id":"evt-demo-001","name":"Demo Sender","email":"demo@example.com","request":"Validate this event"}'
期待されるHTTP 200:
{"verified":true,"data":{"event_id":"evt-demo-001","name":"Demo Sender","email":"demo@example.com","request":"Validate this event"}}
期待されるHTTP 422(emailを省略した場合):
{"verified":false,"error":"Validation failed","reasons":["email must be text of 1 to 254 characters after trimming"]}
検証と失敗時の動作
本文はJSONオブジェクトのみ受け付けます。フィールドが未指定、null、テキスト以外、空、空白のみ、または上限超過の場合は、event_id、name、email、requestの順に理由が返されます。基本的なメールアドレスのチェックでは、@とその後のドットが必要で、空白は許可されません。未知のフィールドは破棄されます。意図するレスポンスには、ヘッダー、生のリクエストデータ、拒否した値は含まれません。
Platform API Keyが未指定または無効の場合は403が返されました。この本番実行では、不正なJSONに対して、本文がオブジェクトでなければならないという検証理由を含む422が返されました。パーサーのバージョンが異なると、グラフ実行前に不正なJSONを400で拒否する場合があります。グラフは、自身の実行前に生成されたレスポンスを上書きできません。
有効なリクエストを繰り返し送信した場合、同じ正規化済みの入力が返される想定です。イベントIDは繰り返しの実行を防ぎません。実行時例外、アカウントのアクセス障害、タイムアウトでは、プラットフォームの別のエラーが返される場合があります。ルーターはこれらを捕捉しません。
テスト結果
2026年10月9日 MYTの本番リクエストでは、全28件に合格しました。各レスポンスは、期待されるJSON本文とJSONのコンテンツタイプに一致しました。情報を伏せる前の記録では、秘密の値、想定外の入力値の返却、内部エラーの漏えいは確認されませんでした。一時的なテスト用認証は削除済みです。この検証フローには永続化ノードがないため、シートの行数は対象外です。
| テストケース | 期待されるHTTP | 実際のHTTP | 判定 |
|---|---|---|---|
| T01 有効な入力 | 200 | 200 | 合格 |
| T02 前後の空白除去とメールアドレスの小文字化 | 200 | 200 | 合格 |
| T03 email未指定 | 422 | 422 | 合格 |
| T04 nameが数値 | 422 | 422 | 合格 |
| T05 不正なJSON | 422 | 422 | 合格 |
| T06 キー未指定 | 403 | 403 | 合格 |
| T07 無効なキー | 403 | 403 | 合格 |
| T08 不正なメールアドレス形式 | 422 | 422 | 合格 |
| T09 nameが空白のみ | 422 | 422 | 合格 |
| T10 event_idがnull | 422 | 422 | 合格 |
| T11 requestがネストされた値 | 422 | 422 | 合格 |
| T12 全フィールド未指定 | 422 | 422 | 合格 |
| T13 bodyが配列 | 422 | 422 | 合格 |
| T14 bodyがnull | 422 | 422 | 合格 |
| T15 bodyがスカラー値 | 422 | 422 | 合格 |
| T16 未知のフィールドを破棄 | 200 | 200 | 合格 |
| T17 繰り返し配信 | 200 | 200 | 合格 |
| T18 nameにUnicode文字 | 200 | 200 | 合格 |
| T19 email内の空白を拒否 | 422 | 422 | 合格 |
| T20 空の本文 | 422 | 422 | 合格 |
| T21 event_idが上限値 | 200 | 200 | 合格 |
| T22 event_idが上限超過 | 422 | 422 | 合格 |
| T21 nameが上限値 | 200 | 200 | 合格 |
| T22 nameが上限超過 | 422 | 422 | 合格 |
| T21 emailが上限値 | 200 | 200 | 合格 |
| T22 emailが上限超過 | 422 | 422 | 合格 |
| T21 requestが上限値 | 200 | 200 | 合格 |
| T22 requestが上限超過 | 422 | 422 | 合格 |
テストしたプラットフォームのバージョン:1.9.2。本番テスト日:2026年10月9日 MYT。実測したノード実行数と課金トークン数:未測定。インポートしたコピーの検証:この検証記録には記載なし。
ダウンロード
このテンプレートには、インポート可能なワークフローのダウンロードは用意されていません。検証記録では本番リクエストの動作を確認できますが、インポート後の再テストは記録されていません。上記の設定手順とJQ式を使用してください。ワークフローファイルを共有する前に、機密情報を除いたエクスポートをインポートし、動作を検証してください。
必要な設定
- 利用権限と十分なFlowi TokensがあるAI Flowi Workflowアカウント。
- 自分の本番Webhook URLと、非公開のPlatform API Key。
- 上記の4つのフィールドと、指定どおりのポート接続。
- このワークフローには、Google接続、スプレッドシート、シートタブ、AIモデルのキー、サードパーティーAPIの契約は不要です。
テストしたバージョンと日付
AI Flowi Workflow 1.9.2で、2026年10月9日 MYTに本番テスト済みです。テンプレートのドキュメント更新日:2026年10月9日。
使用量と費用の前提
ノードの実行1回につき1 Flowi Tokenを消費します。プラン:Goは年払いで月額USD8から(月払いUSD10)、全5プランでPro 500まで。全プランは料金ページに掲載しています。
設計上、有効な入力の経路とスキーマ検証で拒否される経路では、それぞれUniversal Webhook、JSON Operations、Verification Router、Webhook Responseの1つを実行し、リクエスト1件あたり4回のノード実行となります。保存されるノードは5つですが、実行されるレスポンス分岐は1つのみの想定です。グラフ実行前の認証失敗とパーサーの失敗では、ノード実行数は0回の想定です。これらは設計上の回数であり、課金の実測値ではありません。実際に確認された不正なJSONへのレスポンスは、本文がオブジェクトではない場合の422拒否経路を使用したため、この設計では4回の実行として数えます。この28件のテストでは、ルーティングされた26件のリクエスト × 4 = 推定104 Flowi Tokensです。認証で拒否された2件は、ノード実行数0回と仮定しています。
| 月間リクエスト数 | 設計上のノード実行数 / Flowi Tokens | Plusの月間10,000トークンとの比較 |
|---|---|---|
| 100 | 400 | 枠内 |
| 1,000 | 4,000 | 枠内 |
| 10,000 | 40,000 | Plusの月間付与枠を30,000 Flowi Tokens超過。追加購入はPlusが3回でUSD90(サブスクリプション料金は別)。Pro 100の50,000トークンなら枠内です |
ルーティングされる再試行1回ごとに、設計上のノード実行がさらに4回増えます。モデルやサードパーティーAPIの呼び出しは設定されていません。サードパーティーのAPI・モデル使用料はプランに含まれません。枠を超えた場合の単価や総費用は仮定していません。
制限事項
- 不正なJSONに422を返すケースを含め、本番の全28件に合格しました。インポートの検証とノードの課金は記録されていません。パーサーの動作はバージョンによって異なる場合があります。
- メールアドレスのチェックは基本的な形式確認です。そのメールアドレスの所有、配信可否、メール規格への完全な準拠を確認するものではありません。
- 書き込み、永続的な受領記録、重複排除、プロバイダーの署名検証、業務固有の認可は行いません。
- 前後の空白除去はJQの正規表現における空白の定義に従います。長さはコードポイント数で数え、バイト数や見た目の文字単位である書記素クラスター数では数えません。
- フィールドの上限は、受信するHTTP本文のサイズを制限しません。リクエストサイズ、レート制限、保持期間は別途設定してください。プラットフォームは、取得したリクエストや実行ログを保持する場合があります。テストには合成データを使用し、機密性の高い値を送る前に保持方針を確認してください。
次の手順
自分で設定したフローでこれらのケースを再実行し、機密情報を除いたエクスポートをインポートした後に検証してください。イベントの入出力仕様に合わせてフィールドのルールを調整し、本番の送信元を接続する前にレスポンスを確認します。
関連情報:コンポーネントカタログ、Universal Webhook、Webhook Response、別途テスト済みのWebhookからGoogle Sheetsへ送信するチュートリアル。
設定したバージョンのノード実行数、再試行、外部APIの使用量と併せて、AI Flowi Workflowの料金を確認してください。