> ## Documentation Index
> Fetch the complete documentation index at: https://docs.frankieone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Individual Module

> Complete reference for the Individual (KYC) module

## 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:

```javascript theme={null}
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:

```javascript theme={null}
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:

| Value      | Description                                                                                                                                   |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `'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:**

```typescript theme={null}
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:**

```javascript theme={null}
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:**

```typescript theme={null}
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:**

```javascript theme={null}
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:**

```typescript theme={null}
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:**

```javascript theme={null}
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

### `search()`

Searches for and loads existing entity data from the server.

**Signature:**

```typescript theme={null}
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:**

```javascript theme={null}
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:**

```typescript theme={null}
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:**

```javascript theme={null}
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:**

```typescript theme={null}
submit<T extends boolean>(
  options?: {
    verify?: T;
  },
  retryOptions?: {
    maxRetries?: number;
    backoffDelayMs?: number;
  }
): Promise<T extends true ? CheckSummary : void>
```

**Parameters:**

| Parameter                     | Type      | Required | Default | Description                                                                                                    |
| ----------------------------- | --------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------- |
| `options.verify`              | `boolean` | No       | `false` | If `true`, triggers verification checks and returns results. If `false`, only saves data without verification. |
| `retryOptions.maxRetries`     | `number`  | No       | -       | Maximum number of retry attempts on failure                                                                    |
| `retryOptions.backoffDelayMs` | `number`  | No       | -       | 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](#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:**

```javascript theme={null}
// Save data without verification
try {
  await individual.submit();
  console.log('Data saved successfully');
} catch (error) {
  console.error('Submit failed:', error);
}
```

```javascript theme={null}
// 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);
}
```

```javascript theme={null}
// 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:**

```typescript theme={null}
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:**

```javascript theme={null}
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

