メインコンテンツまでスキップ

Webhook通知

PDF生成完了時に自動的にWebhook通知を受け取ることができます。これにより、ポーリング不要でリアルタイムに完了を検知し、メール送信などのワークフローを自動化できます。

概要

Webhook通知は、以下のすべてのPDF生成エンドポイントで自動的に送信されます:

  • POST /file/sync/single - 同期単一ファイル生成
  • POST /file/sync/multiple - 同期複数ファイル生成
  • POST /file/async/single - 非同期単一ファイル生成
  • POST /file/async/multiple - 非同期複数ファイル生成

Webhook URLの設定

Webhook URLを設定するには、ReportFlowのワークスペース設定画面から行います:

  1. ワークスペース設定を開く
  2. 「開発者」タブに移動
  3. 「Webhook URL」フィールドに、通知を受け取るHTTPS URLを入力
  4. 「更新」をクリック

Webhook通知ペイロード

PDF生成が完了すると、設定されたWebhook URLに以下のペイロードがPOSTされます。

ペイロード形式

{
"event": "file.completed",
"timestamp": "2026-02-15T10:30:45.123Z",
"workspaceId": "ws_abc123",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"designId": "design_123",
"version": 5,
"files": [
{
"fileId": "7f3d1a2b-4c5e-6f7a-8b9c-0d1e2f3a4b5c",
"fileName": "請求書.pdf",
"passthrough": { "pageId": "abc123" },
"share": {
"shareType": "workspace",
"url": "https://app.re-port-flow.com/file/{requestId}/{fileId}",
"passcodeEnabled": false
}
}
]
}

フィールド説明

フィールド説明
eventstring固定値: "file.completed"
timestampstringイベント発生時刻 (ISO 8601形式)
workspaceIdstringワークスペースID(参照用)
requestIdstringリクエストID(ダウンロードエンドポイントで使用)
designIdstringデザインID
versionnumberバージョン番号
filesarray生成ファイル情報の配列
files[].fileIdstringファイルID(個別ダウンロードエンドポイントで使用)
files[].fileNamestringファイル名(拡張子付き)
files[].passthroughobjectリクエスト時に指定した passthrough の値(指定時のみ)
files[].share.shareTypestring共有タイプ(workspace / invited / public
files[].share.urlstringファイル表示URL
files[].share.passcodeEnabledbooleanパスコード有効フラグ
files[].share.passcodestringサーバー生成パスコード(passcodeEnabled=true かつ生成直後のみ)

PDFのダウンロード

Webhook通知のペイロードから、以下の情報を使ってPDFをダウンロードできます:

  • requestId: ペイロードの requestId(ZIP一括ダウンロード用)
  • fileId: ペイロードの files[].fileId(個別ダウンロード用)
# ZIP一括ダウンロード
GET /v1/file/download/{requestId}

# 個別ファイルダウンロード
GET /v1/file/download/{requestId}/{fileId}

詳細はファイルダウンロードを参照してください。

実装例

Node.js (Express)

import express from 'express';
import axios from 'axios';
const app = express();

app.use(express.json());

app.post('/webhooks/pdf-completed', async (req, res) => {
const payload = req.body;

// イベント検証
if (payload.event !== 'file.completed') {
return res.status(400).json({ error: 'Unknown event' });
}

console.log(`PDF生成完了: ${payload.files.length}`);

// 各ファイルをダウンロード
for (const file of payload.files) {
const downloadUrl = `https://api.re-port-flow.com/v1/file/download/${payload.requestId}/${file.fileId}`;

try {
// PDFダウンロード
const pdfResponse = await axios.get(downloadUrl, {
headers: {
'appkey': process.env.APP_KEY
},
responseType: 'arraybuffer'
});

const pdfBuffer = Buffer.from(pdfResponse.data);

// メール送信など
await sendEmailWithAttachment({
to: extractEmailFromParams(file.params),
subject: `PDFファイル: ${file.fileName}`,
attachments: [{
filename: file.fileName,
content: pdfBuffer
}]
});

console.log(`メール送信完了: ${file.fileName}`);
} catch (error) {
console.error(`ファイルダウンロードエラー: ${file.fileName}`, error.message);
}
}

// 200 OKを返す
res.status(200).json({ received: true });
});

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

Python (Flask)

from flask import Flask, request, jsonify
import requests
import os

app = Flask(__name__)

@app.route('/webhooks/pdf-completed', methods=['POST'])
def webhook_handler():
payload = request.json

# イベント検証
if payload.get('event') != 'file.completed':
return jsonify({'error': 'Unknown event'}), 400

print(f"PDF生成完了: {len(payload['files'])}件")

# 各ファイルをダウンロード
request_id = payload['requestId']

for file_info in payload['files']:
download_url = f"https://api.re-port-flow.com/v1/file/download/{request_id}/{file_info['fileId']}"

try:
# PDFダウンロード
pdf_response = requests.get(
download_url,
headers={
'appkey': os.getenv('APP_KEY')
}
)
pdf_response.raise_for_status()

# ファイルに保存
with open(file_info['fileName'], 'wb') as f:
f.write(pdf_response.content)

print(f"ダウンロード完了: {file_info['fileName']}")

except Exception as e:
print(f"エラー: {file_info['fileName']}, {str(e)}")

# 200 OKを返す
return jsonify({'received': True}), 200

if __name__ == '__main__':
app.run(port=3000)

セキュリティベストプラクティス

1. HTTPS URLを使用

Webhook URLは必ずHTTPSを使用してください。HTTP URLは拒否されます。

2. 署名検証の実装

現在、Webhook通知にはペイロード署名がありません。なりすましを防ぐため、以下の方法で受信元を検証することを推奨します:

  • IPホワイトリスト
  • API Keyやシークレットトークンによる認証
  • 独自の署名スキーム

3. タイムアウト設定

Webhookエンドポイントは5秒以内に応答することを推奨します。重い処理(メール送信、データベース書き込みなど)は非同期ジョブキューで実行してください。

4. URLに認証情報を含めない

Webhook URLのクエリパラメータに認証トークンやシークレットを含めないでください。認証が必要な場合は、Headerで送信するか、別途管理してください。

リトライ動作

Webhookエンドポイントが以下のステータスコードを返した場合、ReportFlowは自動的にリトライします:

  • 200-299: 成功(リトライしない)
  • 400-499: クライアントエラー(リトライしない)
  • 500-599: サーバーエラー(リトライする

リトライは最大3回まで行われます。すべてのリトライが失敗しても、PDF生成処理自体は成功扱いとなります。

トラブルシューティング

通知が届かない

以下を確認してください:

  1. Webhook URLが設定されているか

    • ワークスペース設定 > 開発者タブで確認
  2. HTTPSを使用しているか

    • HTTP URLは拒否されます
  3. 公開URLを使用しているか

    • localhostやプライベートIPアドレスは拒否されます
    • テスト環境ではwebhook.siteなどのサービスを利用してください
  4. エンドポイントが200を返すか

    • エラーステータスコード(4xx/5xx)を返している場合、リトライされます
    • エンドポイントのログを確認してください

通知が届かない場合は、サポートにお問い合わせください。

次のステップ