E-Pondok
← Home
Developer Reference

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.id for the public landing, signup, checkout, and these docs.
  • Platform. The platform.epondok.id subdomain for super-admins who manage accounts, subscriptions, and new pondok provisioning.
  • Tenant. The *.epondok.id subdomain for each pondok’s admin app (dashboard, attendance, visitors, and relations).

Roles

A person in a pondok has one of the following roles:

santriStudent
ustadzTeacher
staffOperational staff
pengurusPondok 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.

Moved to the Setup Guide

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.

enroll flow
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 by personId, role, from, and to.
  • 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_at tracks the last successful sync.
Globally unique device_uid

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.

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:

EntityKey fields
Personid, full_name, role, phone, active
EnrollmentRowperson_id, device_id, quality_score, active
AttendanceEventperson_id, ts, event_type(entry/exit), confidence, device_id
Visitorvisitor_no, name, category, purpose, arrival_ts, departure_ts
VisitContributiontype, topic, audience, participants, outcomes
RelationshipContactname, institution, status, tags
CollaborationTagslug, label
FollowUpcontact_id, due_date, assigned_to, status
Devicedevice_uid, public_key, status, bound_network, last_seen_at
Pondokid, slug, name, status
MutabaahEntryperson_id, template_id, entry_date, rating
Invoicenumber, person_id, amount, period, status
PayrollRunperiod, status(draft/locked), gross, deduction, net
Booktitle, author, type, copies(code, condition)
ClinicVisitperson_id, complaint, diagnosis, severity, outcome
GatePassperson_id, type, out_at, expected_return_at, status
Applicantfull_name, nisn, school_origin, status
Assetname, category, condition, location, status
Violationperson_id, code, points, occurred_at
LeaveRequestperson_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:

Paged<T>
{
"items":  T[],
"total":  number,
"limit":  number,
"offset": number
}

Example request with a token:

curl
curl -H "Authorization: Bearer <token>" "https://pondokabc.epondok.id/api/attendance?from=2026-01-01&limit=50"

Tenant routes

Authentication

POST/api/auth/loginPhone + password → { token, user }
POST/api/auth/magic/requestSend a magic-link to email
POST/api/auth/magic/verifyExchange magic-link token → { token, user }
GET/api/auth/meCurrent admin session

Dashboard

GET/api/dashboardAttendance, visitor, relation, follow-up summary

Pondok (public)

GET/api/pondoksPondok list for the landing directory

Persons

GET/api/personsList (Paged<Person>) — role, active, q
GET/api/persons/:idPerson detail
POST/api/personsCreate person (full_name, role, phone)
PATCH/api/persons/:idUpdate
DELETE/api/persons/:idDelete (soft delete)

Face enrollment

GET/api/persons/:id/enrollmentsPerson's enrollment history
POST/api/persons/:id/enrollmentsEnroll embedding (+ deviceId, qualityScore, checkDuplicates)
DELETE/api/persons/:id/enrollments/:eidDeactivate enrollment
POST/api/persons/:id/verify-faceMatch embedding vs person's enrollments

Attendance

GET/api/attendanceEvent list (Paged) — personId, role, from, to
GET/api/attendance/presenceWho is currently inside
GET/api/attendance/analyticsWindow analytics — daily, top late, most punctual

Visitors

GET/api/visitorsList (Paged) — category, from, to, open, q
GET/api/visitors/:idVisit detail
POST/api/visitorsCheck-in (name, phone, category, purpose, …)
POST/api/visitors/:id/checkoutCheck-out
GET/api/visitors/:id/contributionsVisit contributions
POST/api/visitors/:id/contributionsRecord contribution (type, topic)

Relations

GET/api/contactsContact list (Paged) — q, status, institution, tag
GET/api/contacts/:idContact detail
POST/api/contactsCreate contact (name, phone)
PATCH/api/contacts/:idUpdate
POST/api/contacts/:id/tagsAttach tag (slug)
DELETE/api/contacts/:id/tags/:slugDetach tag
GET/api/contacts/:id/follow-upsContact follow-ups

Follow-ups

GET/api/follow-upsList (Paged) — status, overdue
POST/api/follow-upsCreate (contact_id, due_date, assigned_to)
PATCH/api/follow-ups/:idUpdate status / due date

Tags

GET/api/tagsList collaboration tags
POST/api/tagsCreate tag (slug, label)

Devices

GET/api/devicesList (Paged) — q, status (admin)
POST/api/devices/registerRegister kiosk (device_uid, public_key, bound_network)
POST/api/devices/:id/revokeRevoke access
POST/api/devices/:id/activateReactivate

Academic

GET/api/academic/cohortsCohort list (classes / halaqah)
POST/api/academic/cohortsCreate cohort
POST/api/academic/cohorts/importBulk-import cohort members (CSV)
GET/api/academic/hafalanQur'an memorization records (Paged)
POST/api/academic/hafalanRecord a memorization deposit
GET/api/academic/rapor-periodsReport-card periods
POST/api/academic/rapor-periodsCreate report-card period

Mutaba'ah (daily deeds)

GET/api/mutabaah/templatesDaily-deed templates (per pondok)
POST/api/mutabaah/templatesCreate template (name, category, unit, target)
GET/api/mutabaah/entriesDaily deed entries (Paged)
POST/api/mutabaah/entriesRecord an entry (rating or check)
GET/api/mutabaah/summaryPer-student report: streaks, per-deed progress, avg rating

Payroll

