콘텐츠로 이동

API 엔드포인트

모든 API는 /procedure-hub prefix.

응답 유지 원칙

기존 endpoint의 최상위 키·필드명·조건부 생략은 소비자 계약이다. 공통 {data, code, meta} envelope를 덧씌우지 않는다. Pydantic은 기존 형태를 검증하는 데 사용하며 alias가 있는 응답은 원래 JSON 키로 직렬화한다. null과 키 생략은 구분하고 exclude_none은 해당 endpoint의 계약에 맞게 적용한다. taxonomy·products·extracted처럼 동적 구조인 응답을 형식 통일을 위해 고정 DTO로 바꾸지 않는다.

합병증 조회의 indication이 없으면 공통 항목과 비-indication 항목을 반환한다. 지정하면 공통 항목과 해당 indication 항목만 반환한다. 다른 부위의 항목을 섞지 않는다.

Swagger / OpenAPI

  • 로컬 Swagger UI: http://localhost:8005/procedure-hub/api-docs
  • 로컬 OpenAPI JSON: http://localhost:8005/procedure-hub/openapi.json
  • STG Swagger UI: https://api-stg-csp.medisolveai.com/procedure-hub/api-docs (다음 Backend 배포 후 노출 확인)

Swagger 설명은 BAY/SAY와 같은 방식으로 backend/app/swagger_docs/에 분리하고 router decorator에서 연결한다. 각 operation의 실제 request/response schema는 Pydantic model, 공개 구조 불변 여부는 backend/tests/test_public_api_contract.py가 소유한다.

공개 계약 기준선 (2026-09-03)

등록된 FastAPI 공개 operation 42개를 현재 계약으로 동결한다. URL, method, parameter, request body, status와 response schema는 승인 없이 변경하지 않는다. 구조적 기준선은 backend/tests/test_public_api_contract.py의 단일 table-driven gate가 소유하고, 실제 대표 응답 값은 기존 router snapshot test가 소유한다.

