chart-api
vet-report 스펙과 동일한 HTTP API입니다. 파트너 연동·리뷰용 상세 문서는 저장소 PARTNER_REVIEW.md 를 참고하고, 이 페이지와 /api/openapi (OpenAPI 3 JSON)로 동일 계약을 기계가 읽을 수 있습니다.
인증
대부분: Authorization: Bearer <CHART_APP_API_KEY>
- 공개:
GET/PATCH …/review-share— 리뷰 토큰만 검증 (차트 앱 키 불필요). - 공유 PDF:
POST …/export-by-share— 바디token만 (Bearer 금지). 인쇄 페이지 URL이 서버에서 만들어지지 않으면 503 (MISSING_PRINT_URL). - 크론:
CRON_SECRET이 설정된 경우Authorization: Bearer <CRON_SECRET>. Vercel Cron은 기본 헤더가 없으므로 호출 방식을 맞추거나 시크릿 없이 운영하지 않도록 설정해야 합니다.
오류 응답
클라이언트 오류는 4xx, 서버·미구현·키 누락은 보통 503 과 JSON 안내 메시지입니다. 연동 시에는 503 본문을 로깅해 두면 포팅 일정 공유에 도움이 됩니다.
Storage 버킷
고정: PDF pdf-uploads, 병원 에셋 hospital-assets. PDF 객체 경로는 extract-uploads/YYYY-MM-DD/<uuid>-<파일명>.pdf 형태입니다.
케이스 이미지: 기본 버킷명 case-image — 통합 인프라에서 이름을 바꿀 때는 환경 변수 SUPABASE_IMAGE_CASE_BUCKET 로 맞춥니다. 브라우저에서 서명 URL로 직접 PUT 하는 경우 Supabase CORS 설정이 필요할 수 있습니다.
서명·공유 TTL (현재 구현)
| 용도 | TTL |
|---|---|
| 케이스 이미지 미리보기 서명 URL | 7일 |
| 병원 로고·직인 업로드 후 서명 URL | 1년 |
| 건강검진 리뷰 공유 링크(토큰 만료) | 발급 후 7일 |
| PDF 업로드 서명 URL | Supabase 제품 정책(별도 상한 합의 권장) |
curl 예시
$BASE를 배포 URL(예: https://your-app.vercel.app)로 바꿉니다.
# OpenAPI 스펙 받기 (인증 불필요) curl -s "$BASE/api/openapi" | jq . # 인증 필요 예시 (헬스성 목록 — 실제 파라미터는 스펙·구현 참고) curl -sS -H "Authorization: Bearer YOUR_CHART_APP_API_KEY" "$BASE/api/history"
서버 환경 변수 요약
| 변수 | 역할 |
|---|---|
DATABASE_URL | Postgres (Pooling URL 권장) |
NEXT_PUBLIC_SUPABASE_URL | Supabase 프로젝트 URL |
SUPABASE_SERVICE_ROLE_KEY | Storage·서버측 Supabase API |
SUPABASE_PDF_UPLOADS_BUCKET | PDF 업로드 Storage 버킷명 (기본 pdf-uploads, 대시보드에서 생성) |
CHART_APP_API_KEY | 파트너 Bearer 토큰과 동일하게 설정 |
GEMINI_API_KEY | LLM 라우트 (없으면 해당 POST 503) |
GEMINI_MODEL | Gemini 모델 ID (선택, 기본 gemini-2.0-flash) |
HEALTH_CHECKUP_PRINT_URL_TEMPLATE | run 인쇄 URL ({runId}) — 예: …/runs/{runId}/report/print |
HEALTH_CHECKUP_PRINT_BASE_URL | run 인쇄 베이스 + /runId |
HEALTH_CHECKUP_SHARE_PRINT_URL_TEMPLATE | 공유 PDF ({token}) — export-by-share, runId와 별도 |
VET_REPORT_PUBLIC_ORIGIN | run: …/runs/…/report/print, share: …/review/health-checkup/…/print 기본 조합 |
VET_REPORT_HEALTH_PRINT_SUBPATH | 선택, run 경로 오리진+sub 오버라이드 |
VET_REPORT_HEALTH_SHARE_PRINT_SUBPATH | 선택, 기본 review/health-checkup (share) |
PLAYWRIGHT_PDF_SERVICE_URL | 선택, 있으면 원격 PDF 우선 (미설정 시 인프로세스 Chromium) |
PLAYWRIGHT_PDF_SERVICE_SECRET | 선택, 원격 PDF Bearer |
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH | 로컬 개발용 시스템 Chrome 경로 (Vercel은 보통 비움) |
CHART_APP_SHARE_PUBLIC_BASE_URL | 리뷰 공유 URL 접두사 (선택) |
SUPABASE_IMAGE_CASE_BUCKET | 케이스 이미지 버킷명 (선택, 기본 case-image) |
IMAGE_CASE_MAX_EDGE | 케이스 WebP 리사이즈 최대 변 px (선택, 기본 2048) |
IMAGE_CASE_WEBP_QUALITY | 케이스 WebP 품질 1–100 (선택, 기본 82) |
CRON_SECRET | 크론 라우트 보호 (선택) |
CHART_APP_DEBUG_RAW_PAYLOAD | 히스토리 디버그 (선택, 1 또는 true) |
파트너 체크리스트 · 프록시 (vet-report)
- 동일 키: Chart API
CHART_APP_API_KEY= vet-report 프록시가 붙이는 Bearer 값. - 예외: 리뷰 공개
GET/PATCH …/review-share, 공유 PDFPOST …/export-by-share는 Bearer를 붙이지 않음 (토큰만). - 리뷰 링크 발급
POST …/review-share는 Bearer 필요. - DB·Supabase: 동일 프로젝트/데이터를 보도록 맞추지 않으면
runId·화면이 어긋날 수 있음 (인쇄 페이지가 Supabase 직접 조회인 경우 특히 합의). - 상세 표·스모크 아이디어는 저장소 PARTNER_REVIEW.md 참고.
PDF (건강검진 export)
- 기본: API 라우트 안에서 playwright-core + @sparticuz/chromium 으로 인쇄 URL을 열어 PDF 생성 (
runtime: nodejs). - Run PDF:
…/runs/<runId>/report/print패턴. 공유 PDF (export-by-share):…/review/health-checkup/<token>/print—runId가 아니라 토큰 경로.HEALTH_CHECKUP_SHARE_PRINT_URL_TEMPLATE또는VET_REPORT_PUBLIC_ORIGIN. PLAYWRIGHT_PDF_SERVICE_URL이 있으면 원격 PDF 서비스 우선 (선택·폴백).- 인쇄 페이지는 공개 접근 가능해야 PDF 렌더가 성공하기 쉬움 (로그인 필수 페이지면 실패 가능).
A. PDF · 텍스트 버킷팅
| 상태 | Method | Path | 설명 | 인증 |
|---|---|---|---|---|
| 동작 | POST | /api/text-bucketing/upload-url | PDF 업로드용 서명 URL 발급signedUrl 은 가능 시 절대 URL · extract-uploads/… · pdf-uploads | Bearer CHART_APP_API_KEY |
| Gemini 필요 | POST | /api/text-bucketing | 텍스트 버킷팅 전체 파이프라인multipart 권장 · 필수 chartType · 병원 UUID는 hospitalId 또는 hospital_id · file 또는 storageBucket+storagePath(pdf-uploads, extract-uploads/) · 선택 chartPasteText·efriendsChartBlocksJson · LLM 미설정 400 · 30MB · runId·friendlyId · 스캔 PDF 422 | Bearer CHART_APP_API_KEY |
B. 런 · 추출 · 평가 · 케이스 이미지
| 상태 | Method | Path | 설명 | 인증 |
|---|---|---|---|---|
| 동작 | PATCH | /api/runs/[runId]/extraction | 추출 결과 섹션별 PATCH | Bearer CHART_APP_API_KEY |
| 혼합(GET 동작 / POST Gemini) | GET, POST | /api/runs/[runId]/assessment | AI 소견 조회 · 생성POST는 GEMINI_API_KEY 필요, 없으면 503 | Bearer CHART_APP_API_KEY |
| 동작 | GET | /api/image-case | 케이스 이미지 목록 + 서명 URL쿼리 runId 필수. 미리보기 서명 TTL 7일. 버킷 SUPABASE_IMAGE_CASE_BUCKET(선택, 기본 case-image) | Bearer CHART_APP_API_KEY |
| 동작 | DELETE | /api/image-case | 이미지 삭제쿼리 runId, imageId | Bearer CHART_APP_API_KEY |
C. 리포트 · 건강검진 PDF
| 상태 | Method | Path | 설명 | 인증 |
|---|---|---|---|---|
| Gemini 필요 | POST | /api/report/generate | 리포트 템플릿 생성(Gemini) | Bearer CHART_APP_API_KEY |
| 혼합(GET 동작 / POST Gemini) | POST | /api/report/export | 리포트 PDF 바이너리POST { printUrl } · 인프로세스 Playwright (원격 URL 있으면 우선) | Bearer CHART_APP_API_KEY |
| Gemini 필요 | POST | /api/report/health-checkup/preview | 건강검진 미리보기(Gemini) | Bearer CHART_APP_API_KEY |
| 혼합(GET 동작 / POST Gemini) | GET, POST | /api/report/health-checkup/export | 건강검진 PDFGET ?runId=&exportRequestId= · POST JSON 또는 form(runId, exportRequestId) · 상관 ID: 헤더 X-Chart-Export-Request-Id 우선 · Playwright · export-debug | Bearer CHART_APP_API_KEY |
| 동작 | POST | /api/report/health-checkup/export-debug | 건강검진 PDF export 진단(JSON)Bearer 필수 · { runId, probePrintUrl? } · 환경 플래그·인쇄 URL fetch·비밀값 미포함 · Failed to fetch 원인 좁히기 | Bearer CHART_APP_API_KEY |
| 혼합(GET 동작 / POST Gemini) | POST | /api/report/health-checkup/export-by-share | 공유 토큰으로 PDF토큰 경로 인쇄 URL · SHARE 템플릿 또는 VET_REPORT_PUBLIC_ORIGIN | 토큰(쿼리/바디) |
D. 생성 콘텐츠 · 공유 리뷰
| 상태 | Method | Path | 설명 | 인증 |
|---|---|---|---|---|
| Gemini 필요 | POST | /api/content/generate | health_checkup | blog_post 생성 | Bearer CHART_APP_API_KEY |
| 동작 | GET | /api/content | generated_run_content 목록쿼리 runId | Bearer CHART_APP_API_KEY |
| 동작 | PATCH | /api/content | 콘텐츠 upsert | Bearer CHART_APP_API_KEY |
| 동작 | DELETE | /api/content | 단건 삭제 | Bearer CHART_APP_API_KEY |
| 동작 | POST | /api/content/health-checkup/review-share | 외부 리뷰용 공유 링크 발급 | Bearer CHART_APP_API_KEY |
| 동작 | GET | /api/content/health-checkup/review-share | 토큰으로 페이로드 조회공개 — 쿼리 token | 공개(토큰만 검증) |
| 동작 | PATCH | /api/content/health-checkup/review-share | 토큰으로 검토 반영공개 — 바디에 token | 공개(토큰만 검증) |
| Gemini 필요 | POST | /api/content/reference-extract | 참고문헌 추출multipart file= 또는 JSON · fileName·mimeType·fullText·rows | Bearer CHART_APP_API_KEY |
E. 건강상식 · OCR · 참고문헌
| 상태 | Method | Path | 설명 | 인증 |
|---|---|---|---|---|
| 503(미포팅) | POST | /api/ocr | 범용 OCRVision 미연동 시 503 | Bearer CHART_APP_API_KEY |
| Gemini 필요 | POST | /api/health-knowledge/generate | 건강상식 HTML(Gemini) | Bearer CHART_APP_API_KEY |
F. 히스토리
| 상태 | Method | Path | 설명 | 인증 |
|---|---|---|---|---|
| 동작 | GET | /api/history | 최근 런 목록 · ?runId= 상세 | Bearer CHART_APP_API_KEY |
| 동작 | DELETE | /api/history/[runId] | 런 + 연관 데이터 삭제 | Bearer CHART_APP_API_KEY |
G. 관리자 · 크론
| 상태 | Method | Path | 설명 | 인증 |
|---|---|---|---|---|
| 동작 | GET | /api/admin/hospitals | 병원 목록 | Bearer CHART_APP_API_KEY |
| 동작 | POST | /api/admin/hospitals | 병원 생성 | Bearer CHART_APP_API_KEY |
| 동작 | PATCH | /api/admin/hospitals/[id] | 병원 수정 | Bearer CHART_APP_API_KEY |
| 동작 | DELETE | /api/admin/hospitals/[id] | 병원 삭제 | Bearer CHART_APP_API_KEY |
| 동작 | POST | /api/admin/hospitals/[id]/assets | logo | seal 업로드 | Bearer CHART_APP_API_KEY |
| 동작 | GET | /api/admin/basic-info-normalization | 종·품종 빈도(정규화 통계) | Bearer CHART_APP_API_KEY |
| 동작 | GET, POST | /api/cron/recompute-basic-info-ages | 나이 재계산 크론CRON_SECRET 설정 시 Bearer 필요 | Bearer CRON_SECRET |
로컬 개발 기본 포트는 3003 (npm run dev). 배포 후에는 이 페이지와 /api/openapi가 파트너에게 동일한 정보를 제공합니다. 리뷰용 장문은 PARTNER_REVIEW.md 를 저장소에서 함께 공유하세요.