| Property                    | Type               | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| --------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`                    | `object`           | **Overall verification status object:**<br />• `type`: `"passed" \| "failed" \| "fail_manual" \| "pass_manual" \| "refer" \| "wait" \| "unchecked" \| "archived" \| "inactive" \| null` - The verification result type<br />• `label`: `string` - Human-readable status label (e.g., "Verified", "Failed", "Needs Review")<br />• `key`: `string` - Status key identifier (e.g., "VERIFIED", "FAILED")<br />• `action?`: `string` - Optional action required                                                                                                                                                  |
| `checkDate`                 | `string`           | ISO 8601 timestamp indicating when verification checks were performed (e.g., `"2024-01-15T10:30:00.000Z"`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `checkTypes`                | `string[]`         | Array of check type names that were executed during verification. Common values: `"name"`, `"dob"`, `"document"`, `"address"`, `"watchlist"`, `"pep"`, `"sanctions"`                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `personalChecks`            | `object`           | **Validation results for personal information fields:**<br />• `name`: `boolean \| null` - Name validation result<br />• `dateOfBirth`: `boolean \| null` - DOB validation result<br />• `phoneNumber`: `boolean \| null` - Phone validation result<br />• `email`: `boolean \| null` - Email validation result<br />• `chineseName`: `string \| null` - Chinese name if provided<br />• `addresses`: `{ [addressId: string]: boolean \| null }` - Address validation results by address ID<br /><br />For boolean fields: `true` = validated successfully, `false` = validation failed, `null` = not checked |
| `risk`                      | `object`           | **Risk assessment:**<br />• `level`: `number \| null` - Numeric risk level (lower numbers indicate lower risk)<br />• `class`: `"low" \| "medium" \| "high" \| "unacceptable" \| null` - Risk classification                                                                                                                                                                                                                                                                                                                                                                                                  |
| `checkResults`              | `array` (optional) | **Array of detailed check results:**<br />Each item contains:<br />• `type`: `string \| null` - Check type identifier (e.g., `"document_verification"`, `"watchlist_aml"`)<br />• `result`: Status object with `type`, `label`, `key` (same structure as main `status`)<br />• `issues`: `Array<{ code: string \| null, description: string \| null }>` - Issues found in this specific check                                                                                                                                                                                                                 |
| `checkCounts`               | `object`           | **Count of data sources used for verification:**<br />• `name`: `string[] \| null` - Data sources that verified name<br />• `dob`: `string[] \| null` - Data sources that verified date of birth<br />• `address`: `{ [addressId: string]: string[] \| null }` - Data sources per address<br />• `document`: `{ [documentId: string]: string[] \| null }` - Data sources per document                                                                                                                                                                                                                         |
| `kycMethod`                 | `string`           | KYC method used: `"electronic"` (automated) or `"manual"` (human review)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `issues`                    | `object`           | Dictionary of issues found during verification. Key-value pairs where keys are issue identifiers and values contain issue details                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `alertList`                 | `array`            | **Array of alerts or actions required:**<br />Each item can be an `IIssue` or `IIssueAction`:<br />• `term`: `string` - Issue identifier (e.g., `"document_expired"`, `"additional_document_required"`)<br />• `type`: `"warning" \| "action" \| "alert" \| "success"` - Alert severity<br />• `extra?`: `{ action: string, label?: string }` - Additional action details (only for `type: "action"`)                                                                                                                                                                                                         |
| `blocklistPotentialMatches` | `array`            | **Array of potential blocklist matches:**<br />Each item contains:<br />• `entityId`: `string` - ID of the matched entity<br />• `matchStrength`: `number \| null` - Match confidence (0-1)<br />• `matches`: Object with `personal` (string array of matched fields) and `documents` (matched document details)                                                                                                                                                                                                                                                                                              |
| `duplicatePotentialMatches` | `array`            | **Array of potential duplicate entities found:**<br />Same structure as `blocklistPotentialMatches`. Indicates this entity may be a duplicate of an existing entity in the system                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `duplicateBlocklistMatches` | `array`            | **Array of entities found in both duplicate and blocklist checks:**<br />Same structure as `blocklistPotentialMatches`. These are high-priority matches requiring attention                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `rulesetsMatches`           | `array`            | **Array of ruleset matching results:**<br />Each item contains:<br />• `name`: `string \| null` - Ruleset name<br />• `order`: `number \| null` - Ruleset execution order<br />• `result`: `string \| null` - Ruleset result (e.g., `"passed"`, `"failed"`)<br />• `rulesetMatchFields`: Object with match counts for `name`, `dob`, `address`, `govId` - each containing `{ required: number \| null, actual: number \| null }`                                                                                                                                                                              |
| `retryPages`                | `array`            | **Array of pages that can be retried if verification failed:**<br />Each item contains:<br />• `name`: `string` - Screen/page identifier that can be retried                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

### Status Types

The `status.type` property indicates the overall verification result:

| Status        | Description                          |
| ------------- | ------------------------------------ |
| `passed`      | Verification passed all checks       |
| `failed`      | Verification failed automated checks |
| `pass_manual` | Manually approved after review       |
| `fail_manual` | Manually rejected after review       |
| `refer`       | Requires manual review               |
| `wait`        | Waiting for additional information   |
| `unchecked`   | No checks have been run              |
| `archived`    | Entity has been archived             |
| `inactive`    | Entity is inactive                   |

### Example Structure

```javascript theme={null}
{
  // 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:**

```typescript theme={null}
access<K extends keyof PublicAccessors>(
  fieldName: K
): PublicAccessors[K]
```

**Parameters:**

| Parameter   | Type     | Required | Description                                                    |
| ----------- | -------- | -------- | -------------------------------------------------------------- |
| `fieldName` | `string` | Yes      | Name of the field to access. See Available Fields table below. |

**Returns:** `Accessor` object

**Accessor Interface:**

```typescript theme={null}
{
  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:**

| Field           | Type                                                 | Description                                                                 |
| --------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- |
| `entityId`      | `string \| null`                                     | Entity identifier (read-only)                                               |
| `name`          | `{ givenName, middleName, familyName, displayName }` | Individual's name                                                           |
| `dateOfBirth`   | `string \| null`                                     | Date of birth (ISO 8601 format: YYYY-MM-DD)                                 |
| `consentsGiven` | `string[]`                                           | Array of consent strings                                                    |
| `documents`     | `object[]`                                           | Array of identity documents. See [Document Structure](#document-structure). |
| `addresses`     | `object[]`                                           | Array of addresses. See [Address Structure](#address-structure).            |
| `profile`       | `object \| null`                                     | Verification profile configuration                                          |
| `phoneNumber`   | `{ documentId, idNumber }`                           | Phone number details                                                        |
| `email`         | `{ documentId, idNumber }`                           | Email details                                                               |
| `extraData`     | `object`                                             | Custom additional data                                                      |
| `device`        | `object`                                             | Device fingerprinting details                                               |
| `isLoading`     | `boolean`                                            | Current loading state (read-only)                                           |
| `isPersisted`   | `boolean`                                            | Current persistence state (read-only)                                       |

**Examples:**

```javascript theme={null}
// 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);
```

```javascript theme={null}
// Update values
individual.access('name').setValue({
  givenName: 'John',
  familyName: 'Doe',
  middleName: null,
  displayName: 'John Doe'
});

individual.access('dateOfBirth').setValue('1990-01-15');
```

```javascript theme={null}
// 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:**

```typescript theme={null}
setEmail(email: string | null): void
```

**Parameters:**

| Parameter | Type             | Required | Description                             |
| --------- | ---------------- | -------- | --------------------------------------- |
| `email`   | `string \| null` | Yes      | Email address string or `null` to clear |

**Example:**

```javascript theme={null}
individual.setEmail('john.doe@example.com');
```

***

### `getEmail()`

Gets the individual's email address.

**Signature:**

```typescript theme={null}
getEmail(): string | null
```

**Returns:** `string | null` - Email address or `null` if not set

**Example:**

```javascript theme={null}
const email = individual.getEmail();
console.log('Email:', email);
```

***

### `setPhoneNumber()`

Sets the individual's phone number.

**Signature:**

```typescript theme={null}
setPhoneNumber(phone: string | null): void
```

**Parameters:**

| Parameter | Type             | Required | Description                            |
| --------- | ---------------- | -------- | -------------------------------------- |
| `phone`   | `string \| null` | Yes      | Phone number string or `null` to clear |

**Example:**

```javascript theme={null}
individual.setPhoneNumber('+61412345678');
```

***

### `getPhoneNumber()`

Gets the individual's phone number.

**Signature:**

```typescript theme={null}
getPhoneNumber(): string | null
```

**Returns:** `string | null` - Phone number or `null` if not set

**Example:**

```javascript theme={null}
const phone = individual.getPhoneNumber();
console.log('Phone:', phone);
```

***

## Profile Methods

### `setProfileType()`

Sets the verification profile type.

**Signature:**

```typescript theme={null}
setProfileType(profileType: string): void
```

**Parameters:**

| Parameter     | Type     | Required | Description                                                               |
| ------------- | -------- | -------- | ------------------------------------------------------------------------- |
| `profileType` | `string` | Yes      | Profile 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 Type              | Description                                                       |
| ------------------------- | ----------------------------------------------------------------- |
| `auto`                    | Automatically selects appropriate profile based on available data |
| `gov_id`                  | Government ID verification                                        |
| `safe_harbour`            | Safe harbour compliance checks                                    |
| `safe_harbour_id`         | Safe harbour with ID verification                                 |
| `safe_harbour_plus`       | Enhanced safe harbour checks                                      |
| `international`           | International verification profile                                |
| `gov_id_media`            | Government ID with media/AML checks                               |
| `safe_harbour_media`      | Safe harbour with media/AML checks                                |
| `safe_harbour_id_media`   | Safe harbour ID with media/AML checks                             |
| `safe_harbour_plus_media` | Safe harbour plus with media/AML checks                           |
| `international_media`     | International with media/AML checks                               |
| `aml_only`                | AML checks only                                                   |
| `aml_media_only`          | AML media checks only                                             |

**Note:** Profile types may be customized in your FrankieOne account configuration. Contact your account manager for custom profile options.

**Examples:**

```javascript theme={null}
// 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:**

```typescript theme={null}
getProfileType(): void
```

**Returns:** `void`

***

## Consent Methods

### `addConsent()`

Adds a consent string to the entity's list of consents.

**Signature:**

```typescript theme={null}
addConsent(type: string): void
```

**Parameters:**

| Parameter | Type     | Required | Description                             |
| --------- | -------- | -------- | --------------------------------------- |
| `type`    | `string` | Yes      | Consent 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:**

```javascript theme={null}
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:**

```typescript theme={null}
addDocument(details: Document): void
```

**Parameters:**

| Parameter | Type     | Required | Description                                                                                          |
| --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `details` | `object` | Yes      | Document object with identity document details. See [Document Structure](#document-structure) below. |

**Example:**

```javascript theme={null}
// 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:**

```typescript theme={null}
updateDocument(id: string | null, details: Document): void
```

**Parameters:**

| Parameter | Type             | Required | Description                                                             |
| --------- | ---------------- | -------- | ----------------------------------------------------------------------- |
| `id`      | `string \| null` | Yes      | Document ID to update                                                   |
| `details` | `object`         | Yes      | Updated document object. See [Document Structure](#document-structure). |

**Example:**

```javascript theme={null}
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:**

```typescript theme={null}
deleteDocument(id: string): void
```

**Parameters:**

| Parameter | Type     | Required | Description           |
| --------- | -------- | -------- | --------------------- |
| `id`      | `string` | Yes      | Document ID to delete |

**Example:**

```javascript theme={null}
const documentId = 'doc-12345';
individual.deleteDocument(documentId);
```

***

## Address Methods

### `addAddress()`

Adds a new address to the entity.

**Signature:**

```typescript theme={null}
addAddress(details: Address): void
```

**Parameters:**

| Parameter | Type     | Required | Description                                                        |
| --------- | -------- | -------- | ------------------------------------------------------------------ |
| `details` | `object` | Yes      | Address object. See [Address Structure](#address-structure) below. |

**Example:**

```javascript theme={null}
// 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:**

```typescript theme={null}
updateAddress(id: string | null, details: Address): void
```

**Parameters:**

| Parameter | Type             | Required | Description                                                          |
| --------- | ---------------- | -------- | -------------------------------------------------------------------- |
| `id`      | `string \| null` | Yes      | Address ID to update                                                 |
| `details` | `object`         | Yes      | Updated address object. See [Address Structure](#address-structure). |

**Example:**

```javascript theme={null}
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:**

```typescript theme={null}
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:**

| Parameter           | Type     | Required         | Description                        |
| ------------------- | -------- | ---------------- | ---------------------------------- |
| `customerReference` | `string` | Yes (overload 1) | Your customer reference identifier |
| `key`               | `string` | Yes (overload 2) | Reference key name                 |
| `value`             | `string` | Yes (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:**

```javascript theme={null}
// 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:**

```typescript theme={null}
setExtraData(data: object): void
```

**Parameters:**

| Parameter | Type     | Required | Description                                |
| --------- | -------- | -------- | ------------------------------------------ |
| `data`    | `object` | Yes      | Custom 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:**

```javascript theme={null}
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.

| Property      | Type             | Required | Description                                                                                                       |
| ------------- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `documentId`  | `string \| null` | No       | Unique document identifier. Leave `null` for new documents (auto-generated).                                      |
| `idType`      | `string \| null` | Yes      | Document type: `'DRIVERS_LICENCE'`, `'PASSPORT'`, `'NATIONAL_ID'`, `'BIRTH_CERTIFICATE'`, `'MEDICARE_CARD'`, etc. |
| `idSubType`   | `string \| null` | No       | Document subtype if applicable (provider-specific).                                                               |
| `country`     | `string \| null` | Yes      | ISO 3166-1 alpha-3 country code (e.g., `'AUS'`, `'USA'`, `'GBR'`).                                                |
| `region`      | `string \| null` | No       | State or region code (e.g., `'NSW'`, `'CA'`, `'QLD'`).                                                            |
| `idNumber`    | `string \| null` | Yes      | Document number or identifier.                                                                                    |
| `idExpiry`    | `string \| null` | No       | Expiry date in ISO 8601 format: `YYYY-MM-DD`.                                                                     |
| `dateOfBirth` | `string \| null` | No       | Date of birth as shown on document in ISO 8601 format: `YYYY-MM-DD`.                                              |
| `gender`      | `string \| null` | No       | Gender as shown on document.                                                                                      |
| `extraData`   | `object`         | No       | Additional document-specific data (key-value pairs).                                                              |

**Example:**

```javascript theme={null}
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.

| Property       | Type             | Required | Description                                                                 |
| -------------- | ---------------- | -------- | --------------------------------------------------------------------------- |
| `addressId`    | `string \| null` | No       | Unique address identifier. Leave `null` for new addresses (auto-generated). |
| `addressType`  | `string \| null` | Yes      | Address type: `'RESIDENTIAL'`, `'MAILING'`, `'BUSINESS'`, etc.              |
| `unitNumber`   | `string \| null` | No       | Unit or apartment number.                                                   |
| `streetNumber` | `string \| null` | Yes      | Street number.                                                              |
| `streetName`   | `string \| null` | Yes      | Street name.                                                                |
| `streetType`   | `string \| null` | No       | Street type (e.g., `'Street'`, `'Road'`, `'Avenue'`, `'Lane'`).             |
| `suburb`       | `string \| null` | No       | Suburb or city district.                                                    |
| `town`         | `string \| null` | Yes      | Town or city name.                                                          |
| `state`        | `string \| null` | No       | State or province code.                                                     |
| `postalCode`   | `string \| null` | Yes      | Postal or ZIP code.                                                         |
| `country`      | `string \| null` | Yes      | ISO 3166-1 alpha-3 country code (e.g., `'AUS'`, `'USA'`).                   |
| `buildingName` | `string \| null` | No       | Building name if applicable.                                                |
| `longForm`     | `string \| null` | No       | Complete address as a single string.                                        |

**Example:**

```javascript theme={null}
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:**

```typescript theme={null}
{
  entityId: string | null;
  reference: string | null;
  isPreloaded: boolean;
}
```

**Example:**

```javascript theme={null}
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:**

```typescript theme={null}
(fieldName: string, newValue: unknown)
```

**Example:**

```javascript theme={null}
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](/docs/sdk-reference/events) for details.

***

## Complete Example

```javascript theme={null}
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.

***

## Related

* [SDK Initialization](/docs/sdk-reference/sdk-initialization)
* [Session Management](/docs/sdk-reference/session-management)
* [Event System](/docs/sdk-reference/events)
* [Form Module](/docs/sdk-reference/form-module)
* [IDV Module](/docs/sdk-reference/idv-module)
