가이드
Webhook
배치 작업 완료 알림 수신
1분 이상 걸리는 배치 작업에서는 Webhook이 폴링보다 저렴하고 빠릅니다. 작업이 종료 상태에 도달하면 Thunderbit가 당신의 URL로 POST합니다.
제출 시 설정
{
"urls": ["https://example.com/page1"],
"webhook": {
"url": "https://your-server.com/api/webhook/distill",
"secret": "whsec_your_secret_key",
"headers": { "X-Custom-Auth": "your-token" }
}
}webhook.headers 필드는 커스텀 헤더 맵을 받지만, 이 필드는 향후 사용을 위해 예약되어 있으며 현재 서버에서 전송되지 않습니다. 검증은 아래 문서화된 헤더만 기준으로 설계하세요.
요청 헤더
모든 전달에는 다음 4개의 헤더가 포함됩니다:
| Header | Value |
|---|---|
Content-Type | application/json |
X-Webhook-Event | batch.completed |
X-Webhook-Timestamp | Unix epoch(밀리초) |
X-Webhook-Signature | sha256=<base64-encoded HMAC-SHA256> |
페이로드
{
"id": "batch_a1b2c3d4...",
"jobType": "batch_distill",
"status": "COMPLETED",
"total": 50,
"completed": 49,
"failed": 1,
"creditsUsed": 100,
"createdAt": "2026-04-26T10:00:00Z",
"completedAt": "2026-04-26T10:05:23Z"
}jobType은batch_distill또는batch_extract.status는COMPLETED,FAILED,CANCELLED중 하나.
페이로드는 의도적으로 작게 유지됩니다. 콜백을 받은 후 GET /batch/distill/{id}(또는 /batch/extract/{id})로 전체 결과를 가져오세요.
서명 검증
secret이 설정되면 모든 전달에 X-Webhook-Signature 헤더가 포함됩니다.
- 알고리즘: HMAC-SHA256
- 서명 대상 문자열:
<X-Webhook-Timestamp>.<raw-json-body>(리터럴.사용) - 출력 형식:
sha256=<base64-encoded-hash>(Base64, hex 아님)
원본 요청 바이트로 검증하세요(JSON을 다시 직렬화하지 마세요). 그 후 상수 시간 비교를 수행합니다.
import hmac, hashlib, base64
def verify(raw_body: bytes, timestamp: str, signature: str, secret: str) -> bool:
base = f"{timestamp}.{raw_body.decode('utf-8')}".encode('utf-8')
digest = hmac.new(secret.encode('utf-8'), base, hashlib.sha256).digest()
expected = "sha256=" + base64.b64encode(digest).decode('ascii')
return hmac.compare_digest(expected, signature)재전송 방지
|now - X-Webhook-Timestamp| > 60000(60초 윈도우)이면 요청을 거부하세요. 타임스탬프는 Unix epoch 밀리초 단위입니다. 프로덕션에서는 서명되지 않은 webhook을 절대 신뢰하지 마세요.
재시도 동작
- 전달당 타임아웃: 30초
- 최대 재시도: 3회
- 백오프: 지수 백오프, 시작 1초, 상한 10초
- 엔드투엔드 총 윈도우: 약 120초
모든 재시도가 실패해도 작업은 우리 쪽에서는 완료된 상태입니다. 수신 엔드포인트는 멱등해야 합니다(id를 중복 제거 키로 사용).