← 카비네이터로 돌아가기
API DOCS

카비네이터 공개 API

카비네이터 본 서비스가 쓰는 상병 검색/필터링 기능을, 여러분의 앱/스크립트에서 그대로 가져다 쓸 수 있는 외부 개발자용 API입니다. 현재 검색 1개 + 필터링 엔진 2개(근골격·외상 MST / 한방내과)가 열려 있습니다.

1. 개요

Base URLhttps://kavinator.com
인증없음 (누구나 호출 가능)
HTTP 메서드GET
응답 형식application/json; charset=utf-8
CORS전면 허용 (Access-Control-Allow-Origin: *) — 브라우저 JS에서 직접 fetch 가능
호출 제한/api/kcd/public-search는 IP당 초당 5회, /api/kcd/public-mst-filter·/api/kcd/public-internal-filter는 IP당 초당 1회(계산량이 더 많은 필터링 엔진이라 더 낮게 설정)로 제한됩니다. 초과 시 503 응답.
데이터 출처 KCD-9(한국표준질병사인분류) 기반 한의 임상 전용 상병 DB를 조회합니다. 데이터 정제 과정과 출처는 제작 뒷이야기 페이지를 참고해주세요.
응답 계약 안정성 이 문서의 public-* 엔드포인트들은 카비네이터 내부 UI와 계산 로직은 공유하지만, 응답 스키마는 완전히 독립된 별도 계약으로 유지됩니다. 내부 화면이 바뀌어도 여기 문서화된 필드는 예고 없이 바뀌지 않습니다.

2. 상병 검색 — /api/kcd/public-search

검색어(상병코드 또는 상병명)를 넣으면, 관련도 순으로 정렬된 상병 목록을 최대 30건 반환합니다.

GET /api/kcd/public-search?q={검색어}&fields={0~3}

요청 파라미터

이름필수기본값설명
q 필수 - 검색어. 상병코드(예: M54.5, 점 유무 무관)나 상병명 일부(예: 요통)를 모두 지원합니다. 띄어쓰기로 여러 단어를 넣으면 각 단어가 모두 포함된 결과만 매치됩니다.
fields 선택 0 응답에 포함할 필드 선택.
0 = 상병코드 + 상병명 + 청구건수 (기본값)
1 = 상병코드만
2 = 상병명만
3 = 상병명 + 청구건수

응답 필드

필드타입설명
querystring요청한 검색어 원문
countnumber반환된 결과 건수 (최대 30)
resultsarray검색 결과 목록. fields 값에 따라 각 항목에 포함되는 키가 달라집니다.
results[].codestring상병코드 (fields=0 또는 1일 때 포함)
results[].namestring상병명 (fields=0, 2, 3일 때 포함)
results[].claim_countnumber한방(HIRA) 청구건수 — 정렬/참고용 지표이며 양방 청구건수와는 다른 값입니다 (fields=0 또는 3일 때 포함)
참고 검색 결과가 0건이어도 에러가 아니라 {"query": "...", "count": 0, "results": []} 형태로 정상 응답합니다. q를 비워서 보내도 마찬가지입니다.

예제 요청 & 응답

요청: GET /api/kcd/public-search?q=요통&fields=0

{
  "query": "요통",
  "count": 29,
  "results": [
    { "code": "M54.5", "name": "요통", "claim_count": 13179873 },
    { "code": "M54.57", "name": "요통, 요천부", "claim_count": 13179873 },
    { "code": "M54.4", "name": "좌골신경통을 동반한 요통", "claim_count": 2303928 }
    // ... 이하 생략
  ]
}

코드로 호출하기

cURL
JavaScript
Python
curl "https://kavinator.com/api/kcd/public-search?q=요통&fields=0"
fetch('https://kavinator.com/api/kcd/public-search?q=' + encodeURIComponent('요통') + '&fields=0')
  .then(res => res.json())
  .then(data => console.log(data));
import requests

res = requests.get(
    'https://kavinator.com/api/kcd/public-search',
    params={'q': '요통', 'fields': 0}
)
data = res.json()
print(data)

3. 근골격·외상 MST 필터 — /api/kcd/public-mst-filter

