Skip to main content

Overview

The Individual module manages individual identity verification (KYC). It provides methods to collect, update, and submit personal information for verification including name, date of birth, documents, addresses, and consents.

Accessing the Module

The Individual module is accessed through the SDK context after initialization:
const oneSDKInstance = await OneSdk({
  mode: 'production',
  session: { token: 'your-token' }
});

// Access the Individual module
const individual = oneSDKInstance.individual();

Module Options

When initializing the SDK, you can configure how much detail the Individual module retrieves from the API:
const oneSDKInstance = await OneSdk({
  mode: 'production',
  session: { token: 'your-token' },
  individualLevel: 'base64'  // or 'meta'
});

IndividualLevel

Controls the level of detail retrieved for entity data, particularly document scans:
ValueDescription
'base64'Retrieves full entity data including document scan images as base64-encoded strings. Use when you need to display or process document images.
'meta'Retrieves only metadata without document scan images. More efficient when you don’t need the actual images.
Default: If not specified, uses the default level configured by FrankieOne.

State Management Methods

isLoading()

Returns whether the module is currently performing an async operation (search, submit, etc.). Signature:
isLoading(): boolean
Returns: boolean - true if loading, false otherwise Description: Indicates if the module is actively fetching or submitting data. Set to true at the start of search() or submit() calls, and false when completed. Example:
console.log('Loading:', individual.isLoading());

// Listen for loading state changes
individual.on('loading', (isLoading, context) => {
  if (isLoading) {
    showSpinner(context.message);
  } else {
    hideSpinner();
  }
});

isPreloaded()

Returns whether existing entity data was found and loaded. Signature:
isPreloaded(): boolean
Returns: boolean - true if existing data was loaded, false if starting fresh Description: After calling search(), this indicates whether the entity already exists in the system with existing verification data. true means you’re continuing an existing verification; false means this is a new entity. Example:
await individual.search();

if (individual.isPreloaded()) {
  console.log('Continuing existing verification');
  // Pre-fill form with existing data
  const name = individual.access('name').getValue();
  prefillForm(name);
} else {
  console.log('Starting new verification');
  // Show empty form
}

isPersisted()

Returns whether all changes have been submitted to the server. Signature:
isPersisted(): boolean
Returns: boolean - true if all data is saved, false if there are unsaved changes Description: Whenever you make changes to the individual’s data (name, documents, addresses, etc.), this flag is set to false. After successfully calling submit(), it’s set back to true. Use this to track whether there are pending changes. Example:
console.log('Has unsaved changes:', !individual.isPersisted());

// Warn user before navigating away
window.addEventListener('beforeunload', (e) => {
  if (!individual.isPersisted()) {
    e.preventDefault();
    e.returnValue = 'You have unsaved changes. Are you sure you want to leave?';
  }
});

Data Fetching Methods

Searches for and loads existing entity data from the server. Signature:
search(): Promise<void>
Returns: Promise<void> - Resolves when search completes Description: Queries the server for any existing data associated with the current session’s entity. If data exists, it’s loaded into the module and can be accessed via the access() method. Sets isPreloaded() to true if data is found. Warning: Calling search() will overwrite any unpersisted local changes with server data. Events Emitted:
  • data_loaded - When search completes (whether data was found or not)
  • loading - Loading state changes
Example:
try {
  await individual.search();

  individual.on('data_loaded', ({ entityId, reference, isPreloaded }) => {
    console.log('Data loaded:', { entityId, reference, isPreloaded });

    if (isPreloaded) {
      // Display existing data
      const name = individual.access('name').getValue();
      const dob = individual.access('dateOfBirth').getValue();
      console.log(`Found existing profile: ${name.givenName} ${name.familyName}`);
    }
  });
} catch (error) {
  console.error('Search failed:', error);
}

syncEntityId()

Synchronizes the entity ID from the session into the individual module. Signature:
syncEntityId(): void
Returns: void Description: Updates the individual’s entity ID to match the current session’s entity ID. Useful if the session entity ID changes after module initialization. Example:
individual.syncEntityId();
const entityId = individual.access('entityId').getValue();
console.log('Synced entity ID:', entityId);

Data Submission Methods

submit()

