Webhookイベントリファレンス

すべてのZenFlip Webhookイベントタイプの詳細なペイロードスキーマとJSON例。リクエストヘッダーとNode.js署名検証の例を含みます。

On this page

Webhookイベントリファレンス

このドキュメントでは、ZenFlipがサポートする各Webhookイベントタイプの完全なペイロードスキーマとJSON例を提供します。すべてのペイロードは同じトップレベル構造に従います。

共通エンベロープ

すべてのWebhookペイロードはこの構造を共有します:

`json { "id": "wh_del_{uuid}", "event": "{event_type}", "createdAt": "ISO 8601 timestamp", "organizationId": "{org_uuid}", "data": { } } `

リクエストヘッダー

すべてのWebhook HTTP POSTリクエストには以下のヘッダーが含まれます:

ヘッダー

値の例

Content-Type

application/json

User-Agent

ZenFlip-Webhooks/1.0

X-ZenFlip-Event

publication.created

X-ZenFlip-Delivery-Id

wh_del_550e8400-e29b-41d4-a716-446655440000

X-ZenFlip-Signature

a3f2b8c91d...(HMAC-SHA256の16進ダイジェスト)


publication.created

組織で新しいパブリケーションが作成されたときに発火します。

ペイロードスキーマ

フィールド

説明

data.publicationId

string

新しいパブリケーションのUUID

data.title

string

パブリケーションタイトル

data.slug

string

URLフレンドリーなスラッグ

data.status

string

