npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rdhiq/rdh-fp

v1.3.7

Published

React SDK for fingerprint capture, validation and submission via Neurotechnology Device Server

Readme

@rdhiq/rdh-fp

React SDK for fingerprint capture, validation, enrollment, verification, identification, transaction browsing, and fingerprint image previewing with Neurotechnology Device Server and RD.FingerPrint.API middleware.

Installation

npm install @rdhiq/rdh-fp
yarn add @rdhiq/rdh-fp
bun add @rdhiq/rdh-fp

Peer dependencies:

npm install react react-dom

Basic Setup

Import the package CSS once, then mount FingerprintProvider around any SDK components.

import "@rdhiq/rdh-fp/style.css";
import {
  FingerprintProvider,
  FingerprintModal,
  FingerprintButtonEnroll,
  FingerprintButtonVerify,
  FingerprintButtonIdentify,
  FingerprintButtonUpsert,
} from "@rdhiq/rdh-fp";

export default function App() {
  return (
    <FingerprintProvider
      initialConfig={{
        deviceServer: {
          baseUrl: "http://127.0.0.1",
          port: 8041,
        },
        middleware: {
          baseUrl: "http://10.254.210.55:5000",
          userId: "EMP-1001",
          callerSystem: "notary-web",
        },
      }}
      onSuccess={(result) => console.log("Capture success", result)}
      onError={(message, result) => console.error("Capture error", message, result)}
    >
      <FingerprintButtonEnroll params={{ personId: "P-001", nationalId: "11000345678901001" }}>
        Enroll
      </FingerprintButtonEnroll>

      <FingerprintButtonVerify params={{ personId: "P-001" }}>
        Verify
      </FingerprintButtonVerify>

      <FingerprintButtonUpsert params={{ personId: "P-001", nationalId: "11000345678901001" }}>
        Upsert
      </FingerprintButtonUpsert>

      <FingerprintButtonIdentify params={{ topK: 5 }}>
        Identify
      </FingerprintButtonIdentify>

      <FingerprintModal />
    </FingerprintProvider>
  );
}

FingerprintModal should be mounted once inside the provider. The buttons and hook open that modal in the correct operation mode.

Provider Configuration

FingerprintProvider merges defaults, saved browser settings, and initialConfig. Use the designSystem prop when the host app should control package colors and spacing from code.

<FingerprintProvider
  designSystem={{
    preset: "biometric",
    density: "comfortable",
    radius: 10,
    colors: {
      primary: "#14b8a6",
      secondary: "#4f46e5",
      success: "#16a34a",
      warning: "#d97706",
      danger: "#e11d48",
      surface: "#0b1320",
      surfaceAlt: "#121d2e",
      text: "#eef7f5",
      textMuted: "#9eb3c2",
    },
  }}
  initialConfig={{
    deviceServer: {
      baseUrl: "http://127.0.0.1",
      port: 8041,
      deviceId: null,
      timeoutMs: 15000,
    },
    middleware: {
      baseUrl: "https://your-middleware.example.com",
      userId: "EMP-1001",
      callerSystem: "notary-web",
      accessToken: undefined,
      apiKey: undefined,
    },
  }}
>
  {children}
</FingerprintProvider>

Design System

designSystem accepts preset, density, radius, and partial colors. Presets are biometric, civic, ocean, and slate; use custom when you want to provide your own palette.

Device Server

| Field | Type | Description | | --- | --- | --- | | baseUrl | string | Device Server host, usually http://127.0.0.1 | | port | number | Device Server port | | deviceId | string \| null | Selected scanner device | | timeoutMs | number | Request timeout in milliseconds | | captureParams | Record<string, unknown> | Optional Device Server capture configuration |

Middleware

| Field | Type | Description | | --- | --- | --- | | baseUrl | string | RD.FingerPrint.API base URL | | userId | string | Operator id, sent as x-user-id | | callerSystem | string | Client application id, sent as x-caller-system | | accessToken | string \| null | Optional bearer token | | apiKey | string \| null | Optional API key, sent as x-api-key when no bearer token is used |

Operation Params

All capture buttons and hook methods accept CaptureOperationParams without the internal mode field.

const operationParams = {
  personId: "A4412188-A29C-48BE-8136-536D6B235009",
  transactionId: "SALE-2026-1009",
  nationalId: "11000345678901009",
  userId: "EMP-1001",
  transactionName: "Fingerprint demo transaction",
  debug: true,
};

Common fields:

