API 레퍼런스

콜백

서명된 완료 콜백.

콜백은 실행이 끝났을 때 서버에 알려 주므로, 폴링하거나 이벤트 스트림을 열어 둘 필요가 없습니다. Ephemeral은 실행이 최종 상태에 도달한 뒤 실행 객체를 담은 서명된 POST 요청을 한 번 보냅니다.

콜백 요청

실행 요청에 callback을 추가합니다.

callback.urlstring필수
엔드포인트. HTTPS를 사용해야 하며 공용 주소로 해석되어야 합니다. 리디렉션은 따라가지 않습니다.
callback.secretstring필수
24~1,024자이며 전송마다 서명하는 데 사용합니다. 무작위 값을 생성해 서버에 보관하세요.
JSON
{
  "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-Signaturesha256= 뒤에, 타임스탬프, 마침표, 원본 본문을 시크릿을 키로 해서 계산한 HMAC-SHA256의 16진수 값이 붙습니다.
Content-Typeapplication/json
Signed content
<X-Ephemeral-Timestamp>.<raw request body>

서명 검증

본문을 파싱하기 전에 원본 바이트로 HMAC을 계산하고, 상수 시간 비교로 대조하세요.

Node.js with Express
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초 후에 시도하고, 이후 간격이 매번 두 배로 늘어 시도 사이의 간격이 최대 약 43분이 됩니다. 대기 중인 전달은 영구 저장되므로 엔진이 재시작되어도 유실되지 않습니다.

실행 ID로 중복을 제거하세요
엔드포인트가 같은 실행을 두 번 이상 받을 수 있습니다. 예를 들어 전달을 처리했지만 응답이 유실된 경우입니다. X-Ephemeral-Run을 사용해 처리를 멱등하게 만드세요.
콜백이 정산이 끝나기 전에 도착할 수 있습니다. 본문의 billing_pending이 true이면, 나중에 GET /v1/runs/{id}로 실행을 다시 읽어 최종 비용을 확인하세요.
© 2026 Ephemeral제작: erni.works
esc

“”와(과) 일치하는 항목이 없습니다.