API Reference — CES
Endpoint untuk monitoring node, pengambilan konfigurasi, dan setup replikasi PostgreSQL pada Centralized Enrollment System.
← Kembali ke CES
Konsep CES, arsitektur Master/Slave, dan panduan penggunaan.
Otentikasi
Cara memperoleh dan menggunakan Bearer token JWT.
Hampir semua endpoint memerlukan header Authorization: Bearer <token>. Satu pengecualian adalah POST /api/ces/metrics (pengiriman metrik dari Slave ke Master) yang menggunakan X-API-Key, dan GET /api/ces/ping yang tidak memerlukan autentikasi sama sekali. Basis URL mengikuti variabel lingkungan VITE_API_URL pada instalasi Lenz Anda.
Health Check
Endpoint ringan untuk memeriksa apakah node CES dapat dijangkau. Tidak memerlukan autentikasi — cocok untuk load balancer health probe.
Health Check
Response Body
application/json
curl -X GET "https://lenz.example.com/api/ces/ping"{ "ok": true, "message": "pong"}Konfigurasi
Mengambil konfigurasi CES aktif pada node saat ini: status aktif/nonaktif, mode operasi (master/slave), dan URL server Master. API Key tidak disertakan dalam respons.
Ambil Konfigurasi CES
Authorization
bearerAuth In: header
Response Body
application/json
application/json
curl -X GET "https://lenz.example.com/api/ces/config"{ "ok": true, "message": "successfully retrieved CES config", "result": { "ces_enabled": true, "ces_mode": "master", "ces_master_url": "http://master-gateway:6015" }}{ "ok": false, "message": "invalid request"}Monitoring Node
Endpoint untuk mengambil dan mengirimkan data metrik node CES.
GET /api/ces/metrics — diakses dari node Master untuk mendapatkan snapshot semua node (Master dan Slave) berikut daftar replication client PostgreSQL yang aktif.
POST /api/ces/metrics — dipanggil secara otomatis oleh scheduler internal node Slave setiap 1 menit. Gunakan endpoint ini jika Anda membangun integrasi kustom yang perlu melaporkan metrik ke Master.
POST /api/ces/metrics menggunakan autentikasi API Key (X-API-Key), bukan Bearer token. Pastikan nilai API Key yang digunakan sesuai dengan ces_master_api_key yang dikonfigurasi di node Master.
Ambil Metrik Semua Node
Authorization
bearerAuth In: header
Query Parameters
Filter node berdasarkan nama (mendukung regex)
ID instance pada mode Federation — mengarahkan query ke instance tertentu
Response Body
application/json
application/json
curl -X GET "https://lenz.example.com/api/ces/metrics"{ "ok": true, "message": "successfully retrieved CES metrics", "results": { "metrics": [ { "id": "20c9acbe", "name": "Master Gateway", "ip_address": "192.168.1.10", "total_enrollment": 1500, "is_master": true, "custom_fields": {}, "last_heartbeat": "2025-12-24T12:30:00Z", "created_at": "2025-12-24T10:00:00Z", "updated_at": "2025-12-24T12:30:00Z", "status": "online" }, { "id": "a1b2c3d4", "name": "Slave Node 1", "ip_address": "192.168.1.11", "total_enrollment": 500, "is_master": false, "custom_fields": { "location": "Gedung B" }, "last_heartbeat": "2025-12-24T12:29:00Z", "created_at": "2025-12-24T10:05:00Z", "updated_at": "2025-12-24T12:29:00Z", "status": "online" } ], "replication_clients": [ { "pid": 12345, "usename": "replication_user", "application_name": "lenz_ces_sub", "client_addr": "192.168.1.11", "client_port": 54321, "backend_start": "2025-12-24T10:05:00Z", "state": "streaming", "sent_lsn": "0/1A2B3C4D", "write_lsn": "0/1A2B3C4D", "flush_lsn": "0/1A2B3C4D", "replay_lsn": "0/1A2B3C4D", "write_lag": null, "flush_lag": null, "replay_lag": null, "sync_state": "async", "reply_time": "2025-12-24T12:30:00Z" } ] }}{ "ok": false, "message": "invalid request"}Kirim Metrik (Slave ke Master)
Authorization
apiKeyAuth In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
curl -X POST "https://lenz.example.com/api/ces/metrics" \ -H "Content-Type: application/json" \ -d '{ "name": "Slave Node 1", "ip_address": "192.168.1.11" }'{ "ok": true, "message": "metric received successfully"}{ "ok": false, "message": "failed to receive metric", "error": "node is not configured as CES master"}{ "ok": false, "message": "invalid request"}Replikasi Database
Endpoint untuk memeriksa status dan menjalankan setup replikasi logis PostgreSQL.
CES mereplikasi data di dua database sekaligus: Lenz (tabel enrolled_face, face_image) dan Fremis (tabel keyspaces, merged_vectors). Oleh karena itu, detail koneksi untuk kedua database diperlukan saat menjalankan setup.
Status Replikasi
Periksa status replikasi sebelum menjalankan setup. Respons berbeda tergantung mode node: node Master akan menampilkan status Publication, sementara node Slave menampilkan status Subscription.
Status Replikasi
Authorization
bearerAuth In: header
Response Body
application/json
application/json
curl -X GET "https://lenz.example.com/api/ces/replication/status"{ "ok": true, "message": "replication status retrieved", "result": { "mode": "master", "is_configured": true, "wal_level": { "current": "logical", "required": "logical", "is_set": true }, "max_replication_slots": { "current": 200, "required": 200, "is_set": true }, "publications": [ { "name": "lenz_ces_pub", "exists": true, "tables": [ "enrolled_face", "face_image" ] }, { "name": "fremis_ces_pub", "exists": true, "tables": [ "keyspaces", "merged_vectors" ] } ] }}{ "ok": false, "message": "invalid request"}Setup Replikasi
Jalankan konfigurasi replikasi PostgreSQL. Endpoint ini mendeteksi mode CES node secara otomatis dan menjalankan langkah yang sesuai.
Jika respons memuat "restart_required": true, PostgreSQL pada node tersebut harus di-restart agar perubahan pengaturan WAL (wal_level, max_replication_slots) mulai berlaku. Replikasi tidak akan aktif sebelum restart dilakukan.
Setup Replikasi
Authorization
bearerAuth In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
curl -X POST "https://lenz.example.com/api/ces/replication/setup" \ -H "Content-Type: application/json" \ -d '{ "fremis_local": { "host": "localhost", "port": 5432, "dbname": "fremis", "user": "postgres", "password": "password" } }'{ "ok": true, "message": "replication setup completed", "result": { "mode": "master", "wal_level": { "current": "replica", "required": "logical", "changed": true }, "max_replication_slots": { "current": 10, "required": 200, "changed": true }, "publications": [ { "name": "lenz_ces_pub", "exists": false, "created": true, "tables": [ "enrolled_face", "face_image" ] }, { "name": "fremis_ces_pub", "exists": false, "created": true, "tables": [ "keyspaces", "merged_vectors" ] } ], "restart_required": true }}{ "ok": false, "message": "failed to setup replication", "error": "CES is not enabled"}{ "ok": false, "message": "invalid request"}