5대 대부위 → 발병기전(외상유무) → 세부분절 → 병변조직군 → 청구안전도 순으로 다차원 소거 필터링해 상병 후보군을 반환합니다. 모든 파라미터는 선택이며, 생략하면 해당 단계는 필터 없이 전체를 봅니다. 각 단계의 집계(*_summary)도 함께 내려가므로, 단계형(위저드) UI를 그대로 구현할 수 있습니다.

GET /api/kcd/public-mst-filter?major=&trauma=&sub=&diag=&tissue=&q=&limit=&offset=
major / sub는 정수 코드 가운데점(·)이 섞인 한글 값을 직접 쿼리스트링에 넣는 대신, 정수 코드(0, 1, ...)로 보냅니다. 코드표는 바로 아래 있습니다. 응답의 selected.major/selected.sub에 보낸 코드와 해석된 값이 함께 echo되니 눈으로 바로 확인할 수 있습니다.

요청 파라미터

이름필수기본값설명
major선택(전체) 5대 대부위 정수 코드(0~4). 코드표는 바로 아래 "대부위(major) 코드표" 참고.
trauma선택ALL 발병기전. ALL(전체) · TRAUMA(급성외상, S/T코드) · NON_TRAUMA(만성·퇴행, M코드 등)
sub선택(전체) 세부분절 정수 코드. major 값과 무관하게 항상 전역 고정 번호(코드 하나 = 값 하나) — 단, 선택한 major에 속하지 않는 코드를 같이 보내면 400 에러. 코드표는 바로 아래 "세부분절(sub) 코드표" 참고.
tissue선택(전체) 병변조직군. BONE · SKIN_WOUND · AUTOIMMUNE · TENDON_LIGAMENT · CARTILAGE · DEFORMITY · MUSCLE · NERVE · CRYSTAL · VASCULAR · SUBLUXATION · CLINICAL
diag선택(전체) 청구안전도. CLINICAL(임상단독) · IMAGING(영상 필요) · BLOOD(혈액검사) · SPECIAL(특수검사) · DUAL(복합). 콤마로 복수 지정 가능(예: IMAGING,BLOOD).
q선택- 상병코드/상병명 추가 검색어 (다른 필터와 AND 결합)
limit선택100 반환 건수 (최대 300)
offset선택0 페이지네이션 오프셋

대부위(major) 코드표

코드값
0체간
1상지
2하지
3두경부
4전신·다발

세부분절(sub) 코드표

코드는 major를 지정하든 안 하든 항상 같은 값을 가리킵니다 — "소속 major" 열은 참고용입니다.

코드값소속 major
0목/경추체간, 두경부
1등/흉추체간
2허리/요추체간
3골반·엉치체간
4가슴·갈비뼈체간
5척추 전체·다발체간
6어깨,위팔상지
7팔꿈치,아래팔상지
8손목상지
9손·손가락상지
10팔저림(방사통)상지
11고관절·대퇴하지
12무릎·하퇴하지
13발목·발하지
14다리저림·좌골신경통(방사통)하지
15턱관절두경부
16안면·안면신경두경부
17두부·두통두경부
18두개·안면외상두경부
19전신대사·자가면역·골다공증전신·다발
20다발성·여러부위전신·다발
21전신_기타전신·다발
22기타 외상·독성전신·다발
23상세불명_전신전신·다발
24처치·수술 합병증전신·다발
25다발성 손상전신·다발
26광범위·다발 화상전신·다발
27상세불명 외상전신·다발
28다발·기타 외상 후유증전신·다발

응답 필드