Persists all entity data to the server. Signature:
submit<T extends boolean>(
  options?: {
    verify?: T;
  },
  retryOptions?: {
    maxRetries?: number;
    backoffDelayMs?: number;
  }
): Promise<T extends true ? CheckSummary : void>
Parameters:
ParameterTypeRequiredDefaultDescription
options.verifybooleanNofalseIf true, triggers verification checks and returns results. If false, only saves data without verification.
retryOptions.maxRetriesnumberNo-Maximum number of retry attempts on failure
retryOptions.backoffDelayMsnumberNo-Delay in milliseconds between retry attempts
Returns:
  • Promise<void> if verify is false (default) - Data saved, no verification run
  • Promise<CheckSummary> if verify is true - Returns verification results (see CheckSummary Structure below)
Description: Submits all individual data (name, DOB, documents, addresses, consents) to the server. When verify: true is passed, it also triggers verification checks and returns a summary of results. Retry behavior is not enabled by default. Pass retryOptions explicitly to enable automatic retries with exponential backoff. Events Emitted:
  • results - When verification completes (only if verify: true)
  • loading - Loading state changes
Examples:
// Save data without verification
try {
  await individual.submit();
  console.log('Data saved successfully');
} catch (error) {
  console.error('Submit failed:', error);
}
// Save data AND run verification
try {
  const results = await individual.submit({ verify: true });

  console.log('Verification results:', {
    status: results.status,
    checkDate: results.checkDate,
    checks: results.checkResults,
    risk: results.risk
  });

  if (results.status.type === 'passed') {
    navigateToSuccess();
  } else {
    showVerificationErrors(results);
  }
} catch (error) {
  console.error('Verification failed:', error);
}
// Submit with retry logic
try {
  await individual.submit(
    { verify: false },
    {
      maxRetries: 3,
      backoffDelayMs: 1000
    }
  );
} catch (error) {
  console.error('Submit failed after retries:', error);
}

runChecks()

Runs verification checks without submitting data. Signature:
runChecks(): Promise<CheckSummary>
Returns: Promise<CheckSummary> - Verification results Description: Triggers verification checks on the current entity data without performing a data submission. Use this to re-run checks on already-submitted data or to check verification status. Events Emitted:
  • results - When checks complete
  • loading - Loading state changes
Example:
try {
  const results = await individual.runChecks();

  console.log('Status:', results.status.type, results.status.label);
  console.log('Risk level:', results.risk.level, results.risk.class);

  // Iterate through individual check results
  if (results.checkResults) {
    results.checkResults.forEach(check => {
      console.log(`${check.type}: ${check.result.label}`);
    });
  }
} catch (error) {
  console.error('Checks failed:', error);
}

CheckSummary Structure

Both submit({ verify: true }) and runChecks() return a CheckSummary object containing verification results.

Properties

PropertyTypeDescription
statusobjectOverall verification status object:
type: "passed" | "failed" | "fail_manual" | "pass_manual" | "refer" | "wait" | "unchecked" | "archived" | "inactive" | null - The verification result type
label: string - Human-readable status label (e.g., “Verified”, “Failed”, “Needs Review”)
key: string - Status key identifier (e.g., “VERIFIED”, “FAILED”)
action?: string - Optional action required
checkDatestringISO 8601 timestamp indicating when verification checks were performed (e.g., "2024-01-15T10:30:00.000Z")
checkTypesstring[]Array of check type names that were executed during verification. Common values: "name", "dob", "document", "address", "watchlist", "pep", "sanctions"
personalChecksobjectValidation results for personal information fields:
name: boolean | null - Name validation result
dateOfBirth: boolean | null - DOB validation result
phoneNumber: boolean | null - Phone validation result
email: boolean | null - Email validation result
chineseName: string | null - Chinese name if provided
addresses: { [addressId: string]: boolean | null } - Address validation results by address ID