| Field | Type | Description | | --- | --- | --- | | requestId | string | Optional host request id. If omitted, the SDK generates one. | | personId | string | Person identifier for enroll, verify, update, and upsert. | | transactionId | string | Business transaction id. | | nationalId | string | National identity document id. | | fullName | string | Person full name. | | citizenName | string | Person display name shown in the modal. | | employeeName | string | Operator display name shown in the modal. | | transactionName | string | Transaction display name shown in the modal and sent to middleware. | | transactionType | string | Optional transaction type/category. | | userId | string | User/operator id for this operation. | | projectId | string | Optional project id. | | fingerIndex | number | ANSI/NIST finger position code. | | fingerPositions | FingerPosition[] | One or more selected finger positions. | | fingers | FingerConfig[] | Custom finger selector labels, ids, and selectable flags. | | threshold | number | Verification/identification threshold. | | topK | number | Number of identify candidates to return. | | allowReducedAcceptance | boolean | Allow reduced mode when validation rules permit it. | | overrideToken | string | Backend override token for reduced acceptance. | | debug | boolean | Show the modal debug panel. |

Capture Buttons

<FingerprintButtonEnroll params={operationParams}>
  Enroll
</FingerprintButtonEnroll>

<FingerprintButtonVerify params={operationParams}>
  Verify
</FingerprintButtonVerify>

<FingerprintButtonUpsert params={operationParams}>
  Upsert
</FingerprintButtonUpsert>

<FingerprintButtonIdentify params={{ ...operationParams, topK: 5 }}>
  Identify
</FingerprintButtonIdentify>

Each button also accepts normal button props plus per-call callbacks:

<FingerprintButtonUpsert
  params={operationParams}
  onSuccess={(result) => console.log("Upsert success", result)}
  onError={(message, result) => console.error("Upsert failed", message, result)}
>
  Upsert
</FingerprintButtonUpsert>

Programmatic Usage

Use useFingerprint() inside FingerprintProvider.

import { useFingerprint } from "@rdhiq/rdh-fp";

function CaptureActions() {
  const {
    openEnroll,
    openVerify,
    openUpsert,
    openIdentify,
    isModalOpen,
    lastResult,
  } = useFingerprint();

  return (
    <>
      <button disabled={isModalOpen} onClick={() => openEnroll({ personId: "P-001" })}>
        Enroll
      </button>

      <button disabled={isModalOpen} onClick={() => openVerify({ personId: "P-001" })}>
        Verify
      </button>

      <button
        disabled={isModalOpen}
        onClick={() =>
          openUpsert(
            { personId: "P-001", nationalId: "11000345678901001" },
            { onSuccess: (result) => console.log(result) },
          )
        }
      >
        Upsert
      </button>

      <button disabled={isModalOpen} onClick={() => openIdentify({ topK: 5 })}>
        Identify
      </button>

      <pre>{JSON.stringify(lastResult, null, 2)}</pre>
    </>
  );
}

Returned values:

| Value | Description | | --- | --- | | openEnroll | Opens enrollment capture. | | openVerify | Opens verification capture. | | openUpsert | Opens enroll-or-update capture through the v2 decision flow. | | openUpdate | Opens explicit update capture. | | openIdentify | Opens 1:N identification capture. | | openPreEnrollCheck | Opens pre-enrollment duplicate check. | | config | Current SDK configuration. | | updateConfig | Replace and persist SDK configuration. | | theme | Current theme. | | setTheme | Set light or dark. | | isModalOpen | Whether a modal capture session is active. | | modalState | Current modal state. | | lastResult | Latest CaptureResult. |

Upsert Decision Flow

FingerprintButtonUpsert and openUpsert() use:

POST /api/v2/fingerprints/upsert-decision

The SDK then follows the middleware decision:

| Decision | SDK behavior | | --- | --- | | Enroll | Submits to the v1 enroll endpoint. | | Upsert | Submits to the v1 upsert endpoint. | | Update | Submits to the v1 update endpoint. | | LinkExistingSubject | Links to the existing ABIS subject and updates biometric data. | | ManualReview | Opens the manual review modal so the operator can select a candidate. | | Reject | Fails the operation with the middleware message. |

Fresh request ids are generated for mutating calls after a decision when needed, so the decision request id is not reused in a way that can trigger duplicate request errors.

Finger Selection

Use fingers to customize labels, ids, and selectable fingers.

import { FINGER_POSITIONS, type FingerConfig } from "@rdhiq/rdh-fp";

const fingers: FingerConfig[] = [
  {
    position: FINGER_POSITIONS.RIGHT_THUMB,
    label: "Right thumb",
    id: "f-rt",
    selectable: true,
  },
  {
    position: FINGER_POSITIONS.RIGHT_INDEX_FINGER,
    label: "Right index",
    id: "f-ri",
    selectable: false,
  },
];

<FingerprintButtonEnroll params={{ personId: "P-001", fingers }}>
  Enroll
</FingerprintButtonEnroll>;

Fingers omitted from the custom list fall back to SDK defaults.

Fingerprint Image

FingerprintImage fetches a stored transaction fingerprint image by personId and transactionId.

import { FingerprintImage } from "@rdhiq/rdh-fp";

