API 문서 (한국어)¶
개요¶
기본 URL: https://face-api.xylolabs.com
주요 콘텐츠 타입:
- 이미지 업로드 엔드포인트: multipart/form-data
- 관리자/인증 엔드포인트: application/json
- 공개 /api/v1/mask 엔드포인트: 바이너리 이미지 응답
인증¶
공개 엔드포인트¶
POST /api/v1/detectPOST /api/v1/mask
이 엔드포인트들은 FACE_API_API_KEY_ENABLED=true일 때 X-API-Key 헤더가 필요합니다. 기본값은 true입니다.
관리자 콘솔 / 관리자 API¶
관리자 인증 방식: - 브라우저 관리자 콘솔: 쿠키 기반 관리자 세션 - 직접 관리자 API를 호출하는 클라이언트: HTTP Basic 인증
브라우저 관리자 세션 엔드포인트:
- POST /api/v1/admin/auth/login
- GET /api/v1/admin/auth/session
- POST /api/v1/admin/auth/logout
요청 제한¶
POST /api/v1/detect: 기본300/minutePOST /api/v1/mask: 기본150/minute- 관리자 로그인: 기본
10/minute
세션 기본값¶
- 관리자 세션 TTL 기본값:
43200초 (12시간) - 관리자 로그인 요청 제한 기본값:
10/minute
오류 형식¶
엔드포인트¶
GET /health¶
인증: 없음
서비스 상태와 모델 정보를 반환합니다. 모델과 필요한 DB/스토리지 의존성이 준비된 경우에만 200을 반환하고, 그렇지 않으면 503을 반환합니다.
- 요청 형식: 없음
- 응답 형식: JSON (
HealthResponse)
import requests
response = requests.get("https://face-api.xylolabs.com/health")
print(response.json())
const response = await fetch("https://face-api.xylolabs.com/health");
console.log(await response.json());
using var client = new HttpClient();
var response = await client.GetAsync("https://face-api.xylolabs.com/health");
Console.WriteLine(await response.Content.ReadAsStringAsync());
POST /api/v1/detect¶
인증: API 키
얼굴을 감지하고 JSON을 반환합니다.
- 요청 형식:
multipart/form-data - 응답 형식: JSON (
DetectResponse)
쿼리 파라미터¶
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
confidence |
float | 0.5 |
최소 신뢰도 |
nms_threshold |
float | 0.4 |
NMS IoU 임계값 |
max_faces |
int | 0 |
0이면 제한 없음 |
예시¶
curl -X POST "https://face-api.xylolabs.com/api/v1/detect?confidence=0.6&max_faces=5" \
-H "X-API-Key: xyl_your_api_key_here" \
-F "image=@photo.jpg"
import requests
response = requests.post(
"https://face-api.xylolabs.com/api/v1/detect?confidence=0.6&max_faces=5",
headers={"X-API-Key": "xyl_your_api_key_here"},
files={"image": open("photo.jpg", "rb")},
)
print(response.json())
const formData = new FormData();
formData.append("image", fileInput.files[0]);
const response = await fetch("https://face-api.xylolabs.com/api/v1/detect?confidence=0.6&max_faces=5", {
method: "POST",
headers: { "X-API-Key": "xyl_your_api_key_here" },
body: formData,
});
console.log(await response.json());
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "xyl_your_api_key_here");
using var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "image", "photo.jpg");
var response = await client.PostAsync(
"https://face-api.xylolabs.com/api/v1/detect?confidence=0.6&max_faces=5",
content
);
Console.WriteLine(await response.Content.ReadAsStringAsync());
응답 구성¶
request_id: 요청 UUIDimage: 입력 이미지 정보detections[]: bbox, 랜드마크, 크기, 면적, 중심, 상대 위치summary: 얼굴 수와 신뢰도 요약processing: 모델/임계값/핵심 처리 시간profiling: 상세 타이밍 정보
POST /api/v1/mask¶
인증: API 키
얼굴을 감지하고 마스킹한 뒤, 처리된 이미지를 바이너리로 반환합니다.
- 요청 형식:
multipart/form-data - 응답 형식: 바이너리 이미지 (
image/jpeg,image/png,image/webp)
쿼리 파라미터¶
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
confidence |
float | 0.5 |
최소 신뢰도 |
nms_threshold |
float | 0.4 |
NMS IoU 임계값 |
max_faces |
int | 0 |
0이면 제한 없음 |
method |
enum | gaussian |
gaussian, pixelate, solid, elliptical |
strength |
int | 199 |
블러/픽셀화 강도 |
padding |
float | 0.15 |
마스킹 전 bbox 확장 비율 |
format |
enum | jpeg |
jpeg, png, webp |
quality |
int | 95 |
출력 품질 |
예시¶
curl -X POST "https://face-api.xylolabs.com/api/v1/mask?method=pixelate&strength=32&format=webp" \
-H "X-API-Key: xyl_your_api_key_here" \
-F "image=@photo.jpg" \
-o masked.webp
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "xyl_your_api_key_here");
using var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "image", "photo.jpg");
var response = await client.PostAsync(
"https://face-api.xylolabs.com/api/v1/mask?method=pixelate&strength=32&format=webp",
content
);
await using var output = File.Create("masked.webp");
await response.Content.CopyToAsync(output);
import requests
response = requests.post(
"https://face-api.xylolabs.com/api/v1/mask?method=pixelate&strength=32&format=webp",
headers={"X-API-Key": "xyl_your_api_key_here"},
files={"image": open("photo.jpg", "rb")},
)
with open("masked.webp", "wb") as f:
f.write(response.content)
const formData = new FormData();
formData.append("image", fileInput.files[0]);
const response = await fetch("https://face-api.xylolabs.com/api/v1/mask?method=pixelate&strength=32&format=webp", {
method: "POST",
headers: { "X-API-Key": "xyl_your_api_key_here" },
body: formData,
});
const blob = await response.blob();
응답¶
바이너리 이미지와 함께 아래 메타데이터 헤더를 반환합니다.
- X-Request-Id
- X-Face-Count
- X-Inference-Ms
- X-Mask-Ms
- X-Encode-Ms
- X-Total-Ms
- X-Model
- 저장 기능이 켜져 있으면 X-Image-Id, X-Job-Id
관리자 인증/세션 엔드포인트¶
POST /api/v1/admin/auth/login¶
인증: 없음
쿠키 기반 관리자 세션을 발급합니다.
- 요청 형식: JSON
- 응답 형식: 빈 바디 (
204 No Content) +Set-Cookie
curl -X POST https://face-api.xylolabs.com/api/v1/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"secret"}' \
-c cookies.txt -i
import requests
session = requests.Session()
response = session.post(
"https://face-api.xylolabs.com/api/v1/admin/auth/login",
json={"username": "admin", "password": "secret"},
)
print(response.status_code)
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify({ username: "admin", password: "secret" }),
});
console.log(response.status);
using System.Text;
using var client = new HttpClient();
using var content = new StringContent("{\"username\":\"admin\",\"password\":\"secret\"}", Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://face-api.xylolabs.com/api/v1/admin/auth/login", content);
Console.WriteLine(response.StatusCode);
성공 시 204 No Content와 Set-Cookie를 반환합니다.
GET /api/v1/admin/auth/session¶
인증: 쿠키 기반 관리자 세션 또는 HTTP Basic
- 요청 형식: 없음
- 응답 형식: JSON (
AdminSessionResponse)
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/auth/session",
auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/auth/session", {
headers: { Authorization: `Basic ${basic}` },
});
console.log(await response.json());
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/auth/session");
Console.WriteLine(await response.Content.ReadAsStringAsync());
POST /api/v1/admin/auth/logout¶
인증: 없음
쿠키 기반 관리자 세션을 지웁니다. 204를 반환합니다.
- 요청 형식: 없음
- 응답 형식: 빈 바디 (
204 No Content)
import requests
session = requests.Session()
response = session.post("https://face-api.xylolabs.com/api/v1/admin/auth/logout")
print(response.status_code)
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/auth/logout", {
method: "POST",
credentials: "include",
});
console.log(response.status);
using var client = new HttpClient();
var response = await client.PostAsync("https://face-api.xylolabs.com/api/v1/admin/auth/logout", content: null);
Console.WriteLine(response.StatusCode);
관리자 엔드포인트¶
모든 관리자 엔드포인트는 /api/v1/admin 아래에 있으며, 유효한 쿠키 기반 관리자 세션 또는 HTTP Basic 인증이 필요합니다.
GET /api/v1/admin/stats¶
이미지/작업 전체 통계를 반환합니다. 스토리지 기반 모드가 필요하며, FACE_API_STORAGE_ENABLED=false이면 501을 반환합니다.
- 요청 형식: 없음
- 응답 형식: JSON (
StatsResponse) - 자세한 예제: 관리자 API
GET /api/v1/admin/images¶
페이지네이션된 이미지 목록을 반환합니다. 스토리지 기반 모드가 필요하며, FACE_API_STORAGE_ENABLED=false이면 501을 반환합니다.
- 요청 형식: 없음(쿼리 문자열만 사용)
응답 항목에 들어가는 정보:
- original_url (비공개 원본 다운로드 URL)
- processed_url (있다면 가장 최근 처리 결과)
- 크기, 용량, 작업 수, 생성 시각
아직 처리 결과가 없으면 processed_url 값은 null입니다.
FACE_API_S3_PUBLIC_ENDPOINT가 설정되어 있으면 processed_url은 공개 처리 자산 호스트를 가리킬 수 있습니다.
- 응답 형식: JSON (
PaginatedResponse[StoredImageResponse]) - 자세한 예제: 관리자 API
GET /api/v1/admin/images/{image_id}¶
이미지 상세 + 관련 작업 목록을 반환합니다.
- 요청 형식: 없음
- 응답 형식: JSON (
StoredImageDetailResponse) - 자세한 예제: 관리자 API
DELETE /api/v1/admin/images/{image_id}¶
DB 메타데이터를 지우고 S3 객체 정리를 시도합니다. 정리에 실패하면 cleanup task로 남겨 두고 이후 재시도합니다. 204를 반환합니다.
- 요청 형식: 없음
- 응답 형식: 빈 바디 (
204 No Content) - 자세한 예제: 관리자 API
GET /api/v1/admin/images/{image_id}/download¶
원본 이미지 URL로 리다이렉트합니다.
- 요청 형식: 없음
- 응답 형식: 리다이렉트 (
302 Found) - 자세한 예제: 관리자 API
GET /api/v1/admin/jobs¶
작업 목록을 반환합니다. job_type, method로 필터할 수 있습니다. 스토리지 기반 모드가 필요하며, FACE_API_STORAGE_ENABLED=false이면 501을 반환합니다.
- 요청 형식: 없음(쿼리 문자열만 사용)
- 응답 형식: JSON (
PaginatedResponse[JobResponse]) - 자세한 예제: 관리자 API
GET /api/v1/admin/jobs/{job_id}¶
감지 결과와 처리 이미지 URL을 포함한 작업 상세입니다.
- 요청 형식: 없음
- 응답 형식: JSON (
JobDetailResponse) - 자세한 예제: 관리자 API
GET /api/v1/admin/jobs/{job_id}/download¶
처리 이미지 URL로 리다이렉트합니다.
- 요청 형식: 없음
- 응답 형식: 리다이렉트 (
302 Found) - 자세한 예제: 관리자 API
POST /api/v1/admin/test/mask¶
관리자 콘솔 테스트 페이지에서 쓰는 관리자 전용 미리보기 엔드포인트입니다.
이 엔드포인트는 공개 /api/v1/mask와 달리 JSON을 반환합니다.
반환 내용:
- DetectResponse 계열 필드 전체
- masking
- output.image_base64
- 요청 형식:
multipart/form-data - 응답 형식: JSON (
MaskResponse) - 자세한 예제: 관리자 콘솔
POST /api/v1/admin/api-keys¶
새 API 키를 만듭니다. 데이터베이스 기반 모드가 필요하며, DB 계층이 비활성화되어 있으면 501을 반환합니다.
생성 시점에만 전체 키를 반환합니다.
- 요청 형식: JSON
- 응답 형식: JSON (
ApiKeyCreatedResponse) - 자세한 예제: API 키 관리
GET /api/v1/admin/api-keys¶
키 메타데이터만 반환합니다. 데이터베이스 기반 모드가 필요하며, DB 계층이 비활성화되어 있으면 501을 반환합니다.
- 요청 형식: 없음(쿼리 문자열만 사용)
필드 예시:
- id
- name
- key_prefix
- key_suffix
- key_preview
- is_active
- request_count
- last_used_at
- created_at
- 응답 형식: JSON (
PaginatedResponse[ApiKeyResponse]) - 자세한 예제: API 키 관리
GET /api/v1/admin/api-keys/{key_id}¶
키 메타데이터만 반환합니다. 데이터베이스 기반 모드가 필요하며, DB 계층이 비활성화되어 있으면 501을 반환합니다.
- 요청 형식: 없음
- 응답 형식: JSON (
ApiKeyResponse) - 자세한 예제: API 키 관리
PATCH /api/v1/admin/api-keys/{key_id}¶
키 이름을 바꾸거나 활성/비활성을 전환합니다. 데이터베이스 기반 모드가 필요하며, DB 계층이 비활성화되어 있으면 501을 반환합니다.
- 요청 형식: JSON
- 응답 형식: JSON (
ApiKeyResponse) - 자세한 예제: API 키 관리
DELETE /api/v1/admin/api-keys/{key_id}¶
키를 삭제합니다. 데이터베이스 기반 모드가 필요하며, DB 계층이 비활성화되어 있으면 501을 반환합니다. 성공 시 204를 반환합니다.
- 요청 형식: 없음
- 응답 형식: 빈 바디 (
204 No Content) - 자세한 예제: API 키 관리
스키마¶
DetectResponse¶
주요 구조:
{
"request_id": "uuid",
"image_id": null,
"job_id": null,
"image": {
"width": 1920,
"height": 1080,
"channels": 3,
"size_bytes": 245760
},
"detections": [],
"summary": {
"face_count": 1,
"avg_confidence": 0.9876,
"min_confidence": 0.9876,
"max_confidence": 0.9876,
"total_face_area": 39999.84,
"face_area_ratio": 0.019
},
"processing": {
"model": "scrfd_10g",
"input_size": [640, 640],
"confidence_threshold": 0.5,
"nms_threshold": 0.4,
"inference_ms": 12.34,
"total_ms": 18.56
},
"profiling": {
"decode_ms": 3.21,
"preprocess_ms": 1.05,
"blob_ms": 0.82,
"inference_ms": 12.34,
"postprocess_ms": 0.45,
"nms_ms": 0.12,
"mask_ms": null,
"encode_ms": null,
"storage_ms": null,
"total_ms": 18.56,
"candidates_before_nms": 15,
"candidates_after_nms": 1,
"det_scale": 0.333333,
"input_resolution": "1920x1080",
"det_resolution": "640x640",
"input_bytes": 245760,
"output_bytes": null,
"input_pixels": 2073600,
"model_name": "scrfd_10g"
}
}
관리자 마스크 미리보기 응답¶
DetectResponse에 아래 필드를 더한 구조입니다.
{
"masking": {
"method": "gaussian",
"strength": 199,
"padding": 0.15,
"regions_masked": 1
},
"output": {
"format": "jpeg",
"quality": 95,
"size_bytes": 123456,
"image_base64": "..."
}
}
PaginatedResponse¶
감지 모델¶
| 모델 | 설명 |
|---|---|
scrfd_10g |
가장 정확하지만 CPU를 많이 씀 |
scrfd_2.5g |
균형형 |
scrfd_500m |
가장 작고 빠르지만 정확도가 낮음 |
코드 예제¶
Python (requests)¶
import requests
with open("photo.jpg", "rb") as f:
response = requests.post(
"https://face-api.xylolabs.com/api/v1/detect?confidence=0.6",
headers={"X-API-Key": "xyl_your_api_key_here"},
files={"image": f},
)
print(response.json()["summary"]["face_count"])
JavaScript (fetch)¶
const formData = new FormData();
formData.append("image", fileInput.files[0]);
const response = await fetch(
"https://face-api.xylolabs.com/api/v1/mask?method=gaussian",
{
method: "POST",
headers: { "X-API-Key": "xyl_your_api_key_here" },
body: formData,
}
);
const blob = await response.blob();
C# (HttpClient)¶
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "xyl_your_api_key_here");
using var detectContent = new MultipartFormDataContent();
detectContent.Add(new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "image", "photo.jpg");
var detectResponse = await client.PostAsync(
"https://face-api.xylolabs.com/api/v1/detect?confidence=0.6",
detectContent
);
Console.WriteLine(await detectResponse.Content.ReadAsStringAsync());
using var maskContent = new MultipartFormDataContent();
maskContent.Add(new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "image", "photo.jpg");
var maskResponse = await client.PostAsync(
"https://face-api.xylolabs.com/api/v1/mask?method=gaussian",
maskContent
);
await using var output = File.Create("masked.jpg");
await maskResponse.Content.CopyToAsync(output);