웹훅
동결된 서피스 (대시보드 UI)
클라우드 대시보드의 전용 웹훅 페이지는 명시적인 제품 결정(2026-07-04, 저장소의 docs/FROZEN_SURFACES.md 참조)에 의해 현재 동결 상태입니다: 사이드바 항목이 숨겨져 있고 /webhooks는 /dashboard로 리디렉션됩니다. 아래에 설명된 웹훅 API와 전달 파이프라인은 계속 운영 중이며 유지됩니다. 단, 동결이 해제될 때까지 새로운 웹훅 기능 작업은 계획되어 있지 않습니다. 여기에 문서화된 REST API 서피스를 통해 웹훅을 관리하세요.
클라우드 전용
웹훅은 클라우드 버전에서만 사용할 수 있습니다.
웹훅을 사용하면 ADHDev Cloud가 머신 및 에이전트 이벤트를 자체 HTTP 엔드포인트로 전송할 수 있습니다.
현재 주요 동작:
- 웹훅 API는 운영 중입니다.
- 전용
/webhooks대시보드 페이지는 현재 안정적인 표준 탐색 서피스가 아닙니다. - 페이로드, 이벤트, 전달 히스토리 구조의 정식 계약은 REST API 레퍼런스를 사용하세요.
- 웹훅 생성/토글/삭제/테스트 작업은 최근 로그인이 보호하는 클라우드 계정 작업으로, API 키가 아닌 신선한 대시보드 세션 JWT가 필요합니다.
웹훅 생성
현재 로그인된 클라우드 대시보드 세션에서 웹훅을 생성하세요. 요청 본문은 다음과 같습니다:
{
"url": "https://example.com/hooks/adhdev",
"events": ["agent:generating_completed", "agent:waiting_approval"]
}만료된 브라우저 세션이나 API 키로 변경 웹훅 엔드포인트를 호출하면 서버는 훅을 프로비저닝하는 대신 403 RECENT_LOGIN_REQUIRED를 반환합니다.
생성 응답에는 다음이 포함됩니다:
- 웹훅 레코드
- 서명 검증을 위해 한 번만 표시되는
secret
모든 지원 이벤트를 구독하려면 events에 ["*"]를 사용하세요.
이벤트
| 이벤트 | 트리거 |
|---|---|
agent:generating_started | 에이전트가 응답 생성을 시작함 |
agent:generating_completed | 에이전트가 생성을 완료함 |
agent:waiting_approval | 에이전트가 승인을 기다리는 중 |
agent:error | 에이전트가 오류를 만남 |
webhook:test | 테스트 전달이 명시적으로 요청됨 |
페이로드 형식
{
"event": "agent:generating_completed",
"payload": {
"chatTitle": "Claude Code · myproject",
"ideType": "claude-code",
"duration": 42,
"timestamp": 1714000000000
},
"timestamp": 1714000000000
}서명 검증
각 웹훅 요청에는 다음이 포함됩니다:
X-ADHDev-SignatureX-ADHDev-Event
서명 형식:
X-ADHDev-Signature: t=1714000000000,v1=a3f9c2b1...원시 요청 본문을 기준으로 검증하세요.
import crypto from 'crypto'
function verifySignature(body, signature, secret) {
const parts = Object.fromEntries(signature.split(',').map((p) => p.split('=')))
const timestamp = parts.t
const received = parts.v1
const payload = `${timestamp}.${body}`
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(received),
Buffer.from(expected)
)
}
// Express 예시
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-adhdev-signature']
const body = req.body.toString('utf8')
if (!verifySignature(body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature')
}
const event = JSON.parse(body)
// 이벤트 처리...
res.sendStatus(200)
})import hmac
import hashlib
def verify_signature(body: bytes, signature: str, secret: str) -> bool:
parts = dict(p.split('=', 1) for p in signature.split(','))
timestamp = parts.get('t', '')
received = parts.get('v1', '')
payload = f"{timestamp}.{body.decode('utf-8')}".encode()
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(received, expected)
# Flask 예시
@app.route('/webhook', methods=['POST'])
def webhook():
sig = request.headers.get('X-ADHDev-Signature', '')
if not verify_signature(request.data, sig, WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.get_json()
# 이벤트 처리...
return '', 200웹훅 시크릿은 웹훅 생성 시 한 번만 표시됩니다 — 안전하게 저장하세요.
관리 엔드포인트
GET /api/v1/webhooks
POST /api/v1/webhooks
PATCH /api/v1/webhooks/{webhookId}
DELETE /api/v1/webhooks/{webhookId}
GET /api/v1/webhooks/{webhookId}/deliveries?limit=20
POST /api/v1/webhooks/{webhookId}/testGET 엔드포인트가 가장 안전한 자동화 서피스입니다. 변경 엔드포인트(POST, PATCH, DELETE, test)는 최근 로그인이 보호하는 대시보드 세션 작업입니다.
재시도 정책
실패한 전달은 지수 백오프로 최대 3회 재시도됩니다.
플랜 제한
| 플랜 | 최대 웹훅 수 |
|---|---|
| Free | 2 |
| Pro | 10 |
| Team | 50 |
| Enterprise | 무제한 |
