웹훅
실행이 끝날 때까지 폴링하지 않고 완료 알림을 받습니다.
엔드포인트를 한 번 등록한 다음, 그 엔드포인트의 webhook_id 를 실행을 시작할 때 전달하면, 해당 실행이 구독한 상태로 바뀌는 순간 저희가 호출합니다 — 보통 1분 이내입니다.
엔드포인트 등록
POST {base_url}/webhooks
{
"url": "https://hooks.example.com/morphic",
"events": ["workflow_run.succeeded", "workflow_run.failed"],
"description": "story pipeline"
}필요 runs:write. URL은 공개되어 있어야 합니다 https 자격 증명이 포함되지 않아야 하며, 조직은 최대 10개의 엔드포인트를 보유할 수 있습니다.
응답은 201 해당 엔드포인트의 id — 이를 webhook_id 실행 시 전달하고 — 그리고 그 엔드포인트의 서명 비밀키 (whsec_…), 한 번만 표시됩니다. API 키처럼 보관하세요.
GET {base_url}/webhooks
DELETE {base_url}/webhooks/{webhook_id}GET (runs:read)는 엔드포인트를 나열할 뿐, 비밀값은 절대 표시하지 않습니다. DELETE (runs:write)는 하나를 제거합니다. 해당 항목에 대해 아직 보류 중인 전달은 삭제됩니다. 비밀을 교체하려면 새 엔드포인트를 등록하고 실행을 그쪽으로 옮기세요.
이벤트
| 이벤트 | 다음 경우에 발생 |
|---|---|
workflow_run.succeeded | 실행이 완료되었으며, 자산을 사용할 수 있습니다 |
workflow_run.failed | 실행이 중단되었으며; error 가 그 이유를 설명합니다 |
workflow_run.needs_input | 실행이 Morphic Studio의 사람을 기다리고 있습니다 |
workflow_run.expired | 실행이 수명 내에 끝나지 않았습니다 |
전달 내용
POST https://hooks.example.com/morphic
Morphic-Event-Id: 0192f4a0-3c71-7b92-8e14-5d6f2a9b3c07
Morphic-Delivery-Id: 0192f4a0-4d82-7c03-9f25-6e7a3b0c4d18
Morphic-Event-Type: workflow_run.succeeded
Morphic-Signature: t=1790056632,v1=3f9c1a…
{
"id": "0192f4a0-3c71-7b92-8e14-5d6f2a9b3c07",
"type": "workflow_run.succeeded",
"created_at": "2026-09-22T04:17:12Z",
"api_version": "v1",
"data": {
"run": { "id": "0192f3d0-…", "status": "succeeded", "assets": [], "credits_used": 1792 }
}
}응답은 run 객체는 동일한 형태입니다 워크플로우 실행 읽기 를 반환하므로, 자산 이 포함되므로 — 성공한 전달은 후속 호출이 필요 없습니다. 이는 이벤트가 발생했을 당시의 실행 상태이며, 전달 재시도 기간 동안에는 자산 링크가 약 하루 동안 유효합니다.
모든 전달 검증하기
다음의 HMAC-SHA256을 계산하세요 {timestamp}.{raw body} 를 서명 비밀키로 계산한 뒤 v1 과 상수 시간으로 비교하세요. 다음의 원시 본문을 JSON 파싱 전에 사용하세요.
import crypto from 'node:crypto';
function verify({ rawBody, header, secret }) {
const parts = Object.fromEntries(
header.split(',').map((pair) => pair.split('=')),
);
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
const signed = Buffer.from(expected);
const given = Buffer.from(parts.v1);
if (signed.length !== given.length) return false;
if (!crypto.timingSafeEqual(signed, given)) return false;
// 재전송된 전달은 거부합니다.
return Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
}검증되지 않은 웹훅 엔드포인트는 열린 문과 같습니다: URL만 알아도 실행이 성공했다고 알려줄 수 있습니다. 서명을 검증하고 5분이 지난 타임스탬프는 거부하세요.
재시도 및 순서
- 응답
2xx이내에 10초. 먼저 수신 확인을 하고, 그다음 작업을 수행하세요 — 느린 처리기는 실패로 간주됩니다. - 비-
2xx또는 타임아웃은 약 하루 동안 지수적 백오프로 재시도된 뒤 삭제됩니다. 리디렉션은 따르지 않으며, 실패로 간주됩니다. - 엔드포인트가 구독한 이벤트만 전송되며, 다른 상태에 도달한 실행은 이에 대해 아무 것도 보고하지 않습니다.
- 전달은 도착할 수 있습니다 순서가 뒤바뀌거나 여러 번. 다음을 키로 사용하세요
Morphic-Event-Id그리고 이미 처리한 것은 무시하세요. - 하나의
성공한전달이 실행에 대한 자체 기록이 생기기 전에 도착할 수 있습니다. 오류로 처리하지 말고 그렇게 처리하세요 — 또는 그런 실행은 폴링으로 대체하세요.
웹훅은 보장이 아니라 최적화입니다. 자신이 아직 알지 못하는 실행을 폴링하는 느린 점검을 유지하여, 자신 쪽의 잘못된 배포 하나 때문에 하루치 출력이 사라지지 않게 하세요.