웹훅
웹훅은 영상 완성 같은 무언가가 발생하면 서버에 알려줍니다. 폴링 GET /v1/job/{id}을 절약해 줍니다. 웹훅은 API 나머지 부분과 동일한 API 키로 관리됩니다 , https://reigniter.ai/api/webhooks.
| 행사 | 발송 시간 |
|---|---|
video.completed |
렌더링이 완료되었습니다. 페이로드는 download_url, 7일 동안 작동하는 링크입니다. |
video.failed |
렌더링이 실패했습니다. 취소한 렌더링은 이 신호를 보내지 않습니다. |
training.invited |
학습자는 모듈을 배정받고 교육 페이지를 받았습니다. |
training.completed |
이름 있는 학습자가 모듈을 완료했습니다. 페이로드에는 점수(서버가 표시), passed, 그리고 결과 페이지가 있습니다. |
training.passed / training.failed |
모듈 합격 점수에 맞춰 training.completed와 함께 전송됨. 시간이 부족하면 실패야. |
training.overdue |
학습자가 마감일에 끝내지 못한 경우. 초대장당 한 번씩. |
training.certificate_expiring |
증명서는 30일 이내에 만료됩니다. 증명서당 한 번씩 유효합니다. |
post.published |
게시물은 YouTube, TikTok, LinkedIn, Facebook 또는 Instagram에서 공개되었습니다. 페이로드에는 플랫폼, 계정, 그리고 url, 그리고 플랫폼이 게시물을 제공할 때 링크가 있습니다. |
post.failed |
게시물이 게시될 수 없었다. reason 플랫폼의 명확한 답변이다. |
credits.low |
잔액이 10 크레딧 이하로 줄었어요. 한 번씩 한 번씩. |
credits.purchased |
계좌에 크레딧이 추가되었습니다. |
subscription.created |
요금제 구독이 시작되었습니다. |
subscription.canceled |
요금제 구독이 취소되었습니다. |
user.signup |
계정이 생성되었습니다. |
user.onboarded |
계정은 온보딩을 마쳤습니다. |
GET /api/webhooks/events 이 목록을 반환합니다.
웹훅을 설정하세요
섹션 제목: “웹훅을 설정하세요”-
서버에 JSON 바디를 가진
POST요청을 받고2xx빠르게 응답하는 엔드포인트를 구축하세요. 공용 인터넷에서 접근 가능해야 합니다. 사설 및 로컬 네트워크 주소는 거부됩니다. -
이벤트에 구독하세요. 웹훅 하나는 이벤트를 듣고; 필요한 이벤트마다 하나씩 생성하세요.
터미널 창 curl https://reigniter.ai/api/webhooks/hooks \-H "Authorization: Bearer $REIGNITER_API_KEY" \-H "Content-Type: application/json" \-d '{"event": "video.completed","webhook_url": "https://hooks.example.com/reignitor","description": "Post finished videos to our CMS"}'const res = await fetch('https://reigniter.ai/api/webhooks/hooks', {method: 'POST',headers: {Authorization: `Bearer ${process.env.REIGNITER_API_KEY}`,'Content-Type': 'application/json',},body: JSON.stringify({event: 'video.completed',webhook_url: 'https://hooks.example.com/reignitor',description: 'Post finished videos to our CMS',}),});const { hook, secret } = await res.json();res = requests.post("https://reigniter.ai/api/webhooks/hooks",headers={"Authorization": f"Bearer {os.environ['REIGNITER_API_KEY']}"},json={"event": "video.completed","webhook_url": "https://hooks.example.com/reignitor","description": "Post finished videos to our CMS",},)data = res.json()hook, secret = data["hook"], data["secret"] -
201응답에서secret을 저장 하세요. 서명을 확인하려면 필요합니다. -
테스트를 보내세요.
POST /api/webhooks/hooks/{id}/test서명된ping이벤트를 URL로 보내고 엔드포인트가 응답한 내용을 알려줍니다:{ "delivered": true, "status": 200 }
같은 이벤트와 URL을 다시 구독해도 중복이 생성되지 않습니다. 기존 웹훅을 reused: true 반환하고 다시 켜집니다.
출산이 어떤 모습인지
섹션 제목: “출산이 어떤 모습인지”모든 출산은 JSON 몸체를 가진 POST 입니다:
{ "event": "video.completed", "payload": { "job_id": "7d2e4b10-5c3a-4f8e-a1b2-9c0d8e7f6a54", "user_id": "3f1c2a9e-8b7d-4c1e-9f0a-2d6b5e4c3a21", "output_url": "https://cdn.example.com/exports/7d2e4b10.mp4", "canvas_id": null, "scene_count": 4, "scenes_failed": 0, "credits_charged": 12 }, "emitted_at": "2026-09-25T10:15:00.000Z", "delivery_id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"}video.failed job_id, user_id, canvas_id, 그리고 reason를 담고 있습니다.
payload.job_id job_id POST /v1/render 매칭하세요.
그리고 이 헤더들:
| 헤더 | 가치 |
|---|---|
X-Reigniter-Event |
이벤트 이름. |
X-Reigniter-Delivery |
이 배달에 대한 고유 ID입니다. 배달이 재시도될 때도 동일하게 유지됩니다. |
X-Reigniter-Timestamp |
유닉스 시간, 즉 전달 서명이 이루어졌을 때 순식간에 달라졌습니다. |
X-Reigniter-Signature |
sha256= 그리고 {timestamp}.{raw body}의 헥스 HMAC-SHA256, 당신의 비밀로 키가 묶여 있습니다. |
서명 확인해
섹션 제목: “서명 확인해”모든 배송을 믿기 전에 확인하세요:
- JSON 파싱하기 전에 원시 요청 본문을 읽으세요.
- 끈을
{X-Reigniter-Timestamp}.{raw body}만들고, - 비밀을 16진으로 사용해 HMAC-SHA256을 계산하고, 앞에
sha256=을 추가하세요. - 상수 시간 비교를 사용해
X-Reigniter-Signature와 비교해 보세요. - 타임스탬프가 5분 이상 지난 경우 배송을 거부하세요.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyReigniterWebhook(rawBody, headers, secret) { const timestamp = headers['x-reigniter-timestamp']; const received = headers['x-reigniter-signature'] ?? ''; if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = 'sha256=' + createHmac('sha256', secret) .update(`${timestamp}.${rawBody}`) .digest('hex');
const a = Buffer.from(expected); const b = Buffer.from(received); return a.length === b.length && timingSafeEqual(a, b);}import hashlib, hmac, time
def verify_reignitor_webhook(raw_body: bytes, headers, secret: str) -> bool: timestamp = headers.get("X-Reigniter-Timestamp") received = headers.get("X-Reigniter-Signature", "") if not timestamp or abs(time.time() - int(timestamp)) > 300: return False
signed = f"{timestamp}.".encode() + raw_body expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, received)전달 및 재도전
섹션 제목: “전달 및 재도전”- 각 배달은 엔드포인트가 응답할 때까지 최대 10초까지 기다립니다.
5xx,429, 타임아웃 또는 네트워크 오류가 최대 3번까지 약 1초 간격으로 재시도됩니다.- 다른
4xx은 재시도되지 않습니다. - 재시도는 같은
X-Reigniter-Delivery을 유지합니다. 이미 처리한 배달은 무시하는 데 사용하세요. - 20번 연속 배송 실패가 발생하면 웹훅이 꺼집니다.
GET /api/webhooks/hooksactive: false와last_status의 마지막 오류가 표시됩니다. 엔드포인트를 고친 후PATCH /api/webhooks/hooks/{id}와{ "active": true }로 다시 켜세요.
배달을 보관한 직후 바로 2xx 답장하고, 그 후에는 천천히 작업하세요.
웹훅 관리
섹션 제목: “웹훅 관리”| 방법 | 경로 | 이 제품이 하는 일은 |
|---|---|---|
GET |
/api/webhooks/events |
이벤트 이름 목록과 서명 방식 |
GET |
/api/webhooks/hooks |
웹훅을 나열하세요 |
POST |
/api/webhooks/hooks |
웹훅 생성 |
PATCH |
/api/webhooks/hooks/{id} |
URL이나 설명을 일시정지, 재개, 변경하세요 |
DELETE |
/api/webhooks/hooks/{id} |
웹훅을 삭제하세요 |
POST |
/api/webhooks/hooks/{id}/test |
서명된 ping |
계정은 최대 25개의 웹훅을 가질 수 있습니다. 전체 요청 및 응답 형태는 엔드포인트 참조에 있습니다.