replicate-webhooks について
ReplicateのWebhookハンドラーを構築する開発者向けのスキルです。予測のライフサイクルイベント、署名検証、ペイロードを扱い、各種フレームワークの実装例を案内します。
主な機能
- 01予測ステータスイベントの処理
- 02Webhook署名の検証
- 03イベントペイロード構造の確認
- 04Express、Next.js、FastAPIの実装リファレンス
- 05ローカルトンネルでのテスト
活用シーン
- 01予測完了または失敗の通知処理
- 02予測ステータスに応じた画面更新や出力処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ hookdeck/ webhook-skills --skill replicate-webhooksインストール後、Claude Code で/replicate-webhooksを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
TODO.mdexamples/express/.env.examplejest.config.jspackage.jsonREADME.mdexamples/express/src/index.jsexamples/express/test/webhook.test.jsexamples/fastapi/.env.examplemain.pyREADME.mdrequirements.txttest_webhook.pyexamples/nextjs/.env.examplepackage.jsonREADME.mdvitest.config.tsexamples/nextjs/app/webhooks/replicate/route.tsexamples/nextjs/test/webhook.test.tsreferences/overview.mdsetup.mdverification.md詳細
Replicate Webhook
このスキルを使用する場面
- Replicate の webhook ハンドラーを設定する
- 署名検証の失敗をデバッグする
- Replicate のイベントタイプとペイロードを理解する
- 予測のライフサイクルイベント(開始、出力、ログ、完了)を処理する
必須コード(必ず使用)
Express Webhook ハンドラー
const express = require('express');
const crypto = require('crypto');
const app = express();
// CRITICAL: Use express.raw() for webhook endpoint - Replicate needs raw body
app.post('/webhooks/replicate',
express.raw({ type: 'application/json' }),
async (req, res) => {
// Get webhook headers
const webhookId = req.headers['webhook-id'];
const webhookTimestamp = req.headers['webhook-timestamp'];
const webhookSignature = req.headers['webhook-signature'];
// Verify we have required headers
if (!webhookId || !webhookTimestamp || !webhookSignature) {
return res.status(400).json({ error: 'Missing required webhook headers' });
}
// Manual signature verification (recommended approach)
const secret = process.env.REPLICATE_WEBHOOK_SECRET; // whsec_xxxxx from Replicate
const signedContent = `${webhookId}.${webhookTimestamp}.${req.body}`;
try {
// Extract base64 secret after 'whsec_' prefix
const secretBytes = Buffer.from(secret.split('_')[1], 'base64');
const expectedSignature = crypto
.createHmac('sha256', secretBytes)
.update(signedContent)
.digest('base64');
// Replicate can send multiple signatures, check each one
const signatures = webhookSignature.split(' ').map(sig => {
const parts = sig.split(',');
return parts.length > 1 ? parts[1] : sig;
});
const isValid = signatures.some(sig => {
try {
return crypto.timingSafeEqual(
Buffer.from(sig),
Buffer.from(expectedSignature)
);
} catch {
return false; // Different lengths = invalid
}
});
if (!isValid) {
return res.status(400).json({ error: 'Invalid signature' });
}
// Check timestamp to prevent replay attacks (5-minute window)
const timestamp = parseInt(webhookTimestamp, 10);
const currentTime = Math.floor(Date.now() / 1000);
if (currentTime - timestamp > 300) {
return res.status(400).json({ error: 'Timestamp too old' });
}
} catch (err) {
console.error('Signature verification error:', err);
return res.status(400).json({ error: 'Invalid signature' });
}
// Parse the verified webhook body
const prediction = JSON.parse(req.body.toString());
// Handle the prediction based on its status
console.log('Prediction webhook received:', {
id: prediction.id,
status: prediction.status,
version: prediction.version
});
switch (prediction.status) {
case 'starting':
console.log('Prediction starting:', prediction.id);
break;
case 'processing':
console.log('Prediction processing:', prediction.id);
if (prediction.logs) {
console.log('Logs:', prediction.logs);
}
break;
case 'succeeded':
console.log('Prediction completed successfully:', prediction.id);
console.log('Output:', prediction.output);
break;
case 'failed':
console.log('Prediction failed:', prediction.id);
console.log('Error:', prediction.error);
break;
case 'canceled':
console.log('Prediction canceled:', prediction.id);
break;
default:
console.log('Unknown status:', prediction.status);
}
res.status(200).json({ received: true });
}
);
よくある予測ステータス
| ステータス | 説明 | よくある使用例 |
|---|---|---|
starting | 予測を初期化しています | UI に読み込み状態を表示する |
processing | モデルが実行中です | 進行状況を表示し、利用可能な場合はログを表示する |
succeeded | 予測が正常に完了しました | 最終出力を処理し、UI を更新する |
failed | 予測でエラーが発生しました | ユーザーにエラーメッセージを表示する |
canceled | 予測がキャンセルされました | リソースをクリーンアップし、ユーザーに通知する |
環境変数
# Your webhook signing secret from Replicate
REPLICATE_WEBHOOK_SECRET=whsec_your_secret_here
ローカル開発
ローカルで webhook をテストするには、Hookdeck CLI をインストールします。
次に、トンネルを起動します。
npx hookdeck-cli listen 3000 replicate --path /webhooks/replicate
アカウントは不要です。リクエストを確認できるローカルトンネルと Web UI を提供します。
参考資料
- Replicate webhook とは — イベントタイプとペイロードの構造
- Webhook の設定 — ダッシュボードの設定と署名シークレット
- 署名の検証 — 検証アルゴリズムとよくある問題
実装用リソース
フレームワークの例
- Express の実装 — Express を使用した Node.js
- Next.js の実装 — API ルートを備えた React フレームワーク
- FastAPI の実装 — Python の非同期フレームワーク
ドキュメント
推奨:webhook-handler-patterns
次のパターンを活用して、webhook の実装を強化しましょう。
関連スキル
- stripe-webhooks - Stripe の決済 webhook
- github-webhooks - GitHub のリポジトリイベント
- shopify-webhooks - Shopify のストアイベント
- clerk-webhooks - Clerk の認証イベント
- webhook-handler-patterns - 冪等性、エラー処理、再試行ロジック
- hookdeck-event-gateway - キューに代わる webhook インフラストラクチャ。確実な配信、自動再試行、再生、レート制限、webhook ハンドラーの可観測性を提供します
コメント
Markdown 対応