> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sajuapi.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 웹훅

> 운세 이벤트에 대한 실시간 알림 수신

<Info>
  웹훅은 곧 출시 예정입니다. 이 페이지는 계획된 기능을 설명합니다.
</Info>

## 개요

웹훅을 통해 사주 API 통합에서 이벤트가 발생할 때 실시간 HTTP 콜백을 받을 수 있습니다.

## 계획된 이벤트

| 이벤트                  | 설명            | 사용 사례         |
| -------------------- | ------------- | ------------- |
| `fortune.generated`  | 새 운세 생성됨      | 사용자 대시보드 업데이트 |
| `daily.reset`        | 자정에 일일 운세 초기화 | 사용자에게 새 운세 알림 |
| `cache.warmed`       | 캐시 워밍 완료      | 시스템 상태 확인     |
| `rate_limit.warning` | 요청 제한 도달 임박   | 운영팀 알림        |

## 웹훅 페이로드 형식

```json theme={null}
{
  "id": "evt_abc123",
  "type": "fortune.generated",
  "created": "2025-01-15T09:00:00Z",
  "data": {
    "dayMaster": "병화",
    "date": "2025-01-15",
    "score": 78,
    "model": "haiku"
  }
}
```

## 웹훅 보안

모든 웹훅에는 검증용 서명 헤더가 포함됩니다:

```typescript theme={null}
import crypto from 'crypto';

function verifyWebhook(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

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

// Express 미들웨어
app.post('/webhooks/saju', (req, res) => {
  const signature = req.headers['x-saju-signature'];
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    signature,
    process.env.WEBHOOK_SECRET
  );

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

  // 웹훅 처리
  handleWebhook(req.body);
  res.status(200).send('OK');
});
```

## 재시도 정책

실패한 웹훅 전송은 지수 백오프로 재시도됩니다:

| 시도 | 지연  |
| -- | --- |
| 1  | 즉시  |
| 2  | 1분  |
| 3  | 5분  |
| 4  | 30분 |
| 5  | 2시간 |

5번 실패 후 웹훅은 실패로 표시되며 이메일 알림을 받게 됩니다.

## 웹훅 관리

### 웹훅 등록 (예정)

```bash theme={null}
curl -X POST https://api.sajuapi.dev/webhooks \
  -H "X-API-Key: bs_live_xxx" \
  -d '{
    "url": "https://your-app.com/webhooks/saju",
    "events": ["fortune.generated", "daily.reset"]
  }'
```

### 웹훅 목록 조회 (예정)

```bash theme={null}
curl https://api.sajuapi.dev/webhooks \
  -H "X-API-Key: bs_live_xxx"
```

### 웹훅 삭제 (예정)

```bash theme={null}
curl -X DELETE https://api.sajuapi.dev/webhooks/wh_abc123 \
  -H "X-API-Key: bs_live_xxx"
```

## 대안: 폴링

웹훅이 출시되기 전까지 폴링으로 업데이트를 확인할 수 있습니다:

```typescript theme={null}
// 매시간 새 운세 데이터 폴링
setInterval(async () => {
  const response = await fetch('/api/daily-fortune', {
    method: 'POST',
    headers: { 'X-API-Key': API_KEY },
    body: JSON.stringify({ saju, userName, date: today })
  });

  const { data, meta } = await response.json();

  if (!meta.cached) {
    // 새 운세 생성됨
    notifyUser(data);
  }
}, 60 * 60 * 1000);
```

## 알림 받기

웹훅 출시 알림을 받고 싶으신가요?

<Card title="대기 목록 등록" icon="bell" href="mailto:api@sajuapi.dev?subject=Webhook%20Waitlist">
  웹훅 베타 대기 목록에 등록하려면 이메일을 보내주세요.
</Card>