初期ステータス(常にdraft

data.createdBy

string

作成したユーザーのUUID

ペイロード例

`json { "id": "wh_del_a1b2c3d4-0001-0001-0001-000000000001", "event": "publication.created", "createdAt": "2026-02-20T12:00:00.000Z", "organizationId": "660e8400-e29b-41d4-a716-446655440000", "data": { "publicationId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "title": "Q1 Sales Report", "slug": "q1-sales-report", "status": "draft", "createdBy": "550e8400-e29b-41d4-a716-446655440000" } } `


publication.converted

PDF変換ジョブが完了したときに発火します(成功・エラーを問わず)。

ペイロードスキーマ

フィールド

説明

data.publicationId

string

パブリケーションのUUID

data.title

string

パブリケーションタイトル

data.versionId

string

変換されたバージョンのUUID

data.versionNumber

integer

連番のバージョン番号

data.status

string

変換結果:readyまたはfailed

data.pageCount

integer

生成されたページ数(失敗時は0)

data.conversionError

string

エラーメッセージ(成功時はnull)

data.convertedAt

string

変換完了のISO 8601タイムスタンプ

ペイロード例(成功)

`json { "id": "wh_del_a1b2c3d4-0002-0002-0002-000000000002", "event": "publication.converted", "createdAt": "2026-02-20T14:05:00.000Z", "organizationId": "660e8400-e29b-41d4-a716-446655440000", "data": { "publicationId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "title": "Q1 Sales Report", "versionId": "c3d4e5f6-a7b8-9012-cdef-123456789012", "versionNumber": 1, "status": "ready", "pageCount": 24, "conversionError": null, "convertedAt": "2026-02-20T14:05:00.000Z" } } `

ペイロード例(失敗)

`json { "id": "wh_del_a1b2c3d4-0002-0002-0002-000000000003", "event": "publication.converted", "createdAt": "2026-02-20T14:06:00.000Z", "organizationId": "660e8400-e29b-41d4-a716-446655440000", "data": { "publicationId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "title": "Q1 Sales Report", "versionId": "d4e5f6a7-b8c9-0123-def0-234567890123", "versionNumber": 2, "status": "failed", "pageCount": 0, "conversionError": "PDF file is password-protected and cannot be processed", "convertedAt": "2026-02-20T14:06:00.000Z" } } `


publication.deleted

パブリケーションが完全に削除されたときに発火します。

ペイロードスキーマ

フィールド

説明

data.publicationId

string

削除されたパブリケーションのUUID

data.title

string

削除時のタイトル

data.slug

string

削除時のスラッグ

data.deletedBy

string

削除したユーザーのUUID

ペイロード例

`json { "id": "wh_del_a1b2c3d4-0003-0003-0003-000000000004", "event": "publication.deleted", "createdAt": "2026-02-20T16:00:00.000Z", "organizationId": "660e8400-e29b-41d4-a716-446655440000", "data": { "publicationId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "title": "Q1 Sales Report", "slug": "q1-sales-report", "deletedBy": "550e8400-e29b-41d4-a716-446655440000" } } `


lead.captured

閲覧者がパブリケーション内のリードキャプチャフォームを送信したときに発火します。

ペイロードスキーマ

フィールド

説明

data.leadId

string

キャプチャされたリードのUUID

data.publicationId

string

パブリケーションのUUID

data.email

string

送信されたメールアドレス

data.name

string

氏名(未収集の場合はnull)

data.company

string

会社名(未収集の場合はnull)

data.phone

string

電話番号(未収集の場合はnull)

data.customFields

object

カスタムフォームフィールドのキーバリューペア

data.sourcePage

integer

フォームがトリガーされたページ

data.triggerType

string

トリガー方法:pageexittimerscroll

data.capturedAt

string

送信のISO 8601タイムスタンプ

ペイロード例

`json { "id": "wh_del_a1b2c3d4-0004-0004-0004-000000000005", "event": "lead.captured", "createdAt": "2026-02-20T15:30:00.000Z", "organizationId": "660e8400-e29b-41d4-a716-446655440000", "data": { "leadId": "d4e5f6a7-b8c9-0123-def0-234567890123", "publicationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "email": "jane@example.com", "name": "Jane Doe", "company": "Acme Inc.", "phone": "+1-555-0100", "customFields": { "jobTitle": "Product Manager", "department": "Marketing" }, "sourcePage": 3, "triggerType": "page", "capturedAt": "2026-02-20T15:30:00.000Z" } } `


team.member_joined

チームメンバーが招待を承認し、組織に参加したときに発火します。

ペイロードスキーマ

フィールド

説明

data.userId

string

新しいチームメンバーのUUID

data.email

string

メンバーのメールアドレス

data.name

string

表示名

data.role

string

割り当てられたロール:admineditorviewer

data.invitedBy

string

招待を送信したユーザーのUUID

data.joinedAt

string

参加時のISO 8601タイムスタンプ

ペイロード例

`json { "id": "wh_del_a1b2c3d4-0005-0005-0005-000000000006", "event": "team.member_joined", "createdAt": "2026-02-20T17:00:00.000Z", "organizationId": "660e8400-e29b-41d4-a716-446655440000", "data": { "userId": "880e8400-e29b-41d4-a716-446655440003", "email": "neweditor@example.com", "name": "Jordan Lee", "role": "editor", "invitedBy": "550e8400-e29b-41d4-a716-446655440000", "joinedAt": "2026-02-20T17:00:00.000Z" } } `


export.completed

HTMLまたはSCORMエクスポートジョブの処理が完了したときに発火します。

ペイロードスキーマ

フィールド

説明

data.exportJobId

string

エクスポートジョブのUUID

data.publicationId

string

エクスポートされたパブリケーションのUUID

data.format

string

エクスポート形式:htmlscorm_12scorm_2004

data.status

string

結果:completedまたはfailed

data.downloadUrl

string

エクスポートをダウンロードするための署名付きURL(失敗時はnull、24時間で期限切れ)

data.fileSizeBytes

integer

エクスポートファイルのバイト数(失敗時は0)

data.error

string

エラーメッセージ(成功時はnull)

data.completedAt

string

完了のISO 8601タイムスタンプ

ペイロード例

`json { "id": "wh_del_a1b2c3d4-0006-0006-0006-000000000007", "event": "export.completed", "createdAt": "2026-02-20T18:00:00.000Z", "organizationId": "660e8400-e29b-41d4-a716-446655440000", "data": { "exportJobId": "f6a7b8c9-d0e1-2345-f012-456789012345", "publicationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "format": "scorm_12", "status": "completed", "downloadUrl": "https://cdn.zenflip.io/exports/f6a7b8c9...?token=abc123&expires=1740182400", "fileSizeBytes": 15728640, "error": null, "completedAt": "2026-02-20T18:00:00.000Z" } } `


署名検証(完全な例)

以下はZenFlip Webhookを受信・検証する完全なNode.js Expressサーバーの例です:

`javascript const express = require("express"); const crypto = require("crypto");

const app = express(); const WEBHOOK_SECRET = process.env.ZENFLIP_WEBHOOK_SECRET;

// 重要:署名検証のために生のボディを取得するにはexpress.raw()を使用 app.post( "/webhooks/zenflip", express.raw({ type: "application/json" }), (req, res) => { const signature = req.headers["x-zenflip-signature"]; const eventType = req.headers["x-zenflip-event"]; const deliveryId = req.headers["x-zenflip-delivery-id"];

// ステップ1:署名の検証 const expected = crypto .createHmac("sha256", WEBHOOK_SECRET) .update(req.body, "utf8") .digest("hex");

const isValid = crypto.timingSafeEqual( Buffer.from(signature, "hex"), Buffer.from(expected, "hex") );

if (!isValid) { console.error("Webhook signature verification failed:", deliveryId); return res.status(401).json({ error: "Invalid signature" }); }

// ステップ2:ペイロードのパース const event = JSON.parse(req.body.toString());

// ステップ3:即座に確認応答 res.status(200).json({ received: true });

// ステップ4:イベントを非同期で処理 handleEvent(event).catch((err) => { console.error("Error processing webhook:", err); }); } );

async function handleEvent(event) { switch (event.event) { case "publication.created": console.log("New publication:", event.data.title); break;

case "publication.converted": if (event.data.status === "ready") { console.log( "Conversion complete:", event.data.title, "-", event.data.pageCount, "pages" ); } else { console.error("Conversion failed:", event.data.conversionError); } break;

case "lead.captured": console.log("New lead:", event.data.email, "from page", event.data.sourcePage); // CRMへの転送、通知の送信など break;

case "team.member_joined": console.log("New team member:", event.data.name, "as", event.data.role); break;

case "export.completed": if (event.data.status === "completed") { console.log("Export ready:", event.data.downloadUrl); } break;

default: console.log("Unhandled event type:", event.event); } }

app.listen(3000, () => { console.log("Webhook server listening on port 3000"); }); `

ベストプラクティス

  1. 必ず署名を検証してください。 X-ZenFlip-Signatureヘッダーを検証せずにWebhookペイロードを信頼しないでください。

  2. 素早く応答してください。 200ステータスを即座に返し、イベントは非同期で処理してください。Webhook配信は10秒でタイムアウトします。

  3. 配信IDで重複を排除してください。 処理済みのid値を保存し、重複をスキップしてください。リトライにより同じイベントが複数回配信される場合があります。

  4. HTTPSエンドポイントを使用してください。 ZenFlipはHTTPSを使用するURLにのみWebhookを送信します。

  5. 障害を適切に処理してください。 下流のサービスが利用できない場合は、エラーステータスを返すのではなく、後で処理するためにイベントをキューに入れてください。

Next →
Webhook概要