Skip to main content

Overview

The eKYC flow guides users through a multi-step manual verification journey: welcome, consent, personal details, document entry, review, and result screens. All data is entered via form fields (no camera capture). This flow is ideal when you need full control over each step and want to collect information through a traditional form-based experience. Modules used: form
Instead of building from scratch, fork an existing flow from the public sample codes.

Flow Diagram

1

Welcome Screen

Initial greeting and introduction to the verification process.
2

Consent Screen

Capture user consent for data processing and identity checks.
3

Personal Details

Collect name, date of birth, address, and other personal information.
4

Document Entry

Collect one or more identity document details (e.g., driver’s licence, passport).
5

Review

Display all entered information for the user to confirm before submission.
6

Result

Show verification outcome — success, fail, pending, or partial.
This flow requires a Google Places API key (googleApiKey) in the form provider configuration. The key powers the address autocomplete field in the PERSONAL form screen. Without it, the address search will not work. Get a key from the Google Cloud Console with the Places API enabled.

Full Implementation

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>OneSDK eKYC Flow</title>
    <script src="https://assets.frankiefinancial.io/one-sdk/v1/oneSdk.umd.js"></script>
    <style>
      body { margin: 0; font-family: sans-serif; background: #fff; }
      #onesdk-container { width: 100%; min-height: 100vh; }
    </style>
  </head>
  <body>
    <div id="onesdk-container"></div>

    <script>
      async function startOneSDK() {
        try {
          // 1. Generate session token (move to your backend in production)
          const tokenResponse = await fetch(
            "https://backend.kycaml.uat.frankiefinancial.io/auth/v2/machine-session",
            {
              method: "POST",
              headers: {
                authorization: "machine " + btoa("<CUSTOMER_ID>:<CUSTOMER_CHILD_ID>:<API_KEY>"),
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                permissions: {
                  preset: "one-sdk",
                  reference: "ekyc-" + Date.now(),
                },
              }),
            }
          );
          const session = await tokenResponse.json();

          // 2. Initialize OneSDK
          const oneSdk = await OneSDK({
            session: session,
            mode: "development",
            recipe: {
              form: {
                provider: {
                  name: "react",
                  googleApiKey: "<YOUR_GOOGLE_API_KEY>",
                },
              },
            },
          });

          const appContainer = "#onesdk-container";

          // 3. Configure form components
          const welcome = oneSdk.component("form", {
            name: "WELCOME",
            type: "manual",
          });

          const consent = oneSdk.component("form", { name: "CONSENT" });

          const personal = oneSdk.component("form", {
            name: "PERSONAL",
            type: "manual",
          });

          const documentForm = oneSdk.component("form", {
            name: "DOCUMENT",
            type: "manual",
            numberOfIDs: 2,
          });

          const review = oneSdk.component("form", {
            name: "REVIEW",
            type: "manual",
            verify: true,
          });

          const retry = oneSdk.component("form", {
            name: "RETRY",
            type: "manual",
          });

          // 4. Wire up form navigation events
          welcome.mount(appContainer);

          welcome.on("form:welcome:failed", () => {
            console.error("Welcome screen failed to load");
          });

          welcome.on("form:welcome:ready", () => {
            consent.mount(appContainer);
          });

          consent.on("form:consent:ready", () => {
            personal.mount(appContainer);
          });

          personal.on("form:personal:ready", () => {
            documentForm.mount(appContainer);
          });

          documentForm.on("form:document:back", () => {
            personal.mount(appContainer);
          });

          documentForm.on("form:document:ready", () => {
            review.mount(appContainer);
          });

          // 5. Handle result screen CTA presses
          // The review component (verify: true) handles verification and shows
          // result screens automatically. These events fire when the user
          // presses the CTA on the result screen.
          review.on("form:result:success", () => {
            console.log("Verification complete");
          });

          review.on("form:result:failed", () => {
            console.log("Verification failed");
          });

          review.on("form:result:pending", () => {
            console.log("Verification pending");
          });

          // 6. Retry logic
          let retryCount = 0;
          review.on("form:result:partial", () => {
            if (retryCount < 2) {
              retry.mount(appContainer);
              retryCount++;
            } else {
              console.log("Max retries reached");
            }
          });
        } catch (error) {
          console.error("OneSDK initialization failed:", error);
        }
      }

      startOneSDK();
    </script>
  </body>
</html>

Step-by-Step Breakdown

1. Initialize the SDK

Pass the session object from your backend to OneSDK(). Include the form.provider recipe to enable React-rendered form components and optional Google Places address autocomplete.

2. Configure Form Components

Create form components using sdk.component("form", { name, type }). Each screen (WELCOME, CONSENT, PERSONAL, DOCUMENT, REVIEW, RESULT) is a separate component instance.

3. Wire Up Events

Use .on(event) listeners to transition between screens. Each form emits a form:<name>:ready event when the user completes that step.

4. Handle Results

The review form with verify: true handles verification and shows result screens automatically. form:result:success, form:result:failed, form:result:pending, and form:result:partial fire when the user presses the CTA on the corresponding result screen. Use these events for post-flow actions (redirects, analytics, retry logic). If you need to intercept the result before a screen is shown, use customResult: true — see Form Screens for details.

Adding Device Tracking (Fraud Detection)

To add fraud detection via device fingerprinting, initialize the device component before mounting the welcome screen:
const device = oneSdk.component("device", {
  activityType: "REGISTRATION",
});
device.start();

// Then continue with the normal flow...
welcome.mount(appContainer);
The device component runs in the background, collecting signals that the FrankieOne platform uses for fraud risk scoring. No additional UI is rendered.

Retry Logic

The retry mechanism allows users a configurable number of attempts before showing a final failure screen:
const retry = oneSdk.component("form", {
  name: "RETRY",
  type: "manual",
});

let retryCount = 0;

review.on("form:result:partial", () => {
  if (retryCount < 2) {
    retry.mount(appContainer);
    retryCount++;
  } else {
    console.log("Max retries reached");
  }
});
The retry form remounts the review step, giving the user another chance to correct any issues. After the maximum number of attempts, the failure screen is shown.

Customizing ID Documents

Configure which documents are accepted and how many are required:
const documentForm = oneSdk.component("form", {
  name: "DOCUMENT",
  type: "manual",
  numberOfIDs: 2,
  documents: [
    {
      type: "DRIVERS_LICENCE",
      countries: {
        default: {
          default: {
            fields: [
              {
                fieldType: "select",
                name: "country",
                options: [
                  { label: "Australia", value: "AUS" },
                  { label: "New Zealand", value: "NZL" },
                ],
              },
            ],
          },
        },
      },
    },
    {
      type: "PASSPORT",
      countries: {
        default: {
          default: {
            fields: [
              {
                fieldType: "select",
                name: "country",
                options: [
                  { label: "Australia", value: "AUS" },
                  { label: "New Zealand", value: "NZL" },
                ],
              },
            ],
          },
        },
      },
    },
  ],
});
See Form Module Configuration for all available document and field options.

Customization Reference

AspectReference
SDK initialization optionsSDK Initialization
Session token generationSession Management
Form screen configurationForm Module
Screen names and typesForm Screens
Custom field configurationForm Configuration
Event names and payloadsEvents
Error handling patternsError Scenarios
Device fraud detectionDevice Module