카비네이터 본 서비스가 쓰는 상병 검색/필터링 기능을, 여러분의 앱/스크립트에서 그대로 가져다 쓸 수 있는 외부 개발자용 API입니다. 현재 검색 1개 + 필터링 엔진 2개(근골격·외상 MST / 한방내과)가 열려 있습니다.
| Base URL | https://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 응답. |
public-* 엔드포인트들은 카비네이터 내부 UI와 계산 로직은 공유하지만, 응답 스키마는
완전히 독립된 별도 계약으로 유지됩니다. 내부 화면이 바뀌어도 여기 문서화된 필드는 예고 없이 바뀌지 않습니다.
/api/kcd/public-search검색어(상병코드 또는 상병명)를 넣으면, 관련도 순으로 정렬된 상병 목록을 최대 30건 반환합니다.
| 이름 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| q | 필수 | - | 검색어. 상병코드(예: M54.5, 점 유무 무관)나 상병명 일부(예: 요통)를 모두 지원합니다.
띄어쓰기로 여러 단어를 넣으면 각 단어가 모두 포함된 결과만 매치됩니다. |
| fields | 선택 | 0 |
응답에 포함할 필드 선택.0 = 상병코드 + 상병명 + 청구건수 (기본값)1 = 상병코드만2 = 상병명만3 = 상병명 + 청구건수
|
| 필드 | 타입 | 설명 |
|---|---|---|
| query | string | 요청한 검색어 원문 |
| count | number | 반환된 결과 건수 (최대 30) |
| results | array | 검색 결과 목록. fields 값에 따라 각 항목에 포함되는 키가 달라집니다. |
| results[].code | string | 상병코드 (fields=0 또는 1일 때 포함) |
| results[].name | string | 상병명 (fields=0, 2, 3일 때 포함) |
| results[].claim_count | number | 한방(HIRA) 청구건수 — 정렬/참고용 지표이며 양방 청구건수와는 다른 값입니다 (fields=0 또는 3일 때 포함) |
{"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 "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)
/api/kcd/public-mst-filter
5대 대부위 → 발병기전(외상유무) → 세부분절 → 병변조직군 → 청구안전도 순으로 다차원 소거 필터링해
상병 후보군을 반환합니다. 모든 파라미터는 선택이며, 생략하면 해당 단계는 필터 없이 전체를 봅니다.
각 단계의 집계(*_summary)도 함께 내려가므로, 단계형(위저드) UI를 그대로 구현할 수 있습니다.
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 | 페이지네이션 오프셋 |
| 코드 | 값 |
|---|---|
| 0 | 체간 |
| 1 | 상지 |
| 2 | 하지 |
| 3 | 두경부 |
| 4 | 전신·다발 |
코드는 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_count | number | 현재 필터 조건에 맞는 전체 건수 (limit/offset 적용 전) |
| selected | object | 요청에 적용된 필터값 echo. major/sub는 {code, value} 형태(보낸 코드 + 해석된 한글 값), 둘 다 생략 시 null |
| major_summary | array | 대부위별 건수 집계. [{major_part, count}] |
| trauma_summary | object | 발병기전별 건수. {total, trauma, non_trauma} |
| sub_summary | array | 세부분절별 건수 집계. [{sub_part, count}] (major 지정 시에만 채워짐) |
| tissue_summary | object | 병변조직군별 건수. {조직군코드: count} |
| diag_summary | object | 청구안전도별 건수. {청구안전도코드: count} |
| candidates[] | array | 상병 후보 목록 (아래 필드로 구성) |
| candidates[].code | string | 상병코드 |
| candidates[].name | string | 상병명 |
| candidates[].synonyms | string | 동의어/영문명 묶음(| 구분) |
| candidates[].eng_name | string | 영문명(추출 실패 시 빈 문자열) |
| candidates[].chapter | string | 챕터(M/S/T 등) |
| candidates[].major_part | string | 대부위 |
| candidates[].sub_part | string | 세부분절 |
| candidates[].target_tissue | string | 병변조직군 |
| candidates[].diagnostic_req | string | 청구안전도 |
| candidates[].required_test | string | 요구 검사/진찰 설명(사람이 읽는 문장) |
| candidates[].claim_count | number | 한방 청구빈도 — 정렬/참고용, 양방 값과 다름 |
| candidates[].claim_count_western | number | 양방 청구빈도(참고용) |
| candidates[].is_primary | boolean | 이 대부위의 주매핑 코드인지 여부 |
| candidates[].cross_reason | string|null | 다른 분과와 이중매핑된 사유(없으면 null) |
| candidates[].is_site_unspecified | boolean | 부위상세불명(모든 대부위 필터에 걸리는) 코드 여부 |
| candidates[].claim_caution | string | 청구 유의사항 문구(없으면 빈 문자열) |
| candidates[].is_caution | boolean | 청구 유의 플래그 |
claim_count는 상병 후보의 정렬/강조 전용 지표입니다 — 후보가 적게 나왔다고 정답이 아닌 것은 아니며,
이 API도 카비네이터 본 서비스와 동일하게 "후보 배제 없이 많이 보여주고 최종 선택은 사용자가" 원칙을 따릅니다.
major/sub에 범위를 벗어난 코드(또는 정수가 아닌 값)를 보내면, 빈 결과 대신 400과 함께
전체 코드표가 담긴 에러를 반환합니다: {"error": "유효하지 않은 major 코드: '9'. 허용 코드: 0=체간, 1=상지, ..."}.
trauma/tissue/diag는 기존처럼 영문 코드 허용값 목록으로 안내합니다.
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 "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)
/api/kcd/public-internal-filter7대 분과 → 청구안전도 → 세부분절 순으로 소거 필터링해 상병 후보군을 반환합니다.
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 | 페이지네이션 오프셋 |
| 코드 | 값 |
|---|---|
| 0 | 소화기계 |
| 1 | 호흡기계 |
| 2 | 피부계 |
| 3 | 부인·비뇨생식 |
| 4 | 정신·신경 |
| 5 | 이비인후·안과 |
| 6 | 전신·대사·순환 |
코드는 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_count | number | 현재 필터 조건에 맞는 전체 건수 |
| selected | object | 요청에 적용된 필터값 echo. division/sub는 {code, value} 형태, sub 생략 시 null |
| division_summary | array | 7대 분과별 건수·아이콘·설명(고정 메타데이터) |
| diag_summary | object | 청구안전도별 건수. {청구안전도코드: count} |
| sub_summary | array | 세부분절별 건수 집계. [{sub_part, count}] |
| candidates[] | array | 상병 후보 목록 (아래 필드로 구성) |
| candidates[].code | string | 상병코드 |
| candidates[].name | string | 상병명 |
| candidates[].synonyms | string | 동의어/영문명 묶음(| 구분) |
| candidates[].eng_name | string | 영문명(추출 실패 시 빈 문자열) |
| candidates[].chapter | string | 챕터(J/K/L 등) |
| candidates[].division | string | 7대 분과 |
| candidates[].sub_part | string | 세부분절 |
| candidates[].diagnostic_req | string | 청구안전도 |
| candidates[].required_test | string | 요구 검사/진찰 설명(사람이 읽는 문장) |
| candidates[].claim_count | number | 한방 청구빈도 — 정렬/참고용, 양방 값과 다름 |
| candidates[].claim_count_western | number | 양방 청구빈도(참고용) |
| candidates[].is_mst_cross | boolean | 근골격 MST 트랙과 이중매핑된 코드인지 여부 |
| candidates[].claim_caution | string | 청구 유의사항 문구(없으면 빈 문자열) |
| candidates[].is_caution | boolean | 청구 유의 플래그 |
division/sub에 범위를 벗어난 코드를 보내면 빈 결과 대신 400과 함께 전체 코드표가 담긴
에러를 반환합니다. diag는 기존처럼 영문 코드 허용값 목록으로 안내합니다.
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 "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)
검색 API — 검색어를 넣어보고 실제 응답을 확인할 수 있습니다.
여기에 응답 결과가 표시됩니다.
MST 필터 API — 대부위/발병기전/조직군을 골라보세요.
여기에 응답 결과가 표시됩니다.
한방내과 필터 API — 분과와 청구안전도를 골라보세요.
여기에 응답 결과가 표시됩니다.
이 API는 카비네이터 본 서비스와 같은 서버에서 무료로 제공됩니다. 과도한 트래픽이 발생하면 예고 없이 제한이 걸릴 수 있으니, 반복 호출이 필요한 경우 결과를 적절히 캐싱해서 사용해주시면 감사하겠습니다. 실제 환자 개인정보는 전혀 포함되지 않은 순수 상병마스터 데이터이므로 별도 개인정보 처리 방침은 적용되지 않습니다.
오류를 발견하셨거나, 더 필요한 파라미터/엔드포인트가 있다면 elaminus1@gmail.com으로 알려주세요.