コールバックは、実行が終了したことをあなたのサーバーに知らせます。ポーリングしたり、イベントストリームを開いたままにしたりする必要はありません。実行が最終ステータスに達すると、Ephemeral が実行オブジェクトを含む署名付きの POST リクエストを 1 回送信します。
コールバックを要求する
実行リクエストに callback を追加します。
callback.urlstring必須あなたのエンドポイント。HTTPS を使用し、パブリックなアドレスに解決される必要があります。リダイレクトには従いません。
callback.secretstring必須24 から 1,024 文字。各配信の署名に使います。ランダムな値を生成し、サーバー上で保管してください。
{
"workflow": "investigate-payment",
"input": { "payment_id": "pay_123" },
"max_cost_micros": 500000,
"callback": {
"url": "https://example.com/hooks/ephemeral",
"secret": "3f9a6c1e8b2d47f0a5c3e9d1b7f2a6c4"
}
}シークレットは、実行の定義を含め、どの読み取りでも返されません。コールバックは保存済みのワークフローには含まれません。必要な実行ごとに設定してください。
受信する内容
ボディは、配信時点の実行オブジェクトで、次のヘッダーを付けた JSON として送信されます。
| ヘッダー | 値 |
|---|---|
X-Ephemeral-Run | 実行 ID。 |
X-Ephemeral-Timestamp | この試行に署名した時刻の Unix 時間 (秒)。 |
X-Ephemeral-Signature | sha256= に続けて、タイムスタンプ、ピリオド、生のボディをシークレットで署名した HMAC-SHA256 の 16 進数。 |
Content-Type | application/ |
<X-Ephemeral-Timestamp>.<raw request body>署名を検証する
ボディをパースする前に、生のバイト列に対して HMAC を計算し、定数時間で比較してください。
import crypto from "node:crypto";
import express from "express";
const app = express();
app.post("/hooks/ephemeral", express.raw({ type: "application/json" }), (req, res) => {
const timestamp = req.get("X-Ephemeral-Timestamp") ?? "";
const signature = req.get("X-Ephemeral-Signature") ?? "";
const expected =
"sha256=" +
crypto
.createHmac("sha256", process.env.EPHEMERAL_CALLBACK_SECRET)
.update(timestamp + ".")
.update(req.body)
.digest("hex");
const valid =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
if (!valid || !fresh) return res.sendStatus(401);
const run = JSON.parse(req.body);
// Record run.id first and skip it if you have already handled it.
res.sendStatus(204);
});各試行は、その時点の時刻で署名されます。古いタイムスタンプを拒否すれば、正当な再試行を拒否することなく、リプレイ攻撃を抑えられます。
配信と再試行
2xx のレスポンスは、配信済みとみなされます。それ以外 (タイムアウトやリダイレクトを含む) は再試行されます。最初の再試行は 10 秒後で、その後は間隔が毎回 2 倍になり、最大で約 43 分間隔になります。保留中の配信は永続的に保存されるため、エンジンが再起動しても失われません。
実行 ID で重複を排除してください
同じ実行が、エンドポイントに複数回届くことがあります。たとえば、配信を処理したもののレスポンスが失われた場合です。
X-Ephemeral-Run を使って、処理が冪等になるようにしてください。コールバックは、請求の精算が完了する前に届くことがあります。ボディの
billing_pending が true の場合は、後で GET /v1/runs/{id} で実行を読み取り、最終的なコストを確認してください。