E-Pondok Developer Reference
The technical side of E-Pondok — concepts, the data model, the face check-in pipeline, security internals, architecture, and the full HTTP API. For step-by-step product setup, see the Setup Guide.
Introduction
E-Pondok is a presence & relations system for the modern pondok. A browser camera at the gate records who comes and goes, a digital guest book manages visits, and the dashboard weaves that data into reports and a living map of institutional relationships.
Built for the realities of a pondok: it grows with many pondok (multi-tenancy) and keeps things secure without heavy operational burden.
What you get
- Touchless face attendance with automatic entry/exit detection, plus an offline kiosk for the gate.
- Anti-spoofing — rejects photos, videos, and fake face masks.
- Academics: cohorts, memorization, report cards, and daily-deed tracking with per-student reports.
- Finance & payroll: SPP invoices, QRIS/transfer payments, emailed receipts, payroll from real attendance.
- Pondok modules: library, clinic, dormitory, online admission, conduct, inventory, permits, EMIS, and an AI assistant.
- Digital guest book with categories, purpose, and visit contributions.
- Automatic parent updates: an email on every check-in/check-out, proof photo included.
- Summary dashboard + attendance analytics.
- Passwordless magic-link login for every user.
Core concepts
Pondok = tenant
One pondok is one isolated tenant. Every pondok gets its own subdomain, e.g. pondokabc.epondok.id. Its data never mixes with another pondok’s, even though they share one database cluster.
Three surfaces
- Apex. The parent domain
epondok.idfor the public landing, signup, checkout, and these docs. - Platform. The
platform.epondok.idsubdomain for super-admins who manage accounts, subscriptions, and new pondok provisioning. - Tenant. The
*.epondok.idsubdomain for each pondok’s admin app (dashboard, attendance, visitors, and relations).
Roles
A person in a pondok has one of the following roles:
| santri | Student |
| ustadz | Teacher |
| staff | Operational staff |
| pengurus | Pondok committee |
App-level admin roles: admin (full access including Payroll & Finance), pengurus, and platform (super-admin at apex).
Quick start
From zero to automatic attendance in five steps.
The five-step product walkthrough (register → subscribe → create pondok → enroll a face from the browser → live), with live previews of every form, now lives in the Setup Guide. This page keeps the technical reference.
Dashboard
The tenant home page. A real-time summary across all modules. Data source: GET /api/dashboard.
Summary cards
- Attendance — present today, absent, late, total population, daily trend.
- Visitors — visits today, this month, lecturer visits over 3 years.
- Relations — new, active partners, potential, strategic, alumni network.
- Follow-ups — number due.
Persons & enrollment
Person = every individual in the pondok (santri, ustadz, staff, pengurus). Full CRUD via /api/persons.
Face enrollment
Enrollment captures a face, converts it to a 512-dimensional embedding, then stores it as an indexed per-pondok template. On enroll, the checkDuplicates option prevents the same face from being registered twice, and qualityScore records capture quality.
capture frame
→ anti-spoofing check // reject photo/video/mask
→ 512-d face template
→ POST /api/persons/:id/enrollments
{ embedding, deviceId, qualityScore, checkDuplicates: true } -
POST /api/persons/:id/verify-face. Match a new embedding against the person’s enrollments. -
DELETE /api/persons/:id/enrollments/:eid. Deactivate an old enrollment rather than deleting it permanently.
Attendance
The product’s core. The check-in camera — the web Check-in page on any webcam device — captures a face at the gate → matches it against the pondok’s face index → entry/exit direction is detected automatically → the event is stored with a confidence score (confidence) and, when applicable, a device id (device_id).
Queries
-
GET /api/attendance. Event list (Paged), filterable bypersonId,role,from, andto. -
GET /api/attendance/presence. Who is currently inside. -
GET /api/attendance/analytics. Daily in/out totals, most-late, most-punctual, with time-range and role filters.
Visitors
The digital guest book. Every visit carries a category, a purpose, check-in/out times, and a visitor number (visitor_no).
Categories
parent_guardianlecturerteachergovernment_officialcommunity_leaderalumnivendorgeneralother
Visit contributions
Each visit can record a contribution for reporting — workshop, guest_lecture, training, mentoring, community_service, research_collaboration, recruitment_opportunity, or other — with topic, audience, participants, and outcomes.
Institutional relations
The pondok’s living institutional network, kept traceable over time.
Contacts
RelationshipContact stores name, institution, title, expertise, status (new / active / potential / alumni / strategic), and notes.
Collaboration tags
CollaborationTag (slug + label) can be attached or removed from contacts to group partners, e.g. guest-teacher and scholarship.
Follow-ups
Scheduled follow-ups: contact_id, due_date, assigned_to, status (open / in_progress / completed / cancelled). The overdue filter highlights what’s past due.
Pondok modules
Every module below follows the same pattern: a paginated list (Paged<T>), writes via POST/PATCH, soft delete (trash + restore), and CSV export. Full routes are in the API reference tables below. Modules tied to a plan tier answer 402 payment_required when the pondok’s plan doesn’t cover them.
Academic
/api/academic — cohorts (classes / halaqah) with bulk import, memorization records per student, and report-card periods.
Mutaba’ah (daily deeds)
/api/mutabaah — pondok-owned daily-deed templates, per-student entries with ratings, and GET /summary for the per-student report: current streak, longest streak, per-deed progress, and average rating.
Payroll
/api/payroll — staff salary profiles, payroll runs generated per period from real attendance (including late deductions), then lock & email payslips.
Parent notifications
/api/notifications — automatic emails on student check-in/check-out (optionally with a proof photo), Email/WhatsApp/Telegram channels, and a delivery log with per-notification status.
Library
/api/perpustakaan — book catalog, per-copy codes, due-dated loans + email reminders, and reservations.
Clinic & health (UKS)
/api/kesehatan — clinic visits (complaint → diagnosis → treatment), medication given, incidents, and immunizations.
Dormitory
/api/asrama — building → room → bed, student placement, and gate passes (leave / home visit) with approval.
Admission (PPDB)
/api/ppdb — a public application form on the pondok’s subdomain, applicant review, accept (becomes a student + enrollment invoice), and period settings.
Finance
/api/finance — fee items, per-period invoices (auto-generated per cohort), multi-method payments with emailed receipts, arrears recap, and payment reminders.
Conduct (tata tertib)
/api/tata-tertib — a point-based violation catalog, incident logging, cumulative points per student, and graduated sanctions.
Inventory
/api/inventaris — assets with condition/location/value, asset lending, and a movement log.
Leave permits
/api/keperizinan — home-leave/out-pass/sick requests with request → approve/reject → return flow, plus parent notification.
EMIS
/api/emis — student data completeness checks for EMIS reporting (flags only, no NIK/NISN values), a CSV export in documented column order, and /api/emis/santri/rows (JSON, includes NIK; admin/pengurus only) which the dashboard uses to build the .xlsx export and fill an uploaded EMIS template in the browser.
AI assistant
/api/asisten — student anomaly summaries from attendance/memorization/clinic data (/brief), and Ask the Kitab under /api/asisten/kitab: upload and manage the kitab corpus, then ask questions answered with references (answers stream over SSE).
Devices
Device management API for hardware clients. Attendance currently runs web-first, so the Devices page is hidden in the admin app and no device registration is needed for daily use. Every registered kiosk has its own unique identity and key; each sync request is verified before processing, and a revoked kiosk is rejected outright.
-
POST /api/devices/register. Register a new kiosk. -
POST /api/devices/:id/revoke. Revoke access so the kiosk can no longer sync. -
POST /api/devices/:id/activate. Reactivate a kiosk. -
last_seen_attracks the last successful sync.
device_uid is unique across all pondok (not per-pondok). Never reuse the same UID for two kiosks.
Admin platform
The platform surface (platform.epondok.id) is the super-admin space for provisioning new pondok, managing subscriptions, and changing pondok status (active / suspended). Platform tokens are separate from tenant tokens because the two live on different origins.
Multi-pondok
One system, many pondok. Each pondok gets its own subdomain and isolated data. Access is enforced in the platform’s data layer — no tenant endpoint can read another pondok’s records.
Magic-link login
Passwordless login: request a link by email, click to sign in. Links are single-use and expire quickly. A password remains available as a fallback for platform admins.
Tenant isolation
Pondok isolation is layered: subdomain → pondok resolution, pondok_id on every row, and the pondok id carried inside each token. No tenant endpoint can read another pondok’s data. All traffic is encrypted in transit (TLS).
Security & data privacy
Your pondok’s data is a trust. The principles we keep:
- Tenant isolation. Your pondok’s data can never be read by another pondok — enforced in the access layer, not just the UI.
- Encrypted in transit. All traffic runs over TLS.
- Face = template, not photo. What’s stored is a 512-dimensional mathematical template that cannot be reversed into a face image. Templates are per-pondok and can be deactivated at any time.
- Anti-spoofing. Frames are checked by an anti-spoofing model before processing; printed photos, videos, and masks are rejected.
- On-device face processing. Detection and template creation run locally in the gate’s browser/device — raw images are never shared with third parties.
- Soft delete + archive. Deleted data is recoverable during the trash window, then disappears from every list.
- Sensitive data stays home. NIK and NISN appear only in admin/pengurus EMIS downloads and are never sent to Kemenag or any third party; an uploaded EMIS template is filled in the browser, not on our server.
Face anti-spoofing
Before a face template is created, the frame is checked by an anti-spoofing model to tell a real face apart from a photo, video, or mask. Only a real face is processed further. The check runs on the gate device (web or kiosk) without sending images to any third party.
Data model
Core entities and their key fields:
| Entity | Key fields |
|---|---|
| Person | id, full_name, role, phone, active |
| EnrollmentRow | person_id, device_id, quality_score, active |
| AttendanceEvent | person_id, ts, event_type(entry/exit), confidence, device_id |
| Visitor | visitor_no, name, category, purpose, arrival_ts, departure_ts |
| VisitContribution | type, topic, audience, participants, outcomes |
| RelationshipContact | name, institution, status, tags |
| CollaborationTag | slug, label |
| FollowUp | contact_id, due_date, assigned_to, status |
| Device | device_uid, public_key, status, bound_network, last_seen_at |
| Pondok | id, slug, name, status |
| MutabaahEntry | person_id, template_id, entry_date, rating |
| Invoice | number, person_id, amount, period, status |
| PayrollRun | period, status(draft/locked), gross, deduction, net |
| Book | title, author, type, copies(code, condition) |
| ClinicVisit | person_id, complaint, diagnosis, severity, outcome |
| GatePass | person_id, type, out_at, expected_return_at, status |
| Applicant | full_name, nisn, school_origin, status |
| Asset | name, category, condition, location, status |
| Violation | person_id, code, points, occurred_at |
| LeaveRequest | person_id, type, from_date, to_date, status |
All tenant entities also carry pondok_id for isolation.
API reference
JSON API behind the app. Session tokens and API keys both authenticate — create a key under Settings → API keys and send X-API-Key: pk_live_… per request to the pondok subdomain. Keys are shown once at creation and revocable anytime. Plan-gated modules answer 402 payment_required. Every list route returns a paginated envelope:
{
"items": T[],
"total": number,
"limit": number,
"offset": number
} Example request with a token:
curl -H "Authorization: Bearer <token>" "https://pondokabc.epondok.id/api/attendance?from=2026-01-01&limit=50" Tenant routes
Authentication
/api/auth/loginPhone + password → { token, user }/api/auth/magic/requestSend a magic-link to email/api/auth/magic/verifyExchange magic-link token → { token, user }/api/auth/meCurrent admin sessionDashboard
/api/dashboardAttendance, visitor, relation, follow-up summaryPondok (public)
/api/pondoksPondok list for the landing directoryPersons
/api/personsList (Paged<Person>) — role, active, q/api/persons/:idPerson detail/api/personsCreate person (full_name, role, phone)/api/persons/:idUpdate/api/persons/:idDelete (soft delete)Face enrollment
/api/persons/:id/enrollmentsPerson's enrollment history/api/persons/:id/enrollmentsEnroll embedding (+ deviceId, qualityScore, checkDuplicates)/api/persons/:id/enrollments/:eidDeactivate enrollment/api/persons/:id/verify-faceMatch embedding vs person's enrollmentsAttendance
/api/attendanceEvent list (Paged) — personId, role, from, to/api/attendance/presenceWho is currently inside/api/attendance/analyticsWindow analytics — daily, top late, most punctualVisitors
/api/visitorsList (Paged) — category, from, to, open, q/api/visitors/:idVisit detail/api/visitorsCheck-in (name, phone, category, purpose, …)/api/visitors/:id/checkoutCheck-out/api/visitors/:id/contributionsVisit contributions/api/visitors/:id/contributionsRecord contribution (type, topic)Relations
/api/contactsContact list (Paged) — q, status, institution, tag/api/contacts/:idContact detail/api/contactsCreate contact (name, phone)/api/contacts/:idUpdate/api/contacts/:id/tagsAttach tag (slug)/api/contacts/:id/tags/:slugDetach tag/api/contacts/:id/follow-upsContact follow-upsFollow-ups
/api/follow-upsList (Paged) — status, overdue/api/follow-upsCreate (contact_id, due_date, assigned_to)/api/follow-ups/:idUpdate status / due dateTags
/api/tagsList collaboration tags/api/tagsCreate tag (slug, label)Devices
/api/devicesList (Paged) — q, status (admin)/api/devices/registerRegister kiosk (device_uid, public_key, bound_network)/api/devices/:id/revokeRevoke access/api/devices/:id/activateReactivateAcademic
/api/academic/cohortsCohort list (classes / halaqah)/api/academic/cohortsCreate cohort/api/academic/cohorts/importBulk-import cohort members (CSV)/api/academic/hafalanQur'an memorization records (Paged)/api/academic/hafalanRecord a memorization deposit/api/academic/rapor-periodsReport-card periods/api/academic/rapor-periodsCreate report-card periodMutaba'ah (daily deeds)
/api/mutabaah/templatesDaily-deed templates (per pondok)/api/mutabaah/templatesCreate template (name, category, unit, target)/api/mutabaah/entriesDaily deed entries (Paged)/api/mutabaah/entriesRecord an entry (rating or check)/api/mutabaah/summaryPer-student report: streaks, per-deed progress, avg ratingPayroll
/api/payroll/profilesStaff payroll profiles/api/payroll/profilesCreate payroll profile (base salary)/api/payroll/runs/generateGenerate a payroll run from real attendance (period)/api/payroll/runsPayroll runs with totals/api/payroll/runs/:id/lockLock a run and email payslipsParent notifications
/api/notifications/settingsParent notification settings/api/notifications/settingsUpdate settings (check-in/out, photo, channels)/api/notifications/logDelivery log — every notification with status/api/notifications/telegram/connectStart Telegram link flowAPI keys
/api/api-keysList API keys (label, prefix, last used)/api/api-keysMint an API key (label) — shown once/api/api-keys/revokeRevoke an API keyLibrary
/api/perpustakaan/booksBook catalog (Paged) — type, q/api/perpustakaan/booksCreate book (title, author, type)/api/perpustakaan/copiesAdd a physical copy (code, condition, location)/api/perpustakaan/loans/borrowLoan a copy (due date)/api/perpustakaan/loans/:id/returnReturn a loan/api/perpustakaan/reservationsReserve a bookClinic & health
/api/kesehatan/visitsClinic visits (Paged)/api/kesehatan/visitsRecord a clinic visit (complaint → treatment)/api/kesehatan/medicationsLog medication given/api/kesehatan/incidentsRecord an incident/api/kesehatan/immunizationsRecord an immunizationDormitory
/api/asrama/buildingsDormitory buildings/api/asrama/buildingsCreate building/api/asrama/roomsCreate room (capacity)/api/asrama/bedsCreate bed/api/asrama/beds/:id/assignAssign a student to a bed/api/asrama/gate-passesCreate a gate pass (type, return time)/api/asrama/gate-passes/:id/approveApprove a gate passAdmission (PPDB)
/api/ppdb/applicantsApplicant list (Paged) — status, q/api/ppdb/applyPublic application (rate-limited)/api/ppdb/applicants/:id/acceptAccept → student + enrollment invoice/api/ppdb/applicants/:id/rejectReject applicant/api/ppdb/settingsEnrollment period & settingsFinance & billing
/api/finance/fee-itemsFee items (SPP, enrollment fee, …)/api/finance/fee-itemsCreate fee item (amount, recurrence)/api/finance/invoicesInvoices (Paged) — status, period/api/finance/invoicesCreate an invoice/api/finance/invoices/generateGenerate invoices for a period & cohort/api/finance/paymentsRecord a payment (method, reference)/api/finance/arrearsArrears recap per student/api/finance/dunning/runRun payment reminders (review or auto)Conduct (tata tertib)
/api/tata-tertib/catalogViolation catalog (codes & default points)/api/tata-tertib/catalogAdd a violation article/api/tata-tertib/violationsRecord a violation (points, date)/api/tata-tertib/pointsCumulative points per student/api/tata-tertib/sanctionsCreate a sanction (warning → suspension)Inventory
/api/inventaris/assetsAsset list (Paged) — category, location/api/inventaris/assetsCreate asset (condition, value)/api/inventaris/loans/borrowLoan an asset (due date)/api/inventaris/loans/:id/returnReturn an asset/api/inventaris/movementsRecord a location/status movementLeave permits
/api/keperizinanLeave requests (Paged) — type, status/api/keperizinanCreate a leave request (type, dates, reason)/api/keperizinan/:id/approveApprove (notifies the parent)/api/keperizinan/:id/rejectReject with a note/api/keperizinan/:id/returnRecord actual return timeEMIS reporting
/api/emis/santri/hygienePer-student data completeness flags/api/emis/santri/exportCSV in documented EMIS column order/api/emis/santri/rowsExport rows as JSON (with NIK) for the in-browser .xlsx export / template autofillAI assistant
/api/asisten/briefAI anomaly summary (attendance, memorization, clinic)/api/asisten/kitab/corpusKitab corpus documents with ingest status/api/asisten/kitab/corpusUpload a kitab (PDF with text layer, DOCX, TXT, MD)/api/asisten/kitab/corpus/:id/processAdvance ingest by one step (extract → index)/api/asisten/kitab/corpus/:idRemove a document, its chunks, and its vectors/api/asisten/kitab/sessionsCreate a chat session (private to the caller)/api/asisten/kitab/sessions/:id/askAsk the kitab (SSE stream with cited passages)Platform routes (apex)
Platform (apex)
/api/platform/registerRegister platform account (name, email, password)/api/platform/loginPlatform login/api/platform/magic/requestPlatform magic-link/api/platform/magic/verifyVerify platform magic-link/api/platform/meCurrent platform session/api/platform/slug/checkCheck pondok slug availability/api/platform/checkoutCreate a checkout session (seats)/api/platform/pondokList pondok owned by the account/api/platform/pondokCreate a new pondok (slug, name)/api/platform/pondok/:idUpdate pondok name / statusThe kiosk & sync routes are used by kiosks with device signatures, not admin tokens. Not documented for direct use.