6.1 KiB
6.1 KiB
API_CONTRACT — MVP 엔드포인트 8개
단일 진실 소스. 프런트(infinith-web) ↔ 백엔드(infinith-api) 간 계약.
변경 절차:
- 이 문서 수정
app/schemas/*.py+app/routers/*.py구현 변경GET /openapi.json결과를 PR 에 diff 로 첨부- 프런트
npx openapi-typescript로 타입 재생성 - 양쪽 PR 크로스 리뷰 후 머지
공통 사항
- Base URL (dev):
http://localhost:8000 - Base URL (staging/prod): Railway 배포 후 확정
- 인증: 모든 엔드포인트
X-API-Key: <secret>헤더 필수 (MVP)- 추후 OAuth/JWT 전환 예정 — 현재는
.env의API_KEY값과 대조
- 추후 OAuth/JWT 전환 예정 — 현재는
- 콘텐츠 타입:
application/json - 시간: 전부 ISO 8601 UTC (예:
2026-04-20T09:00:00Z) - UUID: 모두 UUID v4
1. POST /api/clinics — 병원 등록
Request
{
"url": "https://www.banobagi.com",
"name": "바노바기성형외과",
"name_en": "BANOBAGI",
"address": "서울시 강남구 논현로 842"
}
Response 201 Created
{
"id": "11111111-1111-1111-1111-111111111111",
"url": "https://www.banobagi.com",
"name": "바노바기성형외과",
"created_at": "2026-04-20T09:00:00Z"
}
Error
409— 동일 URL 병원 이미 존재
2. POST /api/analyses — 분석 시작 (MVP 핵심)
Request
{
"clinic_id": "11111111-1111-1111-1111-111111111111",
"channels": {
"youtube": "@banobagi",
"instagram": ["@banobagi_official"],
"facebook": "banobagiofficial",
"naver_blog": "https://blog.naver.com/banobagi",
"gangnam_unni": "https://www.gangnamunni.com/hospital/1234"
},
"options": {
"skip_vision": false,
"skip_perplexity": false
}
}
clinic_id대신url만 제공 시, 서버가clinic_service.upsert_by_url()로 자동 생성- 채널 필드는 전부 선택적 — 최소 1개 이상만 제공되면 OK
instagram은 여러 계정 가능 (예: 본원 + 분원)
Response 202 Accepted
{
"analysis_run_id": "22222222-2222-2222-2222-222222222222",
"clinic_id": "11111111-1111-1111-1111-111111111111",
"status": "discovering",
"estimated_seconds": 90,
"poll_url": "/api/analyses/22222222-2222-2222-2222-222222222222/status"
}
Error
404—clinic_id존재 X422— 채널 하나도 제공 안됨
3. GET /api/analyses/{run_id}/status — 진행 상태 폴링
Response 200 OK
{
"analysis_run_id": "22222222-2222-2222-2222-222222222222",
"status": "collecting",
"progress": 0.45,
"current_step": "채널 데이터 수집 중",
"channel_errors": {
"gangnam_unni": "로그인 벽으로 스크래핑 실패"
},
"completed_at": null
}
Status lifecycle
pending → discovering → collecting → generating → complete
↘ partial (일부 채널 실패)
↘ error (치명적 실패)
Frontend 폴링 가이드
status ∈ {complete, partial, error}일 때까지 2초 간격 폴링complete또는partial→GET /api/reports/{run_id}로 이동error→channel_errors._pipeline에 원인 메시지
4. GET /api/reports/{run_id} — 리포트 조회
Response 200 OK
src/types/report.ts 의 MarketingReport 타입과 100% 호환 JSON. 프런트는 이 응답을 transformReport.ts 에 전달.
{
"id": "22222222-...",
"clinic": {
"name": "바노바기성형외과",
"url": "https://www.banobagi.com"
},
"overall_score": 82,
"youtube": { ... },
"instagram": { ... },
"facebook": { ... },
"naver_place": { ... },
"naver_blog": { ... },
"gangnam_unni": { ... },
"conversion_strategy": { ... },
"roadmap": [ ... ],
"kpis": [ ... ],
"generated_at": "2026-04-20T09:01:30Z"
}
Error
404— run 존재 X409— 아직complete/partial아님 (status: collecting등)
5. POST /api/plans — 콘텐츠 기획 생성
Request
{
"report_id": "22222222-...",
"regenerate": false
}
regenerate=false(기본) — 기존 플랜 있으면 그대로 반환regenerate=true— 강제로 새 플랜 생성
Response 201 Created (신규) or 200 OK (기존)
{
"id": "33333333-...",
"analysis_run_id": "22222222-...",
"brand_guide": { ... },
"channel_strategies": [ ... ],
"content_strategy": { ... },
"calendar": [ ... ],
"created_at": "2026-04-20T09:10:00Z"
}
6. GET /api/plans/{id} — 기획 조회
MarketingPlan 타입 (src/types/plan.ts) 반환. 응답 구조는 5번과 동일.
7. GET /api/clinics/{id}/history — 분석 이력
Response 200 OK
{
"clinic_id": "11111111-...",
"runs": [
{
"run_id": "22222222-...",
"status": "complete",
"started_at": "2026-04-20T09:00:00Z",
"completed_at": "2026-04-20T09:01:30Z",
"overall_score": 82
}
],
"metrics_timeseries": {
"youtube_subscribers": [
{"date": "2026-04-20", "value": 12345},
{"date": "2026-05-20", "value": 13200}
]
}
}
8. POST /api/channels/verify — 핸들 실시간 검증
입력 폼의 "이 계정이 맞나요?" 버튼용.
Request
{
"youtube": "@banobagi",
"instagram": ["@banobagi_official"]
}
Response 200 OK
{
"youtube": {
"handle": "@banobagi",
"verified": true,
"display_name": "바노바기 BANOBAGI",
"followers": 12345
},
"instagram": [
{
"handle": "@banobagi_official",
"verified": "unverifiable",
"note": "Instagram 로그인 벽"
}
]
}
verified: true— 존재 확인verified: false— 404/미존재verified: "unverifiable"— 로그인 벽 등으로 확인 불가 (UI는 경고만, 진행 허용)
Out of scope (post-MVP)
- 결제 / 구독
- 경쟁사 분석 (자동 추천)
- URL 자동 발견 (홈페이지 크롤링 기반)
- 콘텐츠 스튜디오 API (이미지 생성, 캡션 생성)
- 성과 분석 / 스케줄링 자동 배포
- 팀/조직/권한 관리