For boolean fields: true = validated successfully, false = validation failed, null = not checked
riskobjectRisk assessment:
level: number | null - Numeric risk level (lower numbers indicate lower risk)
class: "low" | "medium" | "high" | "unacceptable" | null - Risk classification
checkResultsarray (optional)Array of detailed check results:
Each item contains:
type: string | null - Check type identifier (e.g., "document_verification", "watchlist_aml")
result: Status object with type, label, key (same structure as main status)
issues: Array<{ code: string | null, description: string | null }> - Issues found in this specific check
checkCountsobjectCount of data sources used for verification:
name: string[] | null - Data sources that verified name
dob: string[] | null - Data sources that verified date of birth
address: { [addressId: string]: string[] | null } - Data sources per address
document: { [documentId: string]: string[] | null } - Data sources per document
kycMethodstringKYC method used: "electronic" (automated) or "manual" (human review)
issuesobjectDictionary of issues found during verification. Key-value pairs where keys are issue identifiers and values contain issue details
alertListarrayArray of alerts or actions required:
Each item can be an IIssue or IIssueAction:
term: string - Issue identifier (e.g., "document_expired", "additional_document_required")
type: "warning" | "action" | "alert" | "success" - Alert severity
extra?: { action: string, label?: string } - Additional action details (only for type: "action")
blocklistPotentialMatchesarrayArray of potential blocklist matches:
Each item contains:
entityId: string - ID of the matched entity
matchStrength: number | null - Match confidence (0-1)
matches: Object with personal (string array of matched fields) and documents (matched document details)
duplicatePotentialMatchesarrayArray of potential duplicate entities found:
Same structure as blocklistPotentialMatches. Indicates this entity may be a duplicate of an existing entity in the system
duplicateBlocklistMatchesarrayArray of entities found in both duplicate and blocklist checks:
Same structure as blocklistPotentialMatches. These are high-priority matches requiring attention
rulesetsMatchesarrayArray of ruleset matching results:
Each item contains:
name: string | null - Ruleset name
order: number | null - Ruleset execution order
result: string | null - Ruleset result (e.g., "passed", "failed")
rulesetMatchFields: Object with match counts for name, dob, address, govId - each containing { required: number | null, actual: number | null }
retryPagesarrayArray of pages that can be retried if verification failed:
Each item contains:
name: string - Screen/page identifier that can be retried

Status Types

The status.type property indicates the overall verification result:
StatusDescription
passedVerification passed all checks
failedVerification failed automated checks
pass_manualManually approved after review
fail_manualManually rejected after review
referRequires manual review
waitWaiting for additional information
uncheckedNo checks have been run
archivedEntity has been archived
inactiveEntity is inactive

Example Structure

{
  // Overall verification status
  status: {
    type: "passed",        // "passed" | "failed" | "refer" | "wait" | etc.
    label: "Verified",     // Human-readable status label
    key: "VERIFIED"        // Status key identifier
  },

  // When checks were performed
  checkDate: "2024-01-15T10:30:00.000Z",

  // Types of checks that were executed
  checkTypes: ["name", "dob", "document", "address"],

  // Validation results for personal information
  personalChecks: {
    name: true,           // true = validated, false = failed, null = not checked
    dateOfBirth: true,
    phoneNumber: null,    // Not checked
    email: true,
    chineseName: null,    // Optional field
    addresses: {
      "address-123": true // Address ID as key, validation result as value
    }
  },

  // Risk assessment
  risk: {
    level: 1,             // Risk level number (lower is better)
    class: "low"          // "low" | "medium" | "high" | "unacceptable" | null
  },

  // Detailed results from individual checks
  checkResults: [
    {
      type: "document_verification",
      result: {
        type: "passed",
        label: "Passed",
        key: "DOCUMENT_VERIFIED"
      },
      issues: []          // Array of { code: string | null, description: string | null }
    },
    {
      type: "watchlist_aml",
      result: {
        type: "passed",
        label: "No Matches",
        key: "AML_CLEAR"
      },
      issues: []
    }
  ],

  // Count of data sources used for each check type
  checkCounts: {
    name: ["data_source_1", "data_source_2"],    // Sources that verified name
    dob: ["data_source_1"],                       // Sources that verified DOB
    address: {
      "address-123": ["address_verification_service"]
    },
    document: {
      "passport-456": ["document_ocr_provider"]
    }
  },

  // KYC method used
  kycMethod: "electronic",  // "electronic" | "manual"

  // Issues found during verification (if any)
  issues: {},

  // Alerts requiring attention
  alertList: [
    // Example issue:
    // {
    //   term: "document_expired",
    //   type: "warning"  // "warning" | "action" | "alert" | "success"
    // }
    // Example action required:
    // {
    //   term: "additional_document_required",
    //   type: "action",
    //   extra: {
    //     action: "upload_proof_of_address",
    //     label: "Please upload proof of address"
    //   }
    // }
  ],

  // Duplicate and blocklist matching results
  blocklistPotentialMatches: [],
  duplicatePotentialMatches: [
    // Example duplicate match:
    // {
    //   entityId: "entity-789",
    //   matchStrength: 0.85,
    //   matches: {
    //     personal: ["name", "dob"],
    //     documents: {
    //       documentId: "doc-456",
    //       field: ["documentNumber", "dateOfBirth"]
    //     }
    //   }
    // }
  ],
  duplicateBlocklistMatches: [],

  // Ruleset matching results
  rulesetsMatches: [
    // Example ruleset match:
    // {
    //   name: "standard_kyc_ruleset",
    //   order: 1,
    //   result: "passed",
    //   rulesetMatchFields: {
    //     name: { required: 2, actual: 2 },
    //     dob: { required: 1, actual: 1 },
    //     address: { required: 1, actual: 1 },
    //     govId: { required: 1, actual: 1 }
    //   }
    // }
  ],

  // Pages that can be retried if verification failed
  retryPages: []
}

