메인 콘텐츠로 건너뛰기
테넌트 어드민 JWT 인증 으로 호출. SDK 측의 X-API-KEY 와 다른 인증 체계입니다. 호스트는 https://{tenantCode}.aika.life (베타) / https://{tenantCode}.ones1ght.com (프로덕션).백오피스(admin.aika.life) 는 /api/v1/admin/sdk-chat/... 로 모든 테넌트 데이터를 무제한 조회 가능 (super admin 권한).

1. 실시간 SSE 스트림

GET /api/v1/sdk-chat/events/stream
Content-Type: text/event-stream. 테넌트 어드민으로 1 회 연결하면 그 테넌트 내 모든 SDK 채팅 라이프사이클 이벤트가 실시간으로 푸시됩니다. 25 초 간격 ping heartbeat 로 ALB / nginx idle timeout 방지.

이벤트 종류

event트리거data 페이로드
ready연결 직후 1회{}
ping25 초마다(빈 문자열)
chat_completed폴링 응답이 status: "completed" 로 처음 전이{profile_id, chat_id}
backlist_triggerediOS 가 POST /v1/chat/{pid}/backlist-trigger 호출{profile_id, chat_id, notification_items}

클라이언트 예 (브라우저)

const es = new EventSource("/api/v1/sdk-chat/events/stream", { withCredentials: true });

es.addEventListener("chat_completed", (e) => {
  const { profile_id, chat_id } = JSON.parse(e.data);
  // → /api/v1/sdk-chat/{chat_id} 디테일 재조회
});

es.addEventListener("backlist_triggered", (e) => {
  const { profile_id, chat_id, notification_items } = JSON.parse(e.data);
  // → 대시보드 우측 토스트 / 지도 마커 등 즉시 렌더
});
라이브 only — 구독자가 없는 시점에 발생한 이벤트는 buffering 없이 drop. 누적 데이터는 아래 히스토리 엔드포인트로.

2. 히스토리 리스트 (페이징)

GET /api/v1/sdk-chat?profile_id={uuid}&page=0&size=20
자기 테넌트의 sdk_chat 행을 최신순으로 페이징. profile_id 필터 선택. size 최대 100.

Response 200

{
  "success": true,
  "data": {
    "items": [
      {
        "chat_id":         "3736f10f-...",
        "profile_id":      "6b97957c-...",
        "profile_summary": { "name": "佐藤花子", "gender": "F", "age": 32, "locale": "ja" },
        "prompt":          "오늘 저녁 카레 땡기는데",
        "status":          "completed",
        "last_error":      null,
        "created_at":      "2026-04-23T05:28:08Z",
        "updated_at":      "2026-04-23T05:30:00Z",
        "ended_at":        "2026-04-23T05:31:00Z"
      }
    ],
    "total": 234,
    "page": 0,
    "size": 20
  }
}
필드설명
statusin_progress / completed / error / ended (폴링과 같은 어휘)
profile_summarysdk_profile.data JSONB 에서 name / gender / age / locale 만 추출
last_errorerror 일 때만 채워짐
ended_atDELETE 호출 시점, 그 외 null
pipeline_result 는 리스트에 포함하지 않음 (용량 ↑). 상세는 아래.

3. 히스토리 상세

GET /api/v1/sdk-chat/{chat_id}
폴링 완료 시점의 응답을 그대로 보존 — status / back_list_status / todos / recommended_items / notification_items 가 top-level 에 hoist 되어 있어 폴링 응답과 동일 shape. 자세한 필드 설명은 Profile Chat — 4. 채팅 이력 조회 참조 (응답 구조 동일). 추가로 리스트와 동일하게 profile_summary, profile_session_id 까지 동봉.

4. 백오피스 (super admin) 엔드포인트

admin.aika.life 에서 호출. 테넌트 경계 없이 전체 조회. tenant_id, profile_id 둘 다 선택 필터.
엔드포인트동작
GET /api/v1/admin/sdk-chat?tenant_id=...&profile_id=...&page=...&size=...테넌트 어드민 리스트와 동일 shape, 추가로 각 row 에 tenant_id 동봉
GET /api/v1/admin/sdk-chat/{chat_id}테넌트 어드민 상세와 동일 shape (테넌트 제약 없음)
권한: ROLE_ADMIN (Spring Security @PreAuthorize).

5. 권한 매트릭스

엔드포인트인증권한
GET /api/v1/sdk-chat/events/stream테넌트 JWTuser.role == 'admin'
GET /api/v1/sdk-chat테넌트 JWTuser.role == 'admin'
GET /api/v1/sdk-chat/{chat_id}테넌트 JWTuser.role == 'admin'
GET /api/v1/admin/sdk-chat백오피스 JWTROLE_ADMIN
GET /api/v1/admin/sdk-chat/{chat_id}백오피스 JWTROLE_ADMIN
미인가 시 401 / 403.

6. 푸시 / 풀 둘 다 사용하는 권장 패턴

[페이지 진입]
  ├─ GET /api/v1/sdk-chat?page=0  → 초기 리스트 렌더
  └─ EventSource(/events/stream)  → 이후 변경 사항 실시간 반영
      ├─ chat_completed  → 해당 row 만 GET /{chat_id} 로 fresh detail 갱신
      └─ backlist_triggered  → 토스트 / 지도 마커 등 즉시 표시