# API 명세 Base URL: `/api` ## 인증 ### POST /auth/login 로그인 (JWT 토큰 발급) ### GET /auth/me 현재 사용자 정보 (인증 필요) --- ## 멤버 ### GET /members 멤버 목록 조회 ### GET /members/:id 멤버 상세 조회 --- ## 앨범 ### GET /albums 앨범 목록 조회 ### GET /albums/:id 앨범 상세 조회 --- ## 일정 ### GET /schedules 일정 조회 **Query Parameters:** - `year`, `month` - 월별 조회 - `startDate` - 시작 날짜 (YYYY-MM-DD), 다가오는 일정 조회 - `search` - 검색어 (Meilisearch 사용) - `offset`, `limit` - 페이징 ※ `search`, `startDate`, `year/month` 중 하나는 필수 **월별 조회 응답:** ```json { "2026-01-18": { "categories": [ { "id": 2, "name": "유튜브", "color": "#ff0033", "count": 3 } ], "schedules": [ { "id": 123, "title": "...", "time": "19:00:00", "category": { "id": 2, "name": "유튜브", "color": "#ff0033" }, "source": { "name": "fromis_9", "url": "https://www.youtube.com/watch?v=VIDEO_ID" } } ] } } ``` **source 객체 (카테고리별):** - YouTube (category_id=2): `{ name: "채널명", url: "https://www.youtube.com/..." }` - X (category_id=3): `{ name: "", url: "https://x.com/realfromis_9/status/..." }` (name 빈 문자열) - 기타 카테고리: source 없음 **다가오는 일정 응답 (startDate):** ```json [ { "id": 123, "title": "...", "date": "2026-01-18", "time": "19:00:00", "category_id": 2, "category_name": "유튜브", "category_color": "#ff0033", "members": [{ "name": "송하영" }] } ] ``` ※ 멤버가 5명 이상이면 `[{ "name": "프로미스나인" }]` 반환 **검색 응답:** ```json { "schedules": [ { "id": 123, "title": "...", "datetime": "2026-01-18T19:00:00", "category": { "id": 2, "name": "유튜브", "color": "#ff0033" }, "source": { "name": "fromis_9", "url": "https://..." }, "members": ["송하영"], "_rankingScore": 0.95 } ], "total": 100, "offset": 0, "limit": 20, "hasMore": true } ``` ### GET /schedules/categories 카테고리 목록 조회 **응답:** ```json [ { "id": 1, "name": "기타", "color": "#gray", "sort_order": 0 }, { "id": 2, "name": "유튜브", "color": "#ff0033", "sort_order": 1 } ] ``` ### GET /schedules/:id 일정 상세 조회 ### DELETE /schedules/:id 일정 삭제 (인증 필요) ### POST /schedules/sync-search Meilisearch 전체 동기화 (인증 필요) --- ## 추천 검색어 ### GET /schedules/suggestions 추천 검색어 조회 **Query Parameters:** - `q` - 검색어 (2자 이상) - `limit` - 결과 개수 (기본 10) **응답:** ```json { "suggestions": ["송하영", "송하영 직캠", "하영"] } ``` --- ## 관리자 - 봇 관리 (인증 필요) ### GET /admin/bots 봇 목록 조회 **응답:** ```json [ { "id": "youtube-fromis9", "name": "fromis_9", "type": "youtube", "status": "running", "last_check_at": "2026-01-18T10:30:00Z", "last_added_count": 2, "schedules_added": 150, "check_interval": 2, "error_message": null, "enabled": true } ] ``` ### POST /admin/bots/:id/start 봇 시작 ### POST /admin/bots/:id/stop 봇 정지 ### POST /admin/bots/:id/sync-all 전체 동기화 (모든 영상/트윗 수집) **응답:** ```json { "success": true, "addedCount": 25, "total": 100 } ``` ### GET /admin/bots/quota-warning YouTube API 할당량 경고 조회 **응답:** ```json { "active": true, "message": "YouTube API 할당량 초과", "timestamp": "2026-01-18T10:00:00Z" } ``` ### DELETE /admin/bots/quota-warning 할당량 경고 해제 --- ## 관리자 - YouTube (인증 필요) ### GET /admin/youtube/video-info YouTube 영상 정보 조회 **Query Parameters:** - `url` - YouTube URL (watch, shorts, youtu.be 모두 지원) **응답:** ```json { "videoId": "abc123", "title": "영상 제목", "channelId": "UCxxx", "channelName": "채널명", "date": "2026-01-19", "time": "15:00:00", "videoType": "video", "videoUrl": "https://www.youtube.com/watch?v=abc123" } ``` ### POST /admin/youtube/schedule YouTube 일정 저장 **Request Body:** ```json { "videoId": "abc123", "title": "영상 제목", "channelId": "UCxxx", "channelName": "채널명", "date": "2026-01-19", "time": "15:00:00", "videoType": "video" } ``` ### PUT /admin/youtube/schedule/:id YouTube 일정 수정 (멤버, 영상 유형) **Request Body:** ```json { "memberIds": [1, 2, 3], "videoType": "video" } ``` ※ `videoType`: "video" 또는 "shorts" --- ## 관리자 - X (인증 필요) ### GET /admin/x/post-info X 게시글 정보 조회 (Nitter 스크래핑) **Query Parameters:** - `postId` - 게시글 ID (필수) - `username` - 사용자명 (기본: realfromis_9) **응답:** ```json { "postId": "1234567890", "username": "realfromis_9", "text": "게시글 전체 내용", "title": "첫 문단 (자동 추출)", "imageUrls": ["https://pbs.twimg.com/media/..."], "date": "2026-01-19", "time": "15:00:00", "postUrl": "https://x.com/realfromis_9/status/1234567890", "profile": { "displayName": "프로미스나인 (fromis_9)", "avatarUrl": "https://..." } } ``` ### POST /admin/x/schedule X 일정 저장 **Request Body:** ```json { "postId": "1234567890", "title": "게시글 제목", "content": "게시글 내용", "imageUrls": ["https://..."], "date": "2026-01-19", "time": "15:00:00" } ``` --- ## 헬스 체크 ### GET /health 서버 상태 확인 --- ## API 문서 ### GET /docs Scalar API Reference UI ### GET /docs/json OpenAPI JSON 스펙