필드타입설명
total_countnumber현재 필터 조건에 맞는 전체 건수 (limit/offset 적용 전)
selectedobject요청에 적용된 필터값 echo. major/sub는 {code, value} 형태(보낸 코드 + 해석된 한글 값), 둘 다 생략 시 null
major_summaryarray대부위별 건수 집계. [{major_part, count}]
trauma_summaryobject발병기전별 건수. {total, trauma, non_trauma}
sub_summaryarray세부분절별 건수 집계. [{sub_part, count}] (major 지정 시에만 채워짐)
tissue_summaryobject병변조직군별 건수. {조직군코드: count}
diag_summaryobject청구안전도별 건수. {청구안전도코드: count}
candidates[]array상병 후보 목록 (아래 필드로 구성)
candidates[].codestring상병코드
candidates[].namestring상병명
candidates[].synonymsstring동의어/영문명 묶음(| 구분)
candidates[].eng_namestring영문명(추출 실패 시 빈 문자열)
candidates[].chapterstring챕터(M/S/T 등)
candidates[].major_partstring대부위
candidates[].sub_partstring세부분절
candidates[].target_tissuestring병변조직군
candidates[].diagnostic_reqstring청구안전도
candidates[].required_teststring요구 검사/진찰 설명(사람이 읽는 문장)
candidates[].claim_countnumber한방 청구빈도 — 정렬/참고용, 양방 값과 다름
candidates[].claim_count_westernnumber양방 청구빈도(참고용)
candidates[].is_primaryboolean이 대부위의 주매핑 코드인지 여부
candidates[].cross_reasonstring|null다른 분과와 이중매핑된 사유(없으면 null)
candidates[].is_site_unspecifiedboolean부위상세불명(모든 대부위 필터에 걸리는) 코드 여부
candidates[].claim_cautionstring청구 유의사항 문구(없으면 빈 문자열)
candidates[].is_cautionboolean청구 유의 플래그
참고 claim_count는 상병 후보의 정렬/강조 전용 지표입니다 — 후보가 적게 나왔다고 정답이 아닌 것은 아니며, 이 API도 카비네이터 본 서비스와 동일하게 "후보 배제 없이 많이 보여주고 최종 선택은 사용자가" 원칙을 따릅니다.
잘못된 파라미터 값 major/sub에 범위를 벗어난 코드(또는 정수가 아닌 값)를 보내면, 빈 결과 대신 400과 함께 전체 코드표가 담긴 에러를 반환합니다: {"error": "유효하지 않은 major 코드: '9'. 허용 코드: 0=체간, 1=상지, ..."}. trauma/tissue/diag는 기존처럼 영문 코드 허용값 목록으로 안내합니다.
major와 sub가 서로 안 맞을 때 sub 코드는 전역 고정이라 그 자체로는 유효해도, major와 함께 보냈는데 그 대부위에 속하지 않는 조합이면 역시 400을 반환합니다 — 예를 들어 major=2(하지)와 sub=28(다발·기타 외상 후유증, 실제로는 major=4 전신·다발 소속)을 같이 보내면:
GET /api/kcd/public-mst-filter?major=2&sub=28

{
  "error": "sub 코드 '28'(다발·기타 외상 후유증)는 major=2(하지)에 속하지 않습니다. major=2에서 허용되는 sub 코드: 11=고관절·대퇴, 12=무릎·하퇴, 13=발목·발, 14=다리저림·좌골신경통(방사통)"
}
이렇게 그 major에서 실제로 쓸 수 있는 sub 코드만 추려서 바로 알려줍니다. (major 없이 sub=28만 단독으로 보내면 정상적으로 200이 반환됩니다.)

코드로 호출하기

cURL
JavaScript
Python
curl "https://kavinator.com/api/kcd/public-mst-filter?major=1&trauma=NON_TRAUMA&tissue=MUSCLE&limit=5"
fetch('https://kavinator.com/api/kcd/public-mst-filter?' + new URLSearchParams({
  major: 1, trauma: 'NON_TRAUMA', tissue: 'MUSCLE', limit: 5
}))
  .then(res => res.json())
  .then(data => console.log(data));
import requests

res = requests.get(
    'https://kavinator.com/api/kcd/public-mst-filter',
    params={'major': 1, 'trauma': 'NON_TRAUMA', 'tissue': 'MUSCLE', 'limit': 5}
)
data = res.json()
print(data)

4. 한방내과 필터 — /api/kcd/public-internal-filter

7대 분과 → 청구안전도 → 세부분절 순으로 소거 필터링해 상병 후보군을 반환합니다.