GET/api/payroll/profilesStaff payroll profiles
POST/api/payroll/profilesCreate payroll profile (base salary)
POST/api/payroll/runs/generateGenerate a payroll run from real attendance (period)
GET/api/payroll/runsPayroll runs with totals
POST/api/payroll/runs/:id/lockLock a run and email payslips

Parent notifications

GET/api/notifications/settingsParent notification settings
PATCH/api/notifications/settingsUpdate settings (check-in/out, photo, channels)
GET/api/notifications/logDelivery log — every notification with status
POST/api/notifications/telegram/connectStart Telegram link flow

API keys

GET/api/api-keysList API keys (label, prefix, last used)
POST/api/api-keysMint an API key (label) — shown once
POST/api/api-keys/revokeRevoke an API key

Library

GET/api/perpustakaan/booksBook catalog (Paged) — type, q
POST/api/perpustakaan/booksCreate book (title, author, type)
POST/api/perpustakaan/copiesAdd a physical copy (code, condition, location)
POST/api/perpustakaan/loans/borrowLoan a copy (due date)
POST/api/perpustakaan/loans/:id/returnReturn a loan
POST/api/perpustakaan/reservationsReserve a book

Clinic & health

GET/api/kesehatan/visitsClinic visits (Paged)
POST/api/kesehatan/visitsRecord a clinic visit (complaint → treatment)
POST/api/kesehatan/medicationsLog medication given
POST/api/kesehatan/incidentsRecord an incident
POST/api/kesehatan/immunizationsRecord an immunization

Dormitory

GET/api/asrama/buildingsDormitory buildings
POST/api/asrama/buildingsCreate building
POST/api/asrama/roomsCreate room (capacity)
POST/api/asrama/bedsCreate bed
POST/api/asrama/beds/:id/assignAssign a student to a bed
POST/api/asrama/gate-passesCreate a gate pass (type, return time)
POST/api/asrama/gate-passes/:id/approveApprove a gate pass

Admission (PPDB)

GET/api/ppdb/applicantsApplicant list (Paged) — status, q
POST/api/ppdb/applyPublic application (rate-limited)
POST/api/ppdb/applicants/:id/acceptAccept → student + enrollment invoice
POST/api/ppdb/applicants/:id/rejectReject applicant
PUT/api/ppdb/settingsEnrollment period & settings

Finance & billing

GET/api/finance/fee-itemsFee items (SPP, enrollment fee, …)
POST/api/finance/fee-itemsCreate fee item (amount, recurrence)
GET/api/finance/invoicesInvoices (Paged) — status, period
POST/api/finance/invoicesCreate an invoice
POST/api/finance/invoices/generateGenerate invoices for a period & cohort
POST/api/finance/paymentsRecord a payment (method, reference)
GET/api/finance/arrearsArrears recap per student
POST/api/finance/dunning/runRun payment reminders (review or auto)

Conduct (tata tertib)

GET/api/tata-tertib/catalogViolation catalog (codes & default points)
POST/api/tata-tertib/catalogAdd a violation article
POST/api/tata-tertib/violationsRecord a violation (points, date)
GET/api/tata-tertib/pointsCumulative points per student
POST/api/tata-tertib/sanctionsCreate a sanction (warning → suspension)

Inventory

GET/api/inventaris/assetsAsset list (Paged) — category, location
POST/api/inventaris/assetsCreate asset (condition, value)
POST/api/inventaris/loans/borrowLoan an asset (due date)
POST/api/inventaris/loans/:id/returnReturn an asset
POST/api/inventaris/movementsRecord a location/status movement

Leave permits

GET/api/keperizinanLeave requests (Paged) — type, status
POST/api/keperizinanCreate a leave request (type, dates, reason)
POST/api/keperizinan/:id/approveApprove (notifies the parent)
POST/api/keperizinan/:id/rejectReject with a note
POST/api/keperizinan/:id/returnRecord actual return time

EMIS reporting

GET/api/emis/santri/hygienePer-student data completeness flags
GET/api/emis/santri/exportCSV in documented EMIS column order
GET/api/emis/santri/rowsExport rows as JSON (with NIK) for the in-browser .xlsx export / template autofill

AI assistant

GET/api/asisten/briefAI anomaly summary (attendance, memorization, clinic)
GET/api/asisten/kitab/corpusKitab corpus documents with ingest status
POST/api/asisten/kitab/corpusUpload a kitab (PDF with text layer, DOCX, TXT, MD)
POST/api/asisten/kitab/corpus/:id/processAdvance ingest by one step (extract → index)
DELETE/api/asisten/kitab/corpus/:idRemove a document, its chunks, and its vectors
POST/api/asisten/kitab/sessionsCreate a chat session (private to the caller)
POST/api/asisten/kitab/sessions/:id/askAsk the kitab (SSE stream with cited passages)

Platform routes (apex)

Platform (apex)

Platform admins only. Token is separate from tenant — apex & subdomain are different origins.
POST/api/platform/registerRegister platform account (name, email, password)
POST/api/platform/loginPlatform login
POST/api/platform/magic/requestPlatform magic-link
POST/api/platform/magic/verifyVerify platform magic-link
GET/api/platform/meCurrent platform session
GET/api/platform/slug/checkCheck pondok slug availability
POST/api/platform/checkoutCreate a checkout session (seats)
GET/api/platform/pondokList pondok owned by the account
POST/api/platform/pondokCreate a new pondok (slug, name)
PATCH/api/platform/pondok/:idUpdate pondok name / status
Device-authed routes

The kiosk & sync routes are used by kiosks with device signatures, not admin tokens. Not documented for direct use.