v1 Enterprise API (Coming Soon)이 엔드포인트는 Enterprise 버전에서 제공될 예정입니다.
현재는 v0 API를 사용하세요.
Server-Sent Events(SSE)를 통해 실시간 이벤트를 수신합니다. 웹훅의 대안으로, 클라이언트에서 직접 이벤트를 구독할 수 있습니다.
SSE는 단방향 스트리밍입니다. 양방향 통신이 필요하면 웹훅을 사용하세요.
Query 파라미터
수신할 이벤트 유형입니다. 쉼표로 구분합니다. 생략하면 모든 이벤트를 수신합니다.
마지막으로 수신한 이벤트 ID입니다. 연결이 끊어진 후 재연결 시 사용합니다.
Response
연결에 성공하면 SSE 스트림이 시작됩니다. 이벤트는 text/event-stream 형식으로 전송됩니다.
| 상태 코드 | 에러 타입 | 설명 |
|---|
| 401 | authentication_error | API 키가 유효하지 않음 |
| 429 | rate_limited | 동시 연결 수 초과 |
요청 예시
# 모든 이벤트 수신
curl -N -H "X-API-Key: bs_live_xxx" \
"https://api.sajuapi.dev/v1/events"
# 특정 이벤트만 수신
curl -N -H "X-API-Key: bs_live_xxx" \
"https://api.sajuapi.dev/v1/events?events=fortune.generated,fortune.cached"
# 특정 프로필 이벤트만 수신
curl -N -H "X-API-Key: bs_live_xxx" \
"https://api.sajuapi.dev/v1/events?profile_id=prf_abc123def456"
이벤트 형식
SSE 이벤트는 다음 형식으로 전송됩니다.
event: fortune.generated
id: evt_abc123def456
data: {"type":"fortune.generated","fortune_id":"ftn_xyz789","profile_id":"prf_abc123","score":85,"timestamp":"2025-01-16T09:00:00Z"}
event: heartbeat
id: hb_1705395600
data: {"type":"heartbeat","timestamp":"2025-01-16T09:00:00Z"}
이벤트 유형
| 이벤트 | 설명 | 데이터 |
|---|
fortune.generated | 운세가 생성됨 | fortune_id, profile_id, score, model |
fortune.cached | 캐시된 운세 반환 | fortune_id, profile_id |
profile.created | 프로필이 생성됨 | profile_id, day_master |
profile.updated | 프로필이 수정됨 | profile_id |
profile.deleted | 프로필이 삭제됨 | profile_id |
daily.reset | 일일 운세 리셋 (자정) | date, profiles_count |
heartbeat | 연결 유지 확인 | timestamp |
응답 예시
fortune.generated
{
"type": "fortune.generated",
"fortune_id": "ftn_abc123def456",
"profile_id": "prf_xyz789abc123",
"fortune_type": "daily",
"fortune_date": "2025-01-16",
"score": 85,
"model": "haiku",
"cached": false,
"timestamp": "2025-01-16T09:00:00Z"
}
daily.reset
{
"type": "daily.reset",
"date": "2025-01-17",
"profiles_count": 5420,
"cache_cleared": true,
"timestamp": "2025-01-17T00:00:00+09:00"
}
heartbeat
{
"type": "heartbeat",
"timestamp": "2025-01-16T09:05:00Z"
}
React 통합 예시
import { useEffect, useState } from 'react';
function useEventStream(apiKey, events = []) {
const [lastEvent, setLastEvent] = useState(null);
const [connected, setConnected] = useState(false);
useEffect(() => {
const params = new URLSearchParams();
if (events.length > 0) {
params.set('events', events.join(','));
}
const eventSource = new EventSource(
`https://api.sajuapi.dev/v1/events?${params}`,
{ headers: { 'X-API-Key': apiKey } }
);
eventSource.onopen = () => setConnected(true);
eventSource.onerror = () => setConnected(false);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type !== 'heartbeat') {
setLastEvent(data);
}
};
return () => eventSource.close();
}, [apiKey, events.join(',')]);
return { lastEvent, connected };
}
// 사용 예시
function FortuneMonitor() {
const { lastEvent, connected } = useEventStream(
'bs_live_xxx',
['fortune.generated']
);
return (
<div>
<div>상태: {connected ? '연결됨' : '연결 끊김'}</div>
{lastEvent && (
<div>
최근 이벤트: {lastEvent.type} - {lastEvent.fortune_id}
</div>
)}
</div>
);
}
재연결 처리
연결이 끊어지면 Last-Event-ID 헤더를 사용하여 누락된 이벤트를 복구할 수 있습니다.
let lastEventId = null;
function connect() {
const url = new URL('https://api.sajuapi.dev/v1/events');
if (lastEventId) {
url.searchParams.set('last_event_id', lastEventId);
}
const eventSource = new EventSource(url, {
headers: { 'X-API-Key': 'bs_live_xxx' }
});
eventSource.onmessage = (event) => {
lastEventId = event.lastEventId;
// 이벤트 처리
};
eventSource.onerror = () => {
eventSource.close();
// 5초 후 재연결
setTimeout(connect, 5000);
};
}
동시 SSE 연결 수는 API 키당 5개로 제한됩니다. 초과 시 가장 오래된 연결이 종료됩니다.
Heartbeat
서버는 30초마다 heartbeat 이벤트를 전송하여 연결을 유지합니다. 60초 이상 이벤트가 없으면 연결이 끊어진 것으로 간주하고 재연결하세요.
이벤트는 최대 5분간 버퍼링됩니다. 5분 이상 연결이 끊어지면 일부 이벤트가 손실될 수 있습니다. 중요한 이벤트는 웹훅을 사용하세요.