GET /api/kcd/public-internal-filter?division=&diag=&sub=&q=&limit=&offset=
division / sub는 정수 코드 MST 필터와 동일한 이유로, division/sub는 가운데점(·)이 섞인 한글 값 대신 정수 코드로 보냅니다. 코드표는 바로 아래 있습니다.

요청 파라미터

이름필수기본값설명
division선택0 7대 분과 정수 코드(0~6, 기본 0=소화기계). 코드표는 바로 아래 "분과(division) 코드표" 참고.
diag선택ALL 청구안전도. ALL(전체) · CLINICAL · IMAGING · BLOOD · SPECIAL. 콤마로 복수 지정 가능.
sub선택(전체) 세부분절 정수 코드. division 값과 무관하게 항상 전역 고정 번호 — 단, 선택한 division에 속하지 않는 코드를 같이 보내면 400 에러. 코드표는 바로 아래 "세부분절(sub) 코드표" 참고.
q선택- 상병코드/상병명 추가 검색어
limit선택100 반환 건수 (최대 300)
offset선택0 페이지네이션 오프셋

분과(division) 코드표

코드값
0소화기계
1호흡기계
2피부계
3부인·비뇨생식
4정신·신경
5이비인후·안과
6전신·대사·순환

세부분절(sub) 코드표

코드는 division을 지정하든 안 하든 항상 같은 값을 가리킵니다 — "소속 division" 열은 참고용입니다.

코드값소속 division
0구강·혀·턱소화기계
1위·식도소화기계
2대장·배변소화기계
3항문·치질소화기계
4간·담·췌소화기계
5기타·복벽·흡수소화기계
6치과전문소화기계
7코·비동호흡기계
8인후·편도·후두호흡기계
9기관지·기침호흡기계
10폐·천식·COPD호흡기계
11흉막·간질·기타호흡기계
12습진·아토피·가려움피부계
13두드러기·홍반·건선·주사피부계
14여드름·모낭·피지피부계
15탈모·모발·손발톱피부계
16색소·각화·흉터·티눈피부계
17감염·수포·자가면역·기타피부계
18생리·월경통·PMS부인·비뇨생식
19갱년기·폐경·난임부인·비뇨생식
20자궁·난소·질염·골반부인·비뇨생식
21임신·입덧·산후조리부인·비뇨생식
22방광·요실금·배뇨부인·비뇨생식
23콩팥·전립선·비뇨기타부인·비뇨생식
24수면·불면정신·신경
25화병·우울·불안·스트레스정신·신경
26두통·안면마비·삼차신경정신·신경
27말초신경·저림·손떨림정신·신경
28소아발달·틱·ADHD정신·신경
29퇴행·기질뇌신경정신·신경
30중증정신·기질·중독정신·신경
31이명·난청·귀먹먹이비인후·안과
32어지럼·메니에르·전정이비인후·안과
33외이도·중이염·이관이비인후·안과
34안구건조·눈피로·결막이비인후·안과
35눈꺼풀·다래끼·안과기타이비인후·안과
36만성피로·기허·체력저하전신·대사·순환
37다한증·도한·체온조절전신·대사·순환
38부종·수분대사·어지럼전신·대사·순환
39비만·대사증후군·고지혈전신·대사·순환
40말초순환·혈압·수족냉증전신·대사·순환
41자각증상·호소증상전신·대사·순환
42뇌혈관·중풍전신·대사·순환
43심장질환전신·대사·순환
44기타혈관질환전신·대사·순환
45내분비질환전신·대사·순환
46검사소견·이상소견전신·대사·순환

응답 필드