Data Access Methods

access(fieldName)

Accesses reactive data accessors for reading and updating entity fields. Signature:
access<K extends keyof PublicAccessors>(
  fieldName: K
): PublicAccessors[K]
Parameters:
ParameterTypeRequiredDescription
fieldNamestringYesName of the field to access. See Available Fields table below.
Returns: Accessor object Accessor Interface:
{
  getValue(): T;              // Read current value
  setValue(value: T): void;  // Write new value
  observable: Observable<T>; // Subscribe to reactive changes
}
access() vs search():
  • Use access() to read or write entity data within the module. You don’t have direct access to the full raw entity object — access() is the interface for it.
  • Use search() to refresh entity data by fetching the latest state from FrankieOne’s backend.
Available Fields:
FieldTypeDescription
entityIdstring | nullEntity identifier (read-only)
name{ givenName, middleName, familyName, displayName }Individual’s name
dateOfBirthstring | nullDate of birth (ISO 8601 format: YYYY-MM-DD)
consentsGivenstring[]Array of consent strings
documentsobject[]Array of identity documents. See Document Structure.
addressesobject[]Array of addresses. See Address Structure.
profileobject | nullVerification profile configuration
phoneNumber{ documentId, idNumber }Phone number details
email{ documentId, idNumber }Email details
extraDataobjectCustom additional data
deviceobjectDevice fingerprinting details
isLoadingbooleanCurrent loading state (read-only)
isPersistedbooleanCurrent persistence state (read-only)
Examples:
// Read values
const name = individual.access('name').getValue();
console.log(`Name: ${name.givenName} ${name.familyName}`);

const dob = individual.access('dateOfBirth').getValue();
console.log('Date of birth:', dob);

const documents = individual.access('documents').getValue();
console.log('Number of documents:', documents.length);
// Update values
individual.access('name').setValue({
  givenName: 'John',
  familyName: 'Doe',
  middleName: null,
  displayName: 'John Doe'
});

individual.access('dateOfBirth').setValue('1990-01-15');
// Subscribe to changes
individual.access('name').observable.subscribe((newName) => {
  console.log('Name changed:', newName);
  updateUI(newName);
});

Name Methods

setEmail()

Sets the individual’s email address. Signature:
setEmail(email: string | null): void
Parameters:
ParameterTypeRequiredDescription
emailstring | nullYesEmail address string or null to clear
Example:
individual.setEmail('john.doe@example.com');

getEmail()

Gets the individual’s email address. Signature:
getEmail(): string | null
Returns: string | null - Email address or null if not set Example:
const email = individual.getEmail();
console.log('Email:', email);

setPhoneNumber()

Sets the individual’s phone number. Signature:
setPhoneNumber(phone: string | null): void
Parameters:
ParameterTypeRequiredDescription
phonestring | nullYesPhone number string or null to clear
Example:
individual.setPhoneNumber('+61412345678');

getPhoneNumber()