<FingerprintImage
  personId="A4412188-A29C-48BE-8136-536D6B235009"
  transactionId="SALE-2026-1009"
  width={180}
  height={180}
  alt="Transaction fingerprint"
/>;

The component calls:

GET /api/v1/persons/{personId}/transactions/{businessTransactionId}/fingerprints

type is optional. The SDK does not send ?type=ORIGINAL by default.

<FingerprintImage
  personId="P-001"
  transactionId="SALE-2026-1009"
  type="ENHANCED"
/>

Transactions Page

TransactionsPage provides a transaction browser and a detail drawer.

import { TransactionsPage } from "@rdhiq/rdh-fp";

function TransactionsRoute() {
  return <TransactionsPage />;
}

The list uses:

GET /api/v1/workflow/transactions

Supported filters:

| Filter | Query parameter | | --- | --- | | Transaction ID | transactionId | | Person ID | personId | | Client Application ID | clientApplicationId | | Project ID | projectId |

Opening a row fetches full details by id:

GET /api/v1/workflow/transactions/{businessTransactionId}

The detail drawer shows:

  • transaction metadata
  • person and identity document fields
  • ABIS status fields
  • request cards
  • request status history timeline
  • candidate count and top score where available
  • ABIS transaction and encounter ids
  • error code/message where available

Settings Page

SettingsPage lets a host app manage SDK settings from the UI.

import { SettingsPage } from "@rdhiq/rdh-fp";

function SettingsRoute() {
  return <SettingsPage />;
}

It supports:

  • light/dark theme
  • device discovery and selection
  • middleware validation profile loading
  • project policy loading by project id
  • mandatory and optional finger policy display

Capture Result

interface CaptureResult {
  success: boolean;
  operationMode:
    | "enrollment"
    | "upsert"
    | "update"
    | "verification"
    | "identification"
    | "pre_enroll_check";
  captureMode: "standard" | "reduced";
  sensorData: string | null;
  captureId: string | null;
  metadata: Record<string, string | number | boolean | null>;
  deviceId: string;
  dsVersion: string | null;
  rulesVersion: string | null;
  sessionId: string | null;
  correlationId: string;
  backendResponse?: BackendSubmitResponse;
  error?: string;
}

Common backend response fields:

| Field | Description | | --- | --- | | fingerprintRecordId | Enrolled or updated fingerprint record id. | | qualityScore | Quality score returned by middleware. | | matched | Verification match result. | | score | Verification or candidate score. | | candidatePersonId | Matched person id. | | candidates | Identification candidates. | | requestId | Middleware request id. | | abisTransactionRequestId | ABIS transaction request id. | | abisEncounterId | ABIS encounter id. |

Low-Level Clients

The package exports clients for advanced integrations.

import { MiddlewareClient, DeviceServerClient } from "@rdhiq/rdh-fp";

const middleware = new MiddlewareClient(
  "https://your-middleware.example.com",
  "EMP-1001",
  "notary-web",
);

const transactions = await middleware.getTransactions({
  transactionId: "SALE-2026-1009",
});

const detail = await middleware.getTransactionById(
  "8b511243-f4ff-47fd-b85a-473fd16057d3",
);

const images = await middleware.getPersonTransactionFingerprints(
  "A4412188-A29C-48BE-8136-536D6B235009",
  "SALE-2026-1009",
);

const deviceServer = new DeviceServerClient("http://127.0.0.1", 8041, 15000);
const devices = await deviceServer.getDevices();

Configuration Utilities

import {
  DEFAULT_CONFIG,
  STORAGE_KEY,
  clearConfig,
  loadConfig,
  saveConfig,
} from "@rdhiq/rdh-fp";

const config = loadConfig();
saveConfig({
  ...config,
  middleware: {
    ...config.middleware,
    baseUrl: "https://your-middleware.example.com",
  },
});
clearConfig();
console.log(STORAGE_KEY, DEFAULT_CONFIG);

Runtime Requirements

  • React 18 or newer.
  • A reachable Neurotechnology Device Server for real biometric capture.
  • A reachable RD.FingerPrint.API middleware.
  • Browser access to the Device Server and middleware URLs.
  • CORS must allow the host app origin.
  • x-user-id is required for middleware write operations.
  • x-caller-system should identify the host application.

Troubleshooting

| Problem | Check | | --- | --- | | No device selected | Open SettingsPage, load devices, and select a device. | | Device Server offline | Confirm host and port, for example http://127.0.0.1:8041. | | Middleware offline | Confirm middleware.baseUrl and network access. | | CORS error | Enable CORS for the host app origin or use a dev proxy. | | Duplicate request id | Omit requestId unless the host must control it. The SDK generates safe ids when needed. | | Fingerprint image URL has unsupported query | Do not pass type; the SDK no longer sends ?type=ORIGINAL by default. | | Public HTTPS app cannot call local HTTP services | Browsers may block mixed content. Use HTTPS-capable middleware/device access or run the app locally. |