API 문서
별도 SDK 없이 표준 HTTP 한 번 호출로 기존 앱·키오스크·출입장치에 얼굴인증을 붙입니다. 모든 요청은 multipart/form-data로 이미지를 전송하며, 회사코드 헤더 한 줄로 회사별 데이터가 완전히 분리됩니다.
https://facematch.team1985.commultipart/form-data인증 · 회사코드
모든 엔드포인트는 발급받은 회사코드(License Key)를 요구합니다. X-License-Key 헤더로 전달하는 것을 권장하며, 폼 필드 license_key로도 받습니다.
X-License-Key: <회사코드>
에러 응답
실패 시 status 필드가 "error" 또는 "warning"으로 내려갑니다. 회사코드 관련 오류는 HTTP 상태코드로도 구분됩니다.
| 코드 | status | 의미 |
|---|---|---|
| 200 | success | 정상 처리 (인식 성공 여부는 recognized 필드로 구분) |
| 200 | warning | 얼굴 미감지·전경 얼굴 없음 등 — 요청은 정상이나 처리할 얼굴이 없음 |
| 400 | error | 이미지를 읽을 수 없음 (손상·미지원 형식) |
| 401 | error | 회사코드(license_key) 누락 |
| 403 | error | 유효하지 않은 회사코드 · 라이선스 유효기간 만료 |
식별키 · 부가정보
FaceMatch는 평문 개인정보를 보관하지 않는 PII-free 구조입니다. 회원은 파트너가 정한 키로 식별하고, 이름·연락처 등은 암호화된 부가정보로만 저장됩니다.
| 개념 | 설명 |
|---|---|
| unique_key | 파트너 시스템의 회원 식별자(실질 유일키). 회원번호·ID 등 아무 값이나 사용. 매칭 성공 시 이 값이 그대로 반환되므로 자체 DB 조회 키로 씁니다. |
| group_key | 회사 하위의 그룹 구분값(지점·반 등, 선택). 등록 시 지정하면 탐지 시 group_key로 해당 그룹 소속만 후보로 좁힐 수 있습니다. 재등록(갱신) 판정 범위 = (회사, group_key, unique_key). |
| extra | 자유 형식 부가정보 JSON(이름·연락처 등). AES-256-GCM 으로 암호화 저장되고 매칭 성공 시 복호화되어 그대로 반환됩니다 — 자체 서버가 없는 고객사도 매칭 결과만으로 회원정보를 회수할 수 있습니다. |
POST 얼굴등록 · 멀티임베딩
얼굴 이미지 1~N장에서 512차원 특징을 추출해 저장합니다. 정면·좌우·상하 등 여러 방향을 함께 등록하면 인식률이 크게 올라갑니다(권장 5장: 정면+네 모서리). 같은 (회사, group_key, unique_key)가 이미 있으면 갱신(update)됩니다.
요청 파라미터 · multipart/form-data
| 필드 | 타입 | 설명 |
|---|---|---|
| files 필수 | file[] | 얼굴 이미지 1~N장 (jpg/png). 같은 이름 files 필드를 반복 전송 |
| unique_key 필수 | string | 파트너 회원 식별키. 중복 시 기존 등록을 갱신 |
| poses 선택 | string | 이미지 순서와 1:1인 콤마구분 방향 라벨. 예: frontal,left_up,right_up,left_down,right_down |
| group_key 선택 | string | 그룹 구분값(지점·반 등). 탐지 시 같은 값으로 후보를 좁힐 수 있음 |
| extra 선택 | JSON string | 부가정보 JSON 객체. 암호화 저장 후 매칭 시 복호화 반환. 예: {"name":"홍길동","grade":"A"} |
| license_key 선택 | string | 회사코드 (헤더 X-License-Key 미사용 시) |
curl -X POST https://facematch.team1985.com/api/register \
-H "X-License-Key: <회사코드>" \
-F files=@front.jpg -F files=@lu.jpg -F files=@ru.jpg \
-F files=@ld.jpg -F files=@rd.jpg \
-F poses=frontal,left_up,right_up,left_down,right_down \
-F unique_key=member-1024 \
-F group_key=A \
-F extra='{"name":"홍길동","mobile":"01012345678"}'
{
"status": "success",
"action": "inserted", // 또는 "updated"
"face_id": 12,
"unique_key": "member-1024",
"group_key": "A",
"received": 5, // 받은 이미지 수
"accepted": 5, // 품질게이트 통과·저장 수
"poses": ["frontal","left_up","right_up","left_down","right_down"],
"face": {
"bbox": [142,88,320,300],
"det_score": 0.99
}
}
{ "status": "warning", "message": "얼굴을 감지하지 못했습니다." } 가 반환됩니다. 일부만 실패하면 통과한 장수만 accepted에 반영됩니다.POST 얼굴탐지 · 출석체크 1:N
이미지 1장에서 가장 가까운 전경 얼굴 1명만 골라 등록자와 1:N 매칭합니다. 여러 명이 줄 서 있어도 본인 1명만 인식해 출입·출석에 적합합니다.
요청 파라미터 · multipart/form-data
| 필드 | 타입 | 설명 |
|---|---|---|
| file 필수 | file | 인식할 이미지 |
| group_key 선택 | string | 지정 시 해당 그룹에 등록된 얼굴만 후보로 매칭 |
| threshold 선택 | float | 매칭 임계값. 미지정 시 회사 설정 → 전역 기본(0.35) 순으로 적용 |
| margin 선택 | float | 1·2위 유사도 차이 최소값(오인식 방지). 미지정 시 회사 설정 → 전역 기본(0.05) |
| min_face_ratio 선택 | float | 전경 얼굴로 인정할 최소 크기 비율 (기본 0.10) |
| license_key 선택 | string | 회사코드 (헤더 미사용 시) |
curl -X POST https://facematch.team1985.com/api/detect \
-H "X-License-Key: <회사코드>" \
-F file=@photo.jpg \
-F group_key=A
{
"status": "success",
"recognized": true,
"similarity": 0.987, // 1위 유사도
"similarity2": 0.141, // 2위 유사도
"gap": 0.846, // 1-2위 차이
"ambiguous": false, // 닮은 사람과 구분 애매 여부
"verified_by": null, // 2차 모델(buffalo_l)로 확정 시 모델명, 아니면 null
"threshold": 0.35,
"margin": 0.05,
"elapsed_ms": 176,
"person": {
"id": 12,
"unique_key": "member-1024",
"group_key": "A",
"extra": { "name": "홍길동", "mobile": "01012345678" }
},
"num_faces_in_frame": 1
}
recognized: false여도 status는 success입니다 — 인식 여부는 항상 recognized 필드로 판단하세요. 1·2위 유사도 차이가 margin보다 작으면 ambiguous: true와 함께 인식이 보류됩니다(재촬영 유도 권장). 응답에는 선택된 얼굴 좌표(selected)와 프레임 내 전체 얼굴(all_faces)도 포함됩니다.멀티모델 2차검증 & 후보 반환
내부적으로 1차 모델이 애매(ambiguous)로 판정한 건은 변별력이 더 높은 2차 모델(buffalo_l)로 자동 재검증합니다.
2차가 확정하면 recognized: true + verified_by: "buffalo_l"로 응답합니다(앱은 그대로 두어도 됩니다 — 필드만 추가).
일란성 쌍둥이처럼 얼굴만으로 자동 확정이 불가한 경우에는 recognized는 false로 두되,
아래처럼 후보 명단(candidates)을 함께 내려줍니다. 도입사에서 이 후보로 최종 선택 UI(둘 중 택1 등)를 구성할 수 있습니다.
{
"status": "success",
"recognized": false, // 자동 확정 안 함
"ambiguous": true,
"verified_by": null,
"gap": 0.012,
"message": "닮은 사람과 구분이 어렵습니다. 한 번 더 촬영해 주세요.",
"candidates": [ // '이 중 하나' 후보(top-2)
{ "unique_key": "member-1024", "group_key": "A",
"extra": { "name": "홍길동" }, "similarity": 0.712 },
{ "unique_key": "member-1025", "group_key": "A",
"extra": { "name": "홍길순" }, "similarity": 0.700 }
]
}
candidates는ambiguous: true일 때만 포함됩니다.- 각 후보 형태는
person과 동일 +similarity(유사도) 추가. recognized는 여전히 false — 서버는 자동 확정하지 않습니다.- 후보로 최종 선택 UI를 만들지, 재촬영을 유도할지는 도입사 정책입니다.
- 기존 앱은 모르는 필드를 무시하므로 하위호환됩니다.
POST 다중탐지 · N:N
이미지 속 모든 얼굴을 탐지해 각자 1:N 매칭합니다. CCTV·단체 프레임에서 "지금 화면에 누가 보이는지" 명단을 한 번에 받습니다.
요청 파라미터 · multipart/form-data
| 필드 | 타입 | 설명 |
|---|---|---|
| file 필수 | file | 탐지할 이미지 |
| group_key 선택 | string | 지정 시 해당 그룹에 등록된 얼굴만 후보로 매칭 |
| threshold 선택 | float | 매칭 임계값. 미지정 시 회사 설정 → 전역 기본(0.35) |
| license_key 선택 | string | 회사코드 (헤더 미사용 시) |
curl -X POST https://facematch.team1985.com/api/multi-detect \
-H "X-License-Key: <회사코드>" \
-F file=@crowd.jpg
{
"status": "success",
"num_faces": 3,
"recognized_count": 2,
"elapsed_ms": 880,
"faces": [
{
"recognized": true,
"similarity": 0.987,
"person": {
"unique_key": "member-1024",
"extra": { "name": "홍길동" }
},
"bbox": [88,60,240,250]
},
{
"recognized": false,
"similarity": 0.21,
"person": null,
"bbox": [410,90,560,270]
}
]
}
GET 등록 목록
자기 회사에 등록된 얼굴 전체 목록입니다. 부가정보는 복호화되어 내려가고, name/mobile은 부가정보에서 병합된 값입니다.
curl https://facematch.team1985.com/api/faces \
-H "X-License-Key: <회사코드>"
{
"status": "success",
"list": [
{
"id": 12,
"unique_key": "member-1024",
"group_key": "A",
"extra": { "name": "홍길동", "mobile": "01012345678" },
"name": "홍길동",
"mobile": "01012345678",
"image_path": "/images/reg_....jpg",
"created_at": 1782301234
}
]
}
GET 등록 상세 · 방향별 이미지
등록 얼굴 1건의 방향별 등록 이미지와 복호화된 부가정보를 조회합니다.
curl https://facematch.team1985.com/api/faces/12/poses \
-H "X-License-Key: <회사코드>"
{
"status": "success",
"unique_key": "member-1024",
"group_key": "A",
"extra": { "name": "홍길동" },
"list": [
{ "pose": "frontal", "image_path": "/images/...", "quality": 312.5 },
{ "pose": "left_up", "image_path": "/images/...", "quality": 287.1 }
]
}
POST 등록 수정
이름·연락처를 수정합니다. 값은 암호화된 부가정보에 병합 저장되며, 임베딩·사진은 유지됩니다.
| 필드 | 타입 | 설명 |
|---|---|---|
| name 선택 | string | 이름. 빈 값이면 부가정보에서 제거 |
| mobile 선택 | string | 연락처. 빈 값이면 부가정보에서 제거 |
curl -X POST https://facematch.team1985.com/api/faces/12 \
-H "X-License-Key: <회사코드>" \
-F name=홍길동 -F mobile=01012345678
DELETE 등록 삭제
등록 얼굴을 삭제합니다. 삭제 즉시 인식 대상에서 제외되며, 과거 매칭 로그의 증적 이미지는 보존됩니다(소프트 삭제). 등록 시 사용한 unique_key(식별키)로 삭제하는 것이 기본이며, 내부 face_id를 아는 경우 ID 삭제도 가능합니다.
curl -X DELETE "https://facematch.team1985.com/api/faces/by-key/member-1024?group_key=gangnam" \
-H "X-License-Key: <회사코드>"
# 응답
{ "status": "success", "deleted": 1, "face_ids": [12] }
group_key는 옵션입니다 — 전달하면 해당 그룹 스코프의 등록만 삭제하고, 생략하면 회사 내 해당 식별키의 등록을 모두 삭제합니다(응답의 deleted가 삭제 건수). 일치하는 등록이 없으면 404를 반환합니다.curl -X DELETE https://facematch.team1985.com/api/faces/12 \
-H "X-License-Key: <회사코드>"
GET 매칭 로그
최근 인식 시도 이력입니다. 어떤 방향(matched_pose) 등록 이미지가 매칭을 이겼는지, 시도 사진(probe_image)과 매칭된 등록 사진(matched_image)까지 증적으로 제공됩니다.
curl "https://facematch.team1985.com/api/logs?limit=50" \
-H "X-License-Key: <회사코드>"
{
"status": "success",
"list": [
{
"id": 224,
"mode": "detect", // detect | multi
"recognized": true,
"name": "홍길동",
"unique_key": "member-1024",
"group_key": "A",
"similarity": 0.723,
"threshold": 0.35,
"matched_pose": "left_up",
"probe_image": "/images/probe_....jpg",
"matched_image": "/images/reg_....jpg",
"elapsed_ms": 180,
"num_faces": 1,
"created_at": 1782301234
}
]
}
https://facematch.team1985.com · © 2026 team1985