Dokumentasi API v1

Semua endpoint di bawah /v1, autentikasi lewat header X-Api-Key. Semua respons membawa request_id; semua operasi tulis menerima header Idempotency-Key. Gambar dikirim sebagai base64 / data-URL pada field image (maks 6 MB). Halaman Demo di site ini memakai API key tenant demo lewat proxy server-side (key tidak pernah terekspos ke browser).

POST /v1/enroll

Pendaftaran subjek + template wajah. Consent wajib; tanpa consent respons CONSENT_REQUIRED. Maks 3 template per subjek per versi model.

curl -X POST $API/v1/enroll \ -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \ -d '{ "subject": {"external_id": "budi@mail.com", "name": "Budi"}, "image": "data:image/jpeg;base64,...", "consent": {"accepted": true, "channel": "web"} }'

POST /v1/verify

Verifikasi 1:1 terhadap subjek. Liveness pasif dijalankan otomatis sebelum matching — gagal liveness berhenti dengan LIVENESS_FAILED.

{ "subject_id": "budi@mail.com", "image": "data:image/jpeg;base64,..." } -> {"decision":"match","score":0.81,"threshold":0.363, "liveness":{...}}

POST /v1/identify

Identifikasi 1:N di galeri tenant. Kembalikan kandidat terbaik bila skor ≥ threshold dan margin ke kandidat kedua cukup besar; jika tidak: no_match (below_threshold / ambiguous_margin).

{ "image": "data:image/jpeg;base64,..." } -> {"decision":"match","subject_id":"...","score":0.79,"margin":0.42}

Liveness

POST /v1/liveness/session membuat sesi liveness aktif (masa berlaku 300 detik): kembalikan daftar challenge front → blink → turn_left → turn_right (urutan tengah diacak per sesi). POST /v1/liveness/frame mengirim satu frame kamera tiap ±300 ms — server mengukur mata terbuka/tertutup dan arah wajah (yaw) per frame, lalu maju otomatis antar challenge. POST /v1/liveness tetap tersedia sebagai mode pasif legacy satu foto. Model saat ini: challenge heuristik aktif v1 — bukan PAD tersertifikasi ISO/IEC 30107-3.

POST /v1/liveness/session -> {"session_id","challenges","instructions":[{"action","label"}]} POST /v1/liveness/frame <- {"session_id","image":"data:image/jpeg;base64,... (frame MIRRORED)"} -> {"alive","status","index","total","challenge","label","steps", "observation":{"event":"advance|no_face|eyes_closed|..."}, "metrics":{"eyes_open":0..2,"yaw":...,"iod":...}}

Manajemen Subjek

GET /v1/subjects — daftar subjek tenant.
GET /v1/subjects/{external_id} — detail + metadata template + consent terakhir.
DELETE /v1/subjects/{external_id} — hapus subjek beserta template & consent-nya.

Audit

GET /v1/transactions — jejak lengkap (enroll/verify/identify/liveness) dengan skor, latensi, kode error, versi model, dan request_id tiap baris.

Kode error stabil

FACE_NOT_FOUNDWajah tidak terdeteksi pada gambar
LOW_QUALITYKualitas foto di bawah ambang; field hint berisi instruksi
LIVENESS_FAILEDDugaan foto cetak/layar; matching tidak dilanjutkan
NO_MATCHSkor di bawah threshold (verify) / margin ambigu (identify)
CONSENT_REQUIREDEnroll tanpa baris consent valid
TEMPLATE_LIMITSubjek sudah punya 3 template model versi ini
TEMPLATE_VERSION_MISMATCHMix versi model; jalani re-enroll
RATE_LIMITEDMelebihi 60 request/menit per API key
UNAUTHORIZEDAPI key tidakvalid / tidak aktif

Profil threshold tenant

convenience 0.30 · balanced 0.363 (default, ambang resmi SFace) · high-security 0.42 — plus ambang quality & margin identify yang menyertainya. Model embedding: sface-2021dec (YuNet+SFace, Apache-2.0 — jalur lisensi komersial bersih).