Surface Operation 수 Semantic 분류 현재 확인된 소비자
/health, /health/config 2 read 배포·운영 probe
/api/v1/{taxonomy,...,treatment-sequence} 23 read CHARTY 4개, Linky 4개, Procedure Hub 임상 조회
/api/v1/terminology/* GET 2 read 저장소 내부 호출자 없음
/api/v1/glossary* GET 4 read Procedure Hub glossary 화면·BFF
/api/v1/knowledge/retrieve POST 1 read Procedure Hub 범용 지식 검색 소비자
/api/v1/terminology/* PUT·DELETE 8 write 저장소 내부 호출자 없음; legacy admin surface 유지
/api/v1/glossary/upload POST 1 preview=read, apply=write Procedure Hub upload dialog·BFF
/api/v1/glossary/versions/{id}/rollback POST 1 write Procedure Hub version panel·BFF

HTTP method와 semantic write 여부는 같지 않다. Knowledge Retrieval POST와 glossary upload preview는 상태를 바꾸지 않는다. Glossary upload apply, rollback과 terminology PUT·DELETE만 DB 상태를 변경한다.

Write 보호 책임

  • 기존 FastAPI admin write의 인증·인가는 Gateway가 소유하고 BE router는 직접 인증하지 않는 현재 저장소 규칙을 유지한다.
  • 실제 Gateway 차단 동작은 저장소 코드만으로 증명할 수 없으므로 STG 배포 gate에서 허용·거부 요청으로 검증한다.
  • 현재 glossary Next BFF는 payload와 content-type만 전달하며 X-Uploader 감사 헤더는 전달하지 않는다. 인증 주체와 actor 전달은 Gateway 검증과 함께 보완한다.
  • terminology write는 저장소 정적 검색상 실제 FE caller가 없다. 계약은 보존하되 새 화면이 사용하기 전 admin caller와 actor 전달 방식을 먼저 확정한다.
  • Next PUT /api/taxonomy는 FastAPI operation에 포함되지 않던 무보호 legacy 경로였고 checkpoint C2에서 화면 caller와 함께 제거했다. 분류 화면은 read-only이며, 향후 편집은 DB의 초안·검토·게시·감사를 소유하는 Backend Application Service 없이 재도입하지 않는다.

현재 소비자 근거와 전환 상태는 Canonical 데이터·API 호환·RAG 전달이 소유한다.

Procedure Hub 화면용 Next BFF

화면은 같은 origin의 /api/{endpoint}를 호출하고, Next route는 PROCEDURE_API_BASE의 FastAPI /procedure-hub/api/v1/{endpoint} 응답 상태와 JSON 본문을 그대로 전달한다. 로컬 기본 Backend 주소는 http://localhost:8005다.

C3에서 기존 DB endpoint 11개를, C4에서 anatomy-danger-zones, consent-checklist, market-pricing, patient-education, pih-risk, post-procedure-timeline, procedure-comparison, treatment-optimization, treatment-sequence 9개를 DB-backed compatibility proxy로 전환했다. Backend 연결 실패는 502 {"error":"Procedure API 연결에 실패했습니다."}로 반환한다. 두 단계 모두 기존 Next URL과 응답 본문을 유지하며, 잔여 runtime file route는 extracted와 UI i18n이다.

Health

GET /procedure-hub/health

응답:

{
  "status": "ok",
  "timestamp": "2026-04-15T05:00:00.000000+00:00"
}


핵심 API (CHARTY 사용)

이 4개 엔드포인트는 공통으로 optional lang query param 을 지원한다 (PHUB-WP-005, commit feb3d2f). 자세한 동작은 아래 다국어(lang) 응답 섹션 참조.

GET /procedure-hub/api/v1/taxonomy

시술 분류 체계. 키워드 감지, 시술 상세 정보에 사용.

Query Parameters

param type default required 비고
lang string ko optional 응답 다국어 — ko / en / ja / zh / yue / th / vi 중 택1. 미지정 또는 미지원 값 = ko fallback. i18n 미적재 도메인은 ko fallback (COALESCE 자연 처리).
  • GET /procedure-hub/api/v1/taxonomy → ko 응답
  • GET /procedure-hub/api/v1/taxonomy?lang=zh → 중국어 응답 (modality 17×7 / problem 14×7 / subcategory 3×7 적재 완료)

products[].id (PLAN-009, CHARTY glossary 조인 키)

modality[].products[] 각 항목에 결정적 공개 id 노출 (additive — 기존 키 불변).

  • 형식: {modality_id}-P-{n} (예: M1-P-0). n 은 modality 내 product 위치(sort_order).
  • 결정적: modality_id + 위치에서 산출 → 재시드/환경(stg·prod) 무관하게 동일. DB autoincrement PK 는 노출하지 않음 (재시드 시 변동 가능).
  • lang 무관 동일: ?lang=ja 와 ?lang=ko 응답에서 동일 product 는 동일 id → CHARTY 가 {ja_name: ko_name} 용어집을 id 로 조인 가능.
  • item id(M1-2-1)와 -P- 인픽스로 네임스페이스 분리 (flat {node_id: name} 충돌 방지).
  • ⚠️ 이 id 는 CHARTY glossary 조인 전용. i18n CRUD(PUT/DELETE)는 terminology 엔드포인트의 products[].id(DB int) 사용 — 별개 키.

GET /procedure-hub/api/v1/combo-recipes

원장 검증 시술 조합 프리셋. AI 추천 컨텍스트에 사용.

Query Parameters

param type default required 비고
lang string ko optional taxonomy 와 동일. 현재 i18n row 0 → 모든 lang 에서 ko fallback.

GET /procedure-hub/api/v1/synergy

시술 간 시너지 관계 (116개 링크). AI 추천 컨텍스트에 사용.

Query Parameters

param type default required 비고
lang string ko optional taxonomy 와 동일. 현재 i18n row 0 → 모든 lang 에서 ko fallback.

GET /procedure-hub/api/v1/problem-combos

고민별 시술 패키지 (tier별).

Query Parameters

param type default required 비고
lang string ko optional taxonomy 와 동일. i18n 테이블 신설(alembic 0034)되었으나 row 0 → 현재 ko fallback.

다국어(lang) 응답 (CHARTY 사용 4 endpoint)

위 4개 엔드포인트(taxonomy / combo-recipes / synergy / problem-combos)는 optional lang query param 으로 다국어 응답을 지원한다. additive 변경 — 응답 스키마/키 불변, 기존 호출 영향 0 (CHARTY breaking 0).

지원 언어

ko(기본) / en / ja / zh / yue / th / vi — 7종.

폴백 정책

  • 미지정: lang 생략 = ko → 기존 응답과 byte-identical.
  • 미지원 값: 예 ?lang=xx = ko fallback.
  • i18n miss: i18n 미적재 도메인/row 는 ko 원문 유지 (DB LEFT JOIN + COALESCE 로 자연 처리).
  • 응답 스키마/키 불변: 적재된 도메인만 해당 언어 값으로 치환, 미적재는 ko 그대로.
  • Accept-Language 헤더 미지원 — query param 만 지원 (PHUB-SPEC-052 결정).

도메인별 i18n 적재 현황 (2026-06-05 기준)

endpoint i18n 적재 상태 ?lang=zh 응답
/procedure-hub/api/v1/taxonomy ✅ 적재 완료 (modality 17×7 / problem 14×7 / subcategory 3×7) 다국어 응답 활성
/procedure-hub/api/v1/synergy ❌ i18n row 0 (번역 원천 부재, 게이트 2 후속) ko fallback
/procedure-hub/api/v1/combo-recipes ❌ i18n row 0 (동상) ko fallback
/procedure-hub/api/v1/problem-combos ❌ i18n 테이블 신설(alembic 0034)만, row 0 ko fallback

참조 (정책 SoT)

  • PHUB-SPEC-052 — i18n 정책 (R5: query param 단일 방식, ko fallback).
  • PHUB-SPEC-050 — charty-consumer-contract (draft, 본 lang 정책 환류 예정).
  • CHARTY-DEC-039 — CHARTY consumer 활용 정책.

추가 API

GET /procedure-hub/api/v1/products

제품-제조사 매핑 (60개).

GET /procedure-hub/api/v1/problem-packages

고민별 상담 패키지 (CC 레벨).

GET /procedure-hub/api/v1/complications

합병증 정보.

GET /procedure-hub/api/v1/contraindications

금기사항.

DB-backed 임상 reference read

다음 endpoint는 C4에서 normalized DB projection으로 전환했으며, 전환 전 JSON의 최상위·중첩 응답 형태와 조건부 키를 그대로 유지한다.

  • GET /procedure-hub/api/v1/anatomy-danger-zones
  • GET /procedure-hub/api/v1/consent-checklist
  • GET /procedure-hub/api/v1/market-pricing
  • GET /procedure-hub/api/v1/patient-education
  • GET /procedure-hub/api/v1/pih-risk
  • GET /procedure-hub/api/v1/post-procedure-timeline
  • GET /procedure-hub/api/v1/procedure-comparison
  • GET /procedure-hub/api/v1/treatment-optimization
  • GET /procedure-hub/api/v1/treatment-sequence

Knowledge Retrieval API

POST /procedure-hub/api/v1/knowledge/retrieve

현재 published canonical content release만 조회해 질의와 관련된 전체 PHub 지식 항목을 반환하는 API다. 호출자가 미리 분야나 화면 section을 선택할 필요가 없다.

요청:

{
  "query": "보톡스와 필러를 같이 해도 돼?",
  "lang": "ko",
  "max_results": 40,
  "cursor": null
}
  • query만 필수이며 1~500자다.
  • 공개 request에 domain·section filter를 두지 않고 전체 게시 domain을 검색한다.
  • max_results는 1~200이며, 잘린 결과는 같은 query·release에 묶인 cursor로 이어서 조회한다.
  • 안전·합병증 질의의 구조화 규칙은 검색 점수와 무관하게 강제로 합류한다.

응답 status:

값 의미
ok 같은 release에서 관련 지식을 정상 조회함
no_match 게시 지식에서 관련 항목을 찾지 못함
needs_clarification alias 후보가 복수여서 임의 확정하지 않음
partial 관련 항목은 있으나 필수 안전 규칙 또는 언어 특화가 일부 부족함
unavailable published canonical release가 없어 draft를 노출하지 않음
error 요청을 평가하지 못함

응답에는 interpretation, 공통 items, sources, safety, 전체 domain의 coverage, retrieval, limitations, data_revision이 포함된다. data_revision은 release_id, release version, published_at으로 구성되며, 서로 다른 release의 row를 한 응답에 섞지 않는다. evidence는 approved claim과 현재 statement version의 verified verification, 검증된 identifier를 모두 요구한다.

로컬 조회 화면은 http://localhost:3001/knowledge-retrieval이며, Next BFF POST /api/v1/knowledge/retrieve가 위 FastAPI 응답을 상태와 본문 변경 없이 전달한다.


Linky WP-010 prefill API (신규)

GET /procedure-hub/api/v1/extracted

17 modality별 최신 immutable legacy ContentRevision.snapshot을 {"M1": {...}, "M2": {...}, ...} dict로 반환한다. Linky CatalogResource.EXTRACTED 계약을 유지하며 runtime 파일을 읽지 않는다. Procedure Hub의 Next /api/extracted는 기존 화면 계약인 17개 배열로만 변환한다.

GET /procedure-hub/api/v1/procedure-profiles

시술별 소요시간, 전처치, 사후관리 프로파일. DB compatibility projection. Linky CatalogResource.PROCEDURE_PROFILES 출처.

GET /procedure-hub/api/v1/pre-procedure-checklist

시술 전 공통·카테고리별 체크리스트. DB compatibility projection. Linky CatalogResource.PRE_PROCEDURE_CHECKLIST 출처. universal_checks 12항목.


용어 사전 (terminology) API — 편집기 전용 (PHUB-WP-008)

원장 편집기의 용어 사전 탭 전용. 계층 번역 매트릭스 GET + 레벨별 번역 CRUD.

  • 데이터 소스 = DB (PHUB-SPEC-054 / PHUB-DEC-003). overlay JSON 폐기.
  • CHARTY /taxonomy 와 동일 i18n 테이블 = 단일 소스 — 용어 편집 결과가 곧 CHARTY 다국어 응답에 반영.
  • 라우터는 write 권한을 직접 검증하지 않는다. Gateway 설정에 따른 노출 범위와 운영 조치는 배포 가이드를 따른다.
  • 지원 lang = ko / en / ja / zh / yue / th / vi (7종, taxonomy 와 동일).

셀(cell) 구조

매트릭스의 각 언어 셀 = { name, source, editable }.

source 의미 editable
column 원천 컬럼값 ko = false (편집 거부) / en = true (편집 시 i18n 오버레이 생성)
i18n i18n 테이블 적재 번역 true
missing 미적재 (name: null) true

GET /procedure-hub/api/v1/terminology/matrix

modality + subcategory + product + 용도별 item 계층 번역 매트릭스 (DB 단일 소스).

응답:

{
  "langs": ["ko", "en", "ja", "zh", "yue", "th", "vi"],
  "modalities": [
    {
      "id": "M1",
      "name": "보톡스",
      "name_en": "Botulinum Toxin",
      "cells": { "ko": { "name": "보톡스", "source": "column", "editable": false }, "zh": { "name": null, "source": "missing", "editable": true } },
      "subcategories": [
        { "id": "M1-2", "slug": "by-purpose", "label": "용도별", "cells": { "...": "..." } }
      ],
      "products": [
        { "id": 12, "name": "보툴렉스", "name_en": "Botulax", "cells": { "...": "..." } }
      ],
      "items": [
        { "id": "M1-3-1", "name": "...", "cells": { "...": "..." } }
      ]
    }
  ]
}

  • subcategory 는 같은 ko 라벨끼리 번역을 공유 (slug·ko텍스트 매칭).
  • products[].id = DB int (CRUD path 에 그대로 사용).

GET /procedure-hub/api/v1/terminology/modality

modality × 언어 시술명 매트릭스 (하위호환, PLAN-006). 계층 없는 modality-only. 신규 사용은 matrix 권장.

레벨별 번역 CRUD (DB write)

Method · Path 테이블 id 타입
PUT · DELETE /api/v1/terminology/modality/{modality_id}/{lang} modality_i18n str (예: M1)
PUT · DELETE /api/v1/terminology/subcategory/{subcategory_id}/{lang} subcategory_label_i18n str (예: M1-2)
PUT · DELETE /api/v1/terminology/product/{product_id}/{lang} modality_product_i18n int (GET 응답 products[].id)
PUT · DELETE /api/v1/terminology/item/{item_id}/{lang} modality_item_i18n str (예: M1-3-1)
  • PUT body = { "name": "..." }, 응답 = { "level", "id", "lang", "cell" }.
  • DELETE 응답 = { "level", "id", "lang", "deleted": true }.

검증 / 에러

상황 status
ko(원천) 편집·삭제 400
미지원 lang 400
없는 id 404
이미 없는 번역 재DELETE 404
product id non-int 422
빈 name (min_length=1) 422

엔드포인트 요약

엔드포인트 설명 CHARTY 사용 Linky 사용 ?lang=
GET /procedure-hub/health 헬스 체크 - - -
GET /procedure-hub/api/v1/taxonomy 시술 분류 체계 (modality.name 필드 포함) ✅ ✅ ✅ 적재 완료
GET /procedure-hub/api/v1/combo-recipes 시술 조합 레시피 ✅ - ⚠️ param 지원 / row 0 (ko fallback)
GET /procedure-hub/api/v1/synergy 시너지 관계 ✅ - ⚠️ param 지원 / row 0 (ko fallback)
GET /procedure-hub/api/v1/problem-combos 고민별 조합 ✅ - ⚠️ param 지원 / row 0 (ko fallback)
GET /procedure-hub/api/v1/products 제품 매핑 - - -
GET /procedure-hub/api/v1/problem-packages 고민별 패키지 - - -
GET /procedure-hub/api/v1/complications 합병증 - - -
GET /procedure-hub/api/v1/contraindications 금기사항 - - -
POST /procedure-hub/api/v1/knowledge/retrieve published canonical 범용 지식 검색 - - body lang
GET /procedure-hub/api/v1/extracted 17 modality extracted dict - ✅ -
GET /procedure-hub/api/v1/procedure-profiles 시술 프로파일 - ✅ -
GET /procedure-hub/api/v1/pre-procedure-checklist 시술 전 체크리스트 - ✅ -
GET /procedure-hub/api/v1/terminology/matrix 용어 사전 계층 번역 매트릭스 (편집기 전용, +레벨별 CRUD) - - 7종