필드타입설명
total_countnumber현재 필터 조건에 맞는 전체 건수
selectedobject요청에 적용된 필터값 echo. division/sub는 {code, value} 형태, sub 생략 시 null
division_summaryarray7대 분과별 건수·아이콘·설명(고정 메타데이터)
diag_summaryobject청구안전도별 건수. {청구안전도코드: count}
sub_summaryarray세부분절별 건수 집계. [{sub_part, count}]
candidates[]array상병 후보 목록 (아래 필드로 구성)
candidates[].codestring상병코드
candidates[].namestring상병명
candidates[].synonymsstring동의어/영문명 묶음(| 구분)
candidates[].eng_namestring영문명(추출 실패 시 빈 문자열)
candidates[].chapterstring챕터(J/K/L 등)
candidates[].divisionstring7대 분과
candidates[].sub_partstring세부분절
candidates[].diagnostic_reqstring청구안전도
candidates[].required_teststring요구 검사/진찰 설명(사람이 읽는 문장)
candidates[].claim_countnumber한방 청구빈도 — 정렬/참고용, 양방 값과 다름
candidates[].claim_count_westernnumber양방 청구빈도(참고용)
candidates[].is_mst_crossboolean근골격 MST 트랙과 이중매핑된 코드인지 여부
candidates[].claim_cautionstring청구 유의사항 문구(없으면 빈 문자열)
candidates[].is_cautionboolean청구 유의 플래그
잘못된 파라미터 값 division/sub에 범위를 벗어난 코드를 보내면 빈 결과 대신 400과 함께 전체 코드표가 담긴 에러를 반환합니다. diag는 기존처럼 영문 코드 허용값 목록으로 안내합니다.
division과 sub가 서로 안 맞을 때 sub 코드는 전역 고정이라 그 자체로는 유효해도, division과 함께 보냈는데 그 분과에 속하지 않는 조합이면 400을 반환합니다 — 예를 들어 division=1(호흡기계)과 sub=0(구강·혀·턱, 실제로는 division=0 소화기계 소속)을 같이 보내면:
GET /api/kcd/public-internal-filter?division=1&sub=0

{
  "error": "sub 코드 '0'(구강·혀·턱)는 division=1(호흡기계)에 속하지 않습니다. division=1에서 허용되는 sub 코드: 7=코·비동, 8=인후·편도·후두, 9=기관지·기침, 10=폐·천식·COPD, 11=흉막·간질·기타"
}
이렇게 그 division에서 실제로 쓸 수 있는 sub 코드만 추려서 바로 알려줍니다. (division 없이 sub=0만 단독으로 보내면 정상적으로 200이 반환됩니다.)

코드로 호출하기

cURL
JavaScript
Python
curl "https://kavinator.com/api/kcd/public-internal-filter?division=1&diag=CLINICAL&limit=5"
fetch('https://kavinator.com/api/kcd/public-internal-filter?' + new URLSearchParams({
  division: 1, diag: 'CLINICAL', limit: 5
}))
  .then(res => res.json())
  .then(data => console.log(data));
import requests

res = requests.get(
    'https://kavinator.com/api/kcd/public-internal-filter',
    params={'division': 1, 'diag': 'CLINICAL', 'limit': 5}
)
data = res.json()
print(data)

5. 직접 테스트해보기

검색 API — 검색어를 넣어보고 실제 응답을 확인할 수 있습니다.

여기에 응답 결과가 표시됩니다.

MST 필터 API — 대부위/발병기전/조직군을 골라보세요.

여기에 응답 결과가 표시됩니다.

한방내과 필터 API — 분과와 청구안전도를 골라보세요.

여기에 응답 결과가 표시됩니다.

6. 이용 시 유의사항

이 API는 카비네이터 본 서비스와 같은 서버에서 무료로 제공됩니다. 과도한 트래픽이 발생하면 예고 없이 제한이 걸릴 수 있으니, 반복 호출이 필요한 경우 결과를 적절히 캐싱해서 사용해주시면 감사하겠습니다. 실제 환자 개인정보는 전혀 포함되지 않은 순수 상병마스터 데이터이므로 별도 개인정보 처리 방침은 적용되지 않습니다.

오류를 발견하셨거나, 더 필요한 파라미터/엔드포인트가 있다면 elaminus1@gmail.com으로 알려주세요.

OpenAPI 3.0 스펙 이 문서의 내용을 AI 코드 어시스턴트나 Swagger Editor/Postman 같은 툴이 바로 읽을 수 있는 구조화된 JSON Schema로도 제공합니다: openapi.json (CORS 허용, 그대로 Import/fetch 가능)
KAVINATOR — kcd_match Project | API v1.1 | LastUpdated 2026.10.01