Gets the individual’s phone number. Signature:
getPhoneNumber(): string | null
Returns: string | null - Phone number or null if not set Example:
const phone = individual.getPhoneNumber();
console.log('Phone:', phone);

Profile Methods

setProfileType()

Sets the verification profile type. Signature:
setProfileType(profileType: string): void
Parameters:
ParameterTypeRequiredDescription
profileTypestringYesProfile type name that determines which verification checks are performed
Description: Sets the verification profile which determines what checks are performed during verification. The profile type corresponds to predefined verification workflows. Common Profile Types:
Profile TypeDescription
autoAutomatically selects appropriate profile based on available data
gov_idGovernment ID verification
safe_harbourSafe harbour compliance checks
safe_harbour_idSafe harbour with ID verification
safe_harbour_plusEnhanced safe harbour checks
internationalInternational verification profile
gov_id_mediaGovernment ID with media/AML checks
safe_harbour_mediaSafe harbour with media/AML checks
safe_harbour_id_mediaSafe harbour ID with media/AML checks
safe_harbour_plus_mediaSafe harbour plus with media/AML checks
international_mediaInternational with media/AML checks
aml_onlyAML checks only
aml_media_onlyAML media checks only
Note: Profile types may be customized in your FrankieOne account configuration. Contact your account manager for custom profile options. Examples:
// Common profile types
individual.setProfileType('auto');
individual.setProfileType('safe_harbour_plus');
individual.setProfileType('gov_id_media');

// AML-focused profiles
individual.setProfileType('aml_only');

getProfileType()

Gets the current verification profile type. Signature:
getProfileType(): void
Returns: void

addConsent()

Adds a consent string to the entity’s list of consents. Signature:
addConsent(type: string): void
Parameters:
ParameterTypeRequiredDescription
typestringYesConsent type identifier or consent text
Description: Records that the individual has provided a specific consent. Consent strings are stored and can be retrieved via access('consentsGiven'). Example:
individual.addConsent('terms_and_conditions_v1.2');
individual.addConsent('privacy_policy_2024');

// View all consents
const consents = individual.access('consentsGiven').getValue();
console.log('Consents given:', consents);

Document Methods

addDocument()

Adds a new identity document to the entity. Signature:
addDocument(details: Document): void
Parameters:
ParameterTypeRequiredDescription
detailsobjectYesDocument object with identity document details. See Document Structure below.
Example:
// Pass a plain object - it will be converted internally
const passport = {
  idType: 'PASSPORT',
  country: 'AUS',
  idNumber: 'N1234567',
  idExpiry: '2030-12-31',
  dateOfBirth: '1990-01-15'
};

individual.addDocument(passport);

updateDocument()

Updates an existing document by its ID. Signature:
updateDocument(id: string | null, details: Document): void
Parameters:
ParameterTypeRequiredDescription
idstring | nullYesDocument ID to update
detailsobjectYesUpdated document object. See Document Structure.
Example:
const documents = individual.access('documents').getValue();
const docToUpdate = documents[0];

// Update expiry date
docToUpdate.idExpiry = '2031-12-31';
individual.updateDocument(docToUpdate.documentId, docToUpdate);

// Or create a new object with updates
const updatedDoc = {
  ...docToUpdate,
  idExpiry: '2031-12-31',
  extraData: { verified: true }
};
individual.updateDocument(docToUpdate.documentId, updatedDoc);

deleteDocument()

Deletes a document by its ID. Signature:
deleteDocument(id: string): void
Parameters:
ParameterTypeRequiredDescription
idstringYesDocument ID to delete
Example:
const documentId = 'doc-12345';
individual.deleteDocument(documentId);

Address Methods

addAddress()

Adds a new address to the entity. Signature:
addAddress(details: Address): void
Parameters:
ParameterTypeRequiredDescription
detailsobjectYesAddress object. See Address Structure below.
Example:
// Pass a plain object - it will be converted internally
const residentialAddress = {
  addressType: 'RESIDENTIAL',
  unitNumber: '5',
  streetNumber: '123',
  streetName: 'Main',
  streetType: 'Street',
  suburb: 'Sydney',
  state: 'NSW',
  postalCode: '2000',
  country: 'AUS'
};

individual.addAddress(residentialAddress);

updateAddress()

