Quickstart¶
1. Install and configure¶
pip install "django-fingerprint-attendance[celery,filters,openapi]"
INSTALLED_APPS = [..., "rest_framework", "fingerprint_attendance"]
USE_TZ = True
TIME_ZONE = "Africa/Lagos" # used as the default device timezone
FINGERPRINT_ATTENDANCE = {
"EMPLOYEE_MODEL": "hr.Employee", # optional; default AUTH_USER_MODEL
"EMPLOYEE_LOOKUP_FIELD": "staff_number", # how the API identifies employees
"TEMPLATE_ENCRYPTION_KEYS": [os.environ["FPA_KEY"]],
}
Choose EMPLOYEE_MODEL before the first migrate
Like AUTH_USER_MODEL, the enrollee → employee foreign key is created by the first
migration. The package's migrations never change when you pick a different model, but
switching models later requires a manual data migration.
Any setting can also come from the environment: FPA_TEMPLATE_ENCRYPTION_KEYS=key1,key2,
FPA_ADMS_URL_PREFIX=iclock/, and so on.
2. URLs and database¶
urlpatterns = [
path("", include("fingerprint_attendance.urls")), # /iclock/... and /api/fingerprint/v1/...
]
python manage.py fpa_generate_key # store it in FPA_KEY
python manage.py migrate
python manage.py check # fpa.E0xx errors explain misconfiguration
3. Connect a device¶
Follow ADMS device setup. The device registers itself as
pending_approval. Approve it:
from fingerprint_attendance import services
services.approve_device(Device.objects.get(serial_number="CKJF123456"), by=request.user)
Approval backfills every in-scope enrollee onto the device.
4. Enroll people¶
enrollee = services.create_enrollee(employee) # device PIN auto-generated
services.give_consent(enrollee, version="2026-01", method="paper", by=request.user)
# a) at the device: the admin enrolls PIN <enrollee.device_pin> from the menu, or
# b) remotely:
services.start_enrollment_session(enrollee, device=device, fingers=[6, 1])
# c) at an HR desk with a USB reader: see the agent guide
The template is stored encrypted and queued to every other device in scope.
5. Consume punches¶
from fingerprint_attendance.signals import punch_received
@receiver(punch_received)
def on_punch(sender, punch, payload, **kwargs):
notify_dashboard(payload)
or GET /api/fingerprint/v1/punches/latest/?after=<sequence> for polling, webhooks, or the
WebSocket consumer. Daily results are in AttendanceDay
(GET /api/fingerprint/v1/attendance-days/).
6. Periodic jobs¶
With Celery:
from fingerprint_attendance.tasks.celery import beat_schedule
app.conf.beat_schedule = {**app.conf.beat_schedule, **beat_schedule()}
FINGERPRINT_ATTENDANCE["TASK_BACKEND"] = "celery"
Without Celery, run the commands from cron: fpa_check_devices (every minute),
fpa_expire_commands and fpa_retry_commands (every few minutes),
fpa_generate_absences (daily), and fpa_purge_retention (daily).