Skip to content

관리자 API

관리자 엔드포인트는 /api/v1/admin 아래에 있습니다.

인증 방식: - 브라우저 관리자 콘솔: /api/v1/admin/auth/login으로 시작하는 쿠키 기반 관리자 세션 - 직접 관리자 API를 호출하는 클라이언트: HTTP Basic 인증

브라우저 관리자 세션 엔드포인트: - POST /api/v1/admin/auth/login - GET /api/v1/admin/auth/session - POST /api/v1/admin/auth/logout

Authorization: Basic base64(username:password)

GET /api/v1/admin/stats

전체 통계를 반환합니다. 스토리지 기반 모드가 필요하며, FACE_API_STORAGE_ENABLED=false이면 501을 반환합니다.

  • 요청 형식: 없음
  • 응답 형식: JSON (StatsResponse)
curl -u admin:password https://face-api.xylolabs.com/api/v1/admin/stats
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    "https://face-api.xylolabs.com/api/v1/admin/stats",
    auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/stats", {
  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/stats");
Console.WriteLine(await response.Content.ReadAsStringAsync());
{
  "total_images": 1250,
  "total_jobs": 3420,
  "total_faces_detected": 8910,
  "avg_inference_ms": 14.52,
  "storage_used_bytes": 524288000,
  "jobs_by_type": { "detect": 2100, "mask": 1320 },
  "jobs_by_method": { "gaussian": 800, "pixelate": 400, "solid": 120 }
}

이미지

GET /api/v1/admin/images

저장된 이미지 목록을 반환합니다. 비공개 원본 다운로드 URL과, 있으면 가장 최근 처리 결과 URL도 함께 반환합니다. 스토리지 기반 모드가 필요하며, FACE_API_STORAGE_ENABLED=false이면 501을 반환합니다.

  • 요청 형식: 없음(쿼리 문자열만 사용)
  • 응답 형식: JSON (PaginatedResponse[StoredImageResponse])

아직 처리 결과가 없으면 processed_url 값은 null입니다. FACE_API_S3_PUBLIC_ENDPOINT가 설정되어 있으면 processed_url은 공개 처리 자산 호스트를 가리킬 수 있습니다.

파라미터 타입 기본값 설명
page int 1 페이지 번호
per_page int 20 페이지당 항목 수 (1-100)
curl -u admin:password "https://face-api.xylolabs.com/api/v1/admin/images?page=1&per_page=10"
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    "https://face-api.xylolabs.com/api/v1/admin/images?page=1&per_page=10",
    auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images?page=1&per_page=10", {
  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/images?page=1&per_page=10");
Console.WriteLine(await response.Content.ReadAsStringAsync());
{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "filename": "photo.jpg",
      "content_type": "image/jpeg",
      "size_bytes": 245760,
      "width": 1920,
      "height": 1080,
      "original_url": "https://signed.example.com/originals/...",
      "processed_url": "https://static.face-api.xylolabs.com/face-api/processed/...",
      "job_count": 3,
      "created_at": "2026-04-06T10:30:00+00:00"
    }
  ],
  "total": 1250, "page": 1, "per_page": 10, "pages": 125
}

signed.example.com은 비공개 서명 원본 다운로드 URL 예시를 보여 주기 위한 자리표시자입니다. static.face-api.xylolabs.comFACE_API_S3_PUBLIC_ENDPOINT가 설정된 경우의 공개 처리 자산 호스트 예시입니다.

GET /api/v1/admin/images/{image_id}

이미지 상세 정보와 관련 작업 목록을 반환합니다.

  • 요청 형식: 없음
  • 응답 형식: JSON (StoredImageDetailResponse)
curl -u admin:password https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    "https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...",
    auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...", {
  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/images/550e8400-...");
Console.WriteLine(await response.Content.ReadAsStringAsync());

DELETE /api/v1/admin/images/{image_id}

이미지와 관련 작업, S3 객체를 모두 삭제합니다. 성공 시 204를 반환합니다.

  • 요청 형식: 없음
  • 응답 형식: 빈 바디 (204 No Content)
curl -u admin:password -X DELETE https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...
import requests
from requests.auth import HTTPBasicAuth

response = requests.delete(
    "https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...",
    auth=HTTPBasicAuth("admin", "password"),
)
print(response.status_code)
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...", {
  method: "DELETE",
  headers: { Authorization: `Basic ${basic}` },
});
console.log(response.status);
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.DeleteAsync("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...");
Console.WriteLine(response.StatusCode);

GET /api/v1/admin/images/{image_id}/download

원본 이미지 다운로드 URL로 리다이렉트(302)합니다.

  • 요청 형식: 없음
  • 응답 형식: 리다이렉트 (302 Found)
curl -u admin:password -L https://face-api.xylolabs.com/api/v1/admin/images/550e8400-.../download -o original.jpg
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    "https://face-api.xylolabs.com/api/v1/admin/images/550e8400-.../download",
    auth=HTTPBasicAuth("admin", "password"),
    allow_redirects=True,
)
with open("original.jpg", "wb") as f:
    f.write(response.content)
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-.../download", {
  headers: { Authorization: `Basic ${basic}` },
});
const blob = await response.blob();
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/images/550e8400-.../download");
await using var output = File.Create("original.jpg");
await response.Content.CopyToAsync(output);

작업

GET /api/v1/admin/jobs

작업 목록을 반환합니다(페이지네이션, 필터 지원). 스토리지 기반 모드가 필요하며, FACE_API_STORAGE_ENABLED=false이면 501을 반환합니다.

  • 요청 형식: 없음(쿼리 문자열만 사용)
  • 응답 형식: JSON (PaginatedResponse[JobResponse])
파라미터 타입 기본값 설명
page int 1 페이지 번호
per_page int 20 페이지당 항목 수 (1-100)
job_type string detect 또는 mask
method string 블러 방식으로 필터
curl -u admin:password "https://face-api.xylolabs.com/api/v1/admin/jobs?job_type=mask&method=gaussian"
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    "https://face-api.xylolabs.com/api/v1/admin/jobs?job_type=mask&method=gaussian",
    auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/jobs?job_type=mask&method=gaussian", {
  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/jobs?job_type=mask&method=gaussian");
Console.WriteLine(await response.Content.ReadAsStringAsync());

GET /api/v1/admin/jobs/{job_id}

작업 상세 정보를 반환합니다(감지 데이터 포함).

  • 요청 형식: 없음
  • 응답 형식: JSON (JobDetailResponse)
curl -u admin:password https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-...
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    "https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-...",
    auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-...", {
  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/jobs/550e8400-...");
Console.WriteLine(await response.Content.ReadAsStringAsync());

GET /api/v1/admin/jobs/{job_id}/download

처리된 이미지 URL로 리다이렉트(302)합니다.

  • 요청 형식: 없음
  • 응답 형식: 리다이렉트 (302 Found)
curl -u admin:password -L https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-.../download -o processed.jpg
import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    "https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-.../download",
    auth=HTTPBasicAuth("admin", "password"),
    allow_redirects=True,
)
with open("processed.jpg", "wb") as f:
    f.write(response.content)
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-.../download", {
  headers: { Authorization: `Basic ${basic}` },
});
const blob = await response.blob();
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/jobs/550e8400-.../download");
await using var output = File.Create("processed.jpg");
await response.Content.CopyToAsync(output);

API 키

모든 /api/v1/admin/api-keys* 엔드포인트는 데이터베이스 기반 모드가 필요하며, DB 계층이 비활성화되어 있으면 501을 반환합니다.