Skip to Content
ReferenceFingerprint reader

Fingerprint reader client

Drives a USB fingerprint reader (the contactful path) via the SladeID companion application. See Use a USB fingerprint reader for the companion-app prerequisite, install links, and worked examples of enroll / verify / search.

import { createFingerprintReader, FingerprintReaderClient } from '@sladeid/slade-id-sdk'; const reader: FingerprintReaderClient = createFingerprintReader({ getToken: () => Promise.resolve('<bearer token>'), });

getToken is called on demand and again after a 401, so token rotation is transparent. Throwing inside it surfaces as a ReaderAuthError to the caller.

Methods

MethodReturnsNotes
reader.statusReaderStatusSynchronous snapshot from the last background poll.
refreshStatus()Promise<ReaderStatus>Force an immediate /status fetch (e.g. before a device picker).
enroll(input)Promise<EnrollmentResult>Register input.enrollee at input.position.
verify(input)Promise<VerificationResult>1:1 match against the claimed enrollee.
search()Promise<SearchResult>1:N identify against the enrolled corpus. No input.
fetchEnrolled(enrollee)Promise<EnrolledFingerprints>List a subject’s enrolled positions. No hardware/device needed.
testCapture(opts?)Promise<TestCaptureResult>Grab one frame; { normalized: true } for the preprocessed template.
createEnrollmentSession(input)EnrollmentSessionEvent-driven wrapper around enroll.
createVerificationSession(input)VerificationSessionEvent-driven wrapper around verify.
createSearchSession()SearchSessionEvent-driven wrapper around search.
dispose()voidStop polling, drop listeners. Subsequent actions throw.

Inputs

EnrollmentInput and VerificationInput share the same shape:

FieldTypeRequiredNotes
enrolleestringyesSubject identifier (e.g. beneficiary code).
positionFingerPosition (0–10)yes15 right hand, 610 left hand; 0 = minor / any.
isMinorbooleannoApply relaxed quality checks.
attachmentsRecord<string, string>noFree-form metadata forwarded to the backend (e.g. encounter ids).

search() takes no input — the capture itself is the query.

Results

interface EnrollmentResult { template?: string; // base64 template, when the service returns one verifiedPositions?: number[]; // positions the service confirmed raw: Record<string, unknown>; // untouched server payload } interface VerificationResult { matched: boolean; // false is a normal outcome, not an error matchLogId?: string; // present when matched; persist for audit verifiedPositions?: number[]; } interface SearchResult { found: boolean; // true only when an enrollee matched enrollee?: string; // the matched subject id (single best match, not a ranked list) raw: Record<string, unknown>; // any scoring fields (similarity, match_score) the backend returns } interface EnrolledFingerprints { verified: number[]; // positions already enrolled — safe to skip on resume nonVerified: number[]; // captured but not yet confirmed by the backend total: number; // total fingerprint records on file enrollmentStatus: 'fully_enrolled' | 'partially_enrolled'; notes?: string; // enrollment notes, when present raw: Record<string, unknown>; }

fetchEnrolled(enrollee) is a metadata lookup — it selects no device and resolves even with no scanner attached. Use it to resume a paused multi-finger enrollment: skip the verified positions and prompt only for what’s missing.

ReaderStatus

interface ReaderStatus { connected: boolean; // service reachable isAuthed: boolean; // service accepted the token devices: ReaderDevice[]; // scanners currently visible workstationId?: string; version?: string; lastError?: HwsError; // most recent poll failure; cleared on next success }

The action methods auto-select the first device, so most integrators never read devices — it’s exposed for rendering a device picker.

Client events

connected, disconnected (HwsError), device-attached (ReaderDevice), device-detached (ReaderDevice), poll-failed (HwsError).

poll-failed fires whenever a background /status poll fails — including the very first poll before the client ever went connected. It is de-duped by error code, so a stuck failure (e.g. an empty token) emits once rather than every 3s. The same error is also available synchronously on reader.status.lastError, which is cleared on the next successful poll.

Session events

Sessions are single-shot: call start() once, cancel() to abort an in-flight request. All three emit ready (just before the request goes out — cue “place finger”) and scanning (once in flight — cue spinner), then a terminal event. The terminal events differ per session type — note that verification and search split the outcome so a non-match never looks like an error:

SessionSuccess terminalNon-match terminalFailure terminalResult type
EnrollmentSessioncapturederrorEnrollmentResult
VerificationSessioncapturedmismatcherrorVerificationResult
SearchSessionfoundnot-founderrorSearchResult

error is reserved for transport, auth, device, and server failures (HwsError subclasses). A biometric non-match is delivered through mismatch / not-found, not error.

Errors

All reader errors extend HwsError (which extends SladeIDError) and carry code plus an optional correlationId.

ClassCode
ConnectionErrorREADER_CONNECTION_FAILED
TimeoutErrorREADER_TIMEOUT
ReaderAuthErrorREADER_AUTH_FAILED
DeviceUnavailableErrorREADER_DEVICE_UNAVAILABLE
ReaderValidationErrorREADER_VALIDATION_FAILED
ReaderServerErrorREADER_SERVER_ERROR
BiometricMismatchErrorREADER_BIOMETRIC_MISMATCH

BiometricMismatchError is thrown only by rejection-style helpers; the built-in verify() resolves with { matched: false } instead.