Skip to main content
POST
https://sajuapi.dev
/
v1
/
webhooks
웹훅 등록
curl --request POST \
  --url https://sajuapi.dev/v1/webhooks \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: <api-key>' \
  --data '
{
  "url": "<string>",
  "events": [
    {}
  ],
  "description": "<string>",
  "metadata": {}
}
'
v1 Enterprise API (Coming Soon)이 엔드포인트는 Enterprise 버전에서 제공될 예정입니다. 현재는 v0 API를 사용하세요.
웹훅을 등록하여 특정 이벤트 발생 시 알림을 받습니다. 등록된 웹훅은 지정된 이벤트가 발생할 때마다 HTTP POST 요청을 전송합니다.
웹훅 URL은 HTTPS를 사용해야 하며, 공개적으로 접근 가능해야 합니다. 웹훅 요청은 HMAC-SHA256으로 서명됩니다.

Request Body 파라미터

url
string
required
웹훅 이벤트를 수신할 URL입니다. HTTPS만 지원됩니다. 최대 2048자입니다.
events
array
required
구독할 이벤트 목록입니다. 최소 1개 이상의 이벤트를 지정해야 합니다.
description
string
웹훅에 대한 설명입니다. 최대 200자입니다.
metadata
object
웹훅에 첨부할 메타데이터입니다. 키-값 쌍 형태입니다.

지원 이벤트

이벤트설명
profile.created새 프로필이 생성됨
profile.updated프로필이 수정됨
profile.deleted프로필이 삭제됨
fortune.generated운세가 생성됨
fortune.cached캐시된 운세가 반환됨
fortune.deleted운세가 삭제됨
batch.completed배치 작업이 완료됨
daily.reset자정(KST) 일일 리셋
unmasked.accessed복호화 엔드포인트 접근

Response

성공

웹훅 등록에 성공하면 Webhook 객체가 반환됩니다. secret 필드는 생성 시에만 반환됩니다.

실패

상태 코드에러 타입설명
400validation_error요청 데이터가 유효하지 않음
401authentication_errorAPI 키가 유효하지 않음
429rate_limited요청 한도 초과

요청 예시

curl -X POST https://api.sajuapi.dev/v1/webhooks \
  -H "X-API-Key: bs_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/saju",
    "events": ["fortune.generated", "profile.created", "daily.reset"],
    "description": "운세 생성 알림",
    "metadata": {
      "environment": "production",
      "team": "backend"
    }
  }'

응답 예시

{
  "id": "whk_abc123def456",
  "url": "https://your-server.com/webhooks/saju",
  "events": ["fortune.generated", "profile.created", "daily.reset"],
  "secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "description": "운세 생성 알림",
  "metadata": {
    "environment": "production",
    "team": "backend"
  },
  "active": true,
  "failure_count": 0,
  "created_at": "2025-01-16T09:00:00Z",
  "updated_at": "2025-01-16T09:00:00Z"
}

Webhook 객체

필드타입설명
idstring웹훅 ID입니다. whk_ 접두사로 시작합니다.
urlstring웹훅 수신 URL입니다.
eventsarray구독 중인 이벤트 목록입니다.
secretstring서명 검증용 시크릿입니다. 생성 시에만 반환됩니다.
descriptionstring웹훅 설명입니다.
metadataobject메타데이터입니다.
activeboolean활성화 상태입니다.
failure_countinteger연속 실패 횟수입니다. 5회 초과 시 비활성화됩니다.
last_triggered_atstring마지막 트리거 시간입니다.
created_atstring생성 시간입니다.
updated_atstring수정 시간입니다.
secret은 웹훅 생성 시에만 반환됩니다. 이 값을 안전하게 저장하세요. 분실 시 웹훅을 삭제하고 다시 생성해야 합니다.

웹훅 페이로드

웹훅 이벤트가 발생하면 다음 형식의 페이로드가 POST 요청으로 전송됩니다.
{
  "id": "evt_xyz789",
  "type": "fortune.generated",
  "created_at": "2025-01-16T09:00:00Z",
  "data": {
    "fortune_id": "ftn_abc123",
    "profile_id": "prf_def456",
    "score": 85,
    "model": "sonnet",
    "cached": false
  }
}

서명 검증

모든 웹훅 요청에는 X-Bithumb-Signature 헤더가 포함됩니다. 이 서명을 검증하여 요청의 진위를 확인하세요.
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// Express.js 예시
app.post('/webhooks/saju', (req, res) => {
  const signature = req.headers['x-saju-signature'];
  const isValid = verifyWebhookSignature(req.body, signature, WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // 이벤트 처리
  const { type, data } = req.body;
  console.log(`Received ${type}:`, data);

  res.status(200).json({ received: true });
});