Updates an existing address by its ID. Signature:
updateAddress(id: string | null, details: Address): void
Parameters:
ParameterTypeRequiredDescription
idstring | nullYesAddress ID to update
detailsobjectYesUpdated address object. See Address Structure.
Example:
const addresses = individual.access('addresses').getValue();
const addressToUpdate = addresses[0];

// Update postal code
addressToUpdate.postalCode = '2001';
individual.updateAddress(addressToUpdate.addressId, addressToUpdate);

// Or create a new object with updates
const updatedAddress = {
  ...addressToUpdate,
  postalCode: '2001',
  suburb: 'North Sydney'
};
individual.updateAddress(addressToUpdate.addressId, updatedAddress);

Reference Methods

addReference()

Attaches indexable references to the entity. Signature:
addReference(customerReference: string): void
addReference(key: string, value: string): void
Overloads:
  1. Single parameter - Sets the customer reference (won’t override if already set)
  2. Two parameters - Sets a custom key-value reference pair
Parameters:
ParameterTypeRequiredDescription
customerReferencestringYes (overload 1)Your customer reference identifier
keystringYes (overload 2)Reference key name
valuestringYes (overload 2)Reference value
Description: References are custom identifiers you can attach to entities for indexing and searching in your system. The customer reference is a special primary reference; additional key-value pairs can also be added. Examples:
// Set customer reference
individual.addReference('CUST-12345');

// Add custom key-value references
individual.addReference('application_id', 'APP-789');
individual.addReference('campaign', 'summer-2024');

Extra Data Methods

setExtraData()

Sets custom extra data on the entity. Signature:
setExtraData(data: object): void
Parameters:
ParameterTypeRequiredDescription
dataobjectYesCustom data object to attach to the entity
Description: Allows you to store arbitrary custom data with the entity. This can be used to pass application-specific information through the verification flow. Example:
individual.setExtraData({
  applicationSource: 'mobile_app',
  campaignId: 'PROMO2024',
  internalNotes: 'VIP customer'
});

// Retrieve extra data
const extraData = individual.access('extraData').getValue();
console.log('Extra data:', extraData);

Data Structures

Document Structure

When adding or updating documents, pass a plain object with these properties. The SDK will convert it internally.
PropertyTypeRequiredDescription
documentIdstring | nullNoUnique document identifier. Leave null for new documents (auto-generated).
idTypestring | nullYesDocument type: 'DRIVERS_LICENCE', 'PASSPORT', 'NATIONAL_ID', 'BIRTH_CERTIFICATE', 'MEDICARE_CARD', etc.
idSubTypestring | nullNoDocument subtype if applicable (provider-specific).
countrystring | nullYesISO 3166-1 alpha-3 country code (e.g., 'AUS', 'USA', 'GBR').
regionstring | nullNoState or region code (e.g., 'NSW', 'CA', 'QLD').
idNumberstring | nullYesDocument number or identifier.
idExpirystring | nullNoExpiry date in ISO 8601 format: YYYY-MM-DD.
dateOfBirthstring | nullNoDate of birth as shown on document in ISO 8601 format: YYYY-MM-DD.
genderstring | nullNoGender as shown on document.
extraDataobjectNoAdditional document-specific data (key-value pairs).
Example:
const driverLicense = {
  idType: 'DRIVERS_LICENCE',
  country: 'AUS',
  region: 'NSW',
  idNumber: '12345678',
  idExpiry: '2028-06-30',
  dateOfBirth: '1990-01-15',
  extraData: {
    cardNumber: 'ABC123',
    licenseClass: 'C'
  }
};

individual.addDocument(driverLicense);

Address Structure

When adding or updating addresses, pass a plain object with these properties. The SDK will convert it internally.
PropertyTypeRequiredDescription
addressIdstring | nullNoUnique address identifier. Leave null for new addresses (auto-generated).
addressTypestring | nullYesAddress type: 'RESIDENTIAL', 'MAILING', 'BUSINESS', etc.
unitNumberstring | nullNoUnit or apartment number.
streetNumberstring | nullYesStreet number.
streetNamestring | nullYesStreet name.
streetTypestring | nullNoStreet type (e.g., 'Street', 'Road', 'Avenue', 'Lane').
suburbstring | nullNoSuburb or city district.
townstring | nullYesTown or city name.
statestring | nullNoState or province code.
postalCodestring | nullYesPostal or ZIP code.
countrystring | nullYesISO 3166-1 alpha-3 country code (e.g., 'AUS', 'USA').
buildingNamestring | nullNoBuilding name if applicable.
longFormstring | nullNoComplete address as a single string.
Example:
const homeAddress = {
  addressType: 'RESIDENTIAL',
  unitNumber: '12',
  streetNumber: '456',
  streetName: 'Elizabeth',
  streetType: 'Street',
  suburb: 'Surry Hills',
  town: 'Sydney',
  state: 'NSW',
  postalCode: '2010',
  country: 'AUS'
};

individual.addAddress(homeAddress);

Events

The Individual module emits the following events:

data_loaded

Emitted when entity data has been loaded from the server. Arguments:
{
  entityId: string | null;
  reference: string | null;
  isPreloaded: boolean;
}
Example:
individual.on('data_loaded', ({ entityId, reference, isPreloaded }) => {
  console.log('Data loaded:', { entityId, reference, isPreloaded });

  if (isPreloaded) {
    console.log('Found existing entity data');
  } else {
    console.log('No existing data, starting fresh');
  }
});

data_updated

Emitted when any data field changes. Arguments:
(fieldName: string, newValue: unknown)
Example:
individual.on('data_updated', (fieldName, newValue) => {
  console.log(`Field "${fieldName}" updated:`, newValue);
});

Common Events

The Individual module also emits common events inherited from the event system:
  • error - When an error occurs
  • warning - For non-critical warnings
  • info - Informational messages
  • loading - Loading state changes
See Event System Reference for details.

Complete Example

import OneSdk from '@frankieone/one-sdk';

async function performKYC() {
  try {
    // Initialize SDK
    const sdk = await OneSdk({
      mode: 'production',
      session: { token: await getSessionToken() },
      individualLevel: 'base64' // Include document images
    });

    // Get Individual module
    const individual = sdk.individual();

    // Set up event listeners
    individual.on('data_loaded', ({ isPreloaded }) => {
      if (isPreloaded) {
        console.log('Continuing existing verification');
      }
    });

    individual.on('error', (error) => {
      console.error('Individual module error:', error);
    });

    // Search for existing data
    await individual.search();

    // Set personal information
    individual.access('name').setValue({
      givenName: 'John',
      familyName: 'Doe',
      middleName: null,
      displayName: 'John Doe'
    });

    individual.access('dateOfBirth').setValue('1990-01-15');
    individual.setEmail('john.doe@example.com');
    individual.setPhoneNumber('+61412345678');

    // Add consent
    individual.addConsent('terms_and_conditions_v1.0');

    // Add document (plain object - converted internally)
    const license = {
      idType: 'DRIVERS_LICENCE',
      country: 'AUS',
      region: 'NSW',
      idNumber: '12345678',
      idExpiry: '2028-12-31'
    };
    individual.addDocument(license);

    // Add address (plain object - converted internally)
    const address = {
      addressType: 'RESIDENTIAL',
      streetNumber: '123',
      streetName: 'Main',
      streetType: 'Street',
      suburb: 'Sydney',
      state: 'NSW',
      postalCode: '2000',
      country: 'AUS'
    };
    individual.addAddress(address);

    // Submit and verify (includes automatic retry logic)
    const results = await individual.submit({ verify: true });

    if (results.status.type === 'passed') {
      console.log('✓ Verification passed');
      return { success: true, entityId: individual.access('entityId').getValue() };
    } else {
      console.log('✗ Verification failed');
      return { success: false, status: results.status, issues: results.issues };
    }

  } catch (error) {
    console.error('KYC process failed:', error);
    throw error;
  }
}

Best Practices

  1. Always call search() first - Load existing data before making changes to avoid overwriting user progress.
  2. Check isPersisted() before navigation - Warn users if they have unsaved changes.
  3. Use access() for reactive data - Subscribe to field changes for real-time UI updates.
  4. Handle verification results - Always check checkStatus after submit({ verify: true }).
  5. Validate data before submit - Check that required fields are populated before calling submit().
  6. Add proper error handling - Listen to error events and wrap async calls in try-catch blocks.
  7. Set consents explicitly - Always record user consent with addConsent() before verification.