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

# Step Types

> Configure workflow steps for document upload, forms, selfie, liveness, and subsessions

Workflow steps define the sequence of actions users must complete during the KYC onboarding process. Each step type has specific configuration options.

## Step Types Overview

| Type                    | Description                               | Use Case                       |
| ----------------------- | ----------------------------------------- | ------------------------------ |
| `document_upload`       | Upload and extract data from documents    | ID, passport, proof of address |
| `form_fill`             | Custom form fields for data collection    | Personal info, company details |
| `selfie`                | Capture selfie photo for face matching    | Identity verification          |
| `liveness`              | AWS Rekognition Face Liveness detection   | Anti-fraud, spoof prevention   |
| `subsession_collection` | Collect verification from related parties | UBOs, submerchants, directors  |

## Common Step Properties

All step types share these base properties:

| Property       | Type    | Required | Description                                                                                 |
| -------------- | ------- | -------- | ------------------------------------------------------------------------------------------- |
| `step_id`      | string  | ✓        | Unique identifier for the step                                                              |
| `order`        | integer | ✓        | Step order (1-based, sequential)                                                            |
| `name`         | string  | ✓        | Step display name                                                                           |
| `type`         | string  | ✓        | Step type: `document_upload`, `form_fill`, `selfie`, `liveness`, or `subsession_collection` |
| `required`     | boolean |          | Whether this step is required or optional (default: true)                                   |
| `description`  | string  |          | Step description for internal use                                                           |
| `instructions` | string  |          | Instructions shown to the end user                                                          |

***

## Document Upload Step

Collect and process documents with automatic data extraction.

### Configuration

```json theme={null}
{
  "step_id": "step_1",
  "order": 1,
  "name": "Identity Document",
  "type": "document_upload",
  "instructions": "Please upload a clear photo of your government-issued ID",
  "document_requirements": [
    {
      "document_type": "id",
      "display_name": "Government ID",
      "required": true,
      "require_back": false,
      "allow_multiple_persons": false,
      "auto_extract": true,
      "allow_multiple": false,
      "enable_auto_classification": false,
      "extraction_profile": null,
      "post_upload_validations": []
    }
  ]
}
```

### Document Requirement Properties

| Property                     | Type    | Required | Description                                                                                                                                                    |
| ---------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_type`              | string  | ✓        | Type of document to collect                                                                                                                                    |
| `display_name`               | string  |          | Name shown to the user                                                                                                                                         |
| `required`                   | boolean |          | Whether document is required (default: true)                                                                                                                   |
| `require_back`               | boolean |          | Require both front and back captures for this document type (default: false)                                                                                   |
| `allow_multiple_persons`     | boolean |          | Allow collecting the same document type for multiple people (default: false)                                                                                   |
| `min_persons`                | integer |          | Minimum number of people/documents required when `allow_multiple_persons` is true                                                                              |
| `max_persons`                | integer |          | Maximum number of people/documents allowed when `allow_multiple_persons` is true                                                                               |
| `person_role_label`          | string  |          | Label shown for each person's role when multiple people are collected                                                                                          |
| `auto_extract`               | boolean |          | Automatically extract data from document (default: false)                                                                                                      |
| `allow_multiple`             | boolean |          | Allow multiple files for this document type (default: false)                                                                                                   |
| `enable_auto_classification` | boolean |          | Use AI to auto-classify document type (default: false)                                                                                                         |
| `extraction_profile`         | string  |          | Custom extraction profile ID (optional)                                                                                                                        |
| `post_upload_validations`    | array   |          | Validations to run after upload                                                                                                                                |
| `entity_role`                | string  |          | Entity role for watchlist tagging: `individual`, `ubo`, `director`, `shareholder`, `representative`. Entities extracted from these documents inherit this tag. |

<Tip>
  Use `entity_role` on document requirements when uploading multiple IDs for UBOs or directors. For example:

  ```json theme={null}
  {
    "document_type": "id",
    "display_name": "UBO ID Documents",
    "auto_extract": true,
    "allow_multiple": true,
    "entity_role": "ubo"
  }
  ```

  All names extracted from these documents will be tagged as `ubo` when auto-added to watchlists.
</Tip>

### Document Types

#### Individual Documents

| Type               | Description                                                    |
| ------------------ | -------------------------------------------------------------- |
| `id`               | Government-issued ID (passport, driver's license, national ID) |
| `id_document`      | Alias for `id`                                                 |
| `id_front`         | Front side of a government-issued ID                           |
| `id_back`          | Back side of a government-issued ID                            |
| `passport`         | Passport specifically                                          |
| `proof_of_address` | Utility bill, bank statement, etc.                             |
| `selfie`           | Selfie photo (when uploaded as document)                       |

#### Company Documents

| Type                        | Description                      |
| --------------------------- | -------------------------------- |
| `company_charter`           | Company charter or constitution  |
| `articles_of_incorporation` | Incorporation documents          |
| `tax_certificate`           | Tax registration certificate     |
| `shareholder_registry`      | Shareholder registry document    |
| `beneficial_owners`         | Beneficial ownership declaration |
| `operating_agreement`       | Operating agreement for LLCs     |

<Note>
  **Tax certificate cardinality.** A `tax_certificate` requirement allows one active upload by default because `allow_multiple` defaults to `false`; uploading it again replaces the previous document entry for that requirement. Set `allow_multiple: true` when the workflow must retain several tax certificates in the same step. A session can also contain more than one tax certificate when different steps request the same type. Consequently, consumers of `GET /kyc/sessions/{session_id}` should treat matching documents and extraction results as a collection keyed by `doc_id`, not as a session-wide singleton.
</Note>

#### Business Documents

| Type               | Description                         |
| ------------------ | ----------------------------------- |
| `business_license` | Business operating license          |
| `bank_account`     | Bank account verification           |
| `bank_ownership`   | Bank account ownership verification |
| `bank_letter`      | Bank reference letter               |

#### Generic

| Type     | Description          |
| -------- | -------------------- |
| `custom` | Custom document type |
| `other`  | Other document types |

### Example: Multiple Document Requirements

```json theme={null}
{
  "step_id": "documents",
  "order": 1,
  "name": "Upload Documents",
  "type": "document_upload",
  "document_requirements": [
    {
      "document_type": "id",
      "display_name": "Passport or ID Card",
      "required": true,
      "auto_extract": true
    },
    {
      "document_type": "proof_of_address",
      "display_name": "Proof of Address (utility bill, bank statement)",
      "required": true,
      "auto_extract": true,
      "allow_multiple": true
    }
  ]
}
```

***

## Form Fill Step

Collect structured data using custom form fields with semantic validation.

### Configuration

```json theme={null}
{
  "step_id": "step_2",
  "order": 2,
  "name": "Personal Information",
  "type": "form_fill",
  "instructions": "Please provide your personal details",
  "custom_fields": [
    {
      "field_id": "full_name",
      "name": "Full Name",
      "type": "name",
      "name_type": "individual",
      "validate_lists": true,
      "required": true
    },
    {
      "field_id": "nationality",
      "name": "Nationality",
      "type": "country",
      "country_type": "nationality",
      "required": true
    }
  ]
}
```

### Form Fill Properties

| Property        | Type  | Required | Description                                                                                              |
| --------------- | ----- | -------- | -------------------------------------------------------------------------------------------------------- |
| `custom_fields` | array | ✓        | Array of field definitions. See [Field Types](/api-reference/workflows/fields) for all available fields. |

<Note>
  See the [Field Types](/api-reference/workflows/fields) documentation for complete field type reference including semantic fields like `country`, `name`, `wallet`, `domain`, and `volume`.
</Note>

***

## Selfie Step

Capture a selfie photo for face matching against ID documents.

### Configuration

```json theme={null}
{
  "step_id": "step_3",
  "order": 3,
  "name": "Take a Selfie",
  "type": "selfie",
  "instructions": "Please take a clear selfie matching your ID photo. Ensure good lighting and remove glasses.",
  "selfie_config": {
    "require_good_lighting": true,
    "require_face_centered": true
  }
}
```

### Selfie Config Properties

| Property                | Type    | Description                          |
| ----------------------- | ------- | ------------------------------------ |
| `require_good_lighting` | boolean | Require adequate lighting conditions |
| `require_face_centered` | boolean | Require face to be centered in frame |

<Warning>
  For production use with higher security requirements, consider using the `liveness` step type instead of `selfie` to prevent spoofing attacks.
</Warning>

***

## Liveness Step

Perform AWS Rekognition Face Liveness detection to verify the user is a real person and prevent spoofing attacks (printed photos, masks, deep fakes).

### Configuration

```json theme={null}
{
  "step_id": "step_3",
  "order": 3,
  "name": "Liveness Verification",
  "type": "liveness",
  "instructions": "Follow the on-screen instructions to verify your identity",
  "liveness_config": {
    "min_confidence": 90.0,
    "challenge_type": "FaceMovementChallenge",
    "save_reference_image": true,
    "save_audit_images": false,
    "use_for_face_match": true,
    "max_retries": 3
  }
}
```

### Liveness Config Properties

| Property               | Type    | Description                                                                                                                                      |
| ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `min_confidence`       | number  | Minimum confidence threshold (0-100) to pass liveness check. Default: 90.0                                                                       |
| `challenge_type`       | string  | Type of liveness challenge: `FaceMovementChallenge` (simpler) or `FaceMovementAndLightChallenge` (more secure). Default: `FaceMovementChallenge` |
| `save_reference_image` | boolean | Save high-quality reference image from liveness check to S3. Default: true                                                                       |
| `save_audit_images`    | boolean | Save audit images (up to 4 frames from the video) to S3. Default: false                                                                          |
| `use_for_face_match`   | boolean | Use the liveness reference image as source for face matching against ID. Default: true                                                           |
| `max_retries`          | integer | Maximum number of retry attempts allowed (1-10). Default: 3                                                                                      |

### Challenge Types

| Challenge                       | Description                            | Security Level |
| ------------------------------- | -------------------------------------- | -------------- |
| `FaceMovementChallenge`         | User follows head movement prompts     | Standard       |
| `FaceMovementAndLightChallenge` | Adds colored light reflections on face | High           |

### Frontend Integration

The frontend must integrate with AWS Rekognition Face Liveness SDK:

```javascript theme={null}
// 1. Start liveness session via API
const response = await fetch(`/public/sessions/${accessToken}/liveness/start`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ step_id: "liveness" })
});
const startPayload = await response.json();
const livenessSessionId = startPayload.data.liveness_session_id;
const region = "us-east-1"; // Match the region configured for your tenant

// 2. Use AWS Amplify FaceLivenessDetector component
import { FaceLivenessDetector } from '@aws-amplify/ui-react-liveness';

<FaceLivenessDetector
  sessionId={livenessSessionId}
  region={region}
  onAnalysisComplete={async () => {
    // 3. Complete liveness result via API
    const result = await fetch(`/public/sessions/${accessToken}/liveness/complete`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ liveness_session_id: livenessSessionId })
    });
    const completePayload = await result.json();
    const { passed, confidence } = completePayload.data;
  }}
  onError={(error) => console.error(error)}
/>
```

### Example: Complete Liveness Workflow

```json theme={null}
{
  "name": "Secure KYC with Liveness",
  "steps": [
    {
      "step_id": "id_upload",
      "order": 1,
      "name": "Upload ID",
      "type": "document_upload",
      "document_requirements": [
        {"document_type": "id", "required": true, "auto_extract": true}
      ]
    },
    {
      "step_id": "liveness",
      "order": 2,
      "name": "Verify Identity",
      "type": "liveness",
      "liveness_config": {
        "min_confidence": 92.0,
        "challenge_type": "FaceMovementAndLightChallenge",
        "use_for_face_match": true
      }
    }
  ],
  "validation_config": {
    "auto_face_match": true,
    "face_match_threshold": 0.85
  }
}
```

***

## Subsession Collection Step

Collect verification from related parties (UBOs, submerchants, directors) by creating independent subsessions that can be completed by third parties.

### Configuration

```json theme={null}
{
  "step_id": "step_ubos",
  "order": 4,
  "name": "UBO Verification",
  "type": "subsession_collection",
  "instructions": "Add all beneficial owners with 25% or more ownership. Each UBO will receive a separate verification link.",
  "subsession_config": {
    "workflow_id": "ubo-verification-workflow",
    "max_subsessions": 5,
    "min_subsessions": 1,
    "require_completion_before_proceed": true,
    "impact_parent_status": true,
    "ttl_days": 7,
    "category": "ubo",
    "role_label": "Role",
    "role_selection_required": true,
    "allow_multiple_roles": false,
    "role_options": [
      {"value": "ubo", "label": "Ultimate Beneficial Owner"},
      {"value": "director", "label": "Director"}
    ],
    "subsession_label": "UBO",
    "subsession_label_plural": "UBOs",
    "allow_link_regeneration": true
  }
}
```

### Subsession Config Properties

| Property                            | Type    | Required | Description                                                                                          |
| ----------------------------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `workflow_id`                       | string  | ✓        | ID of the workflow to use for subsessions                                                            |
| `max_subsessions`                   | integer |          | Maximum number of subsessions allowed (default: 1)                                                   |
| `min_subsessions`                   | integer |          | Minimum number of subsessions required to proceed (default: 1)                                       |
| `require_completion_before_proceed` | boolean |          | If true, parent session cannot proceed until all subsessions are completed/approved (default: false) |
| `impact_parent_status`              | boolean |          | If true, subsession status can affect parent session status (default: false)                         |
| `ttl_days`                          | integer |          | TTL for subsessions in days (overrides default workflow TTL)                                         |
| `category`                          | string  |          | Category/tag applied to subsessions created from this step                                           |
| `role_label`                        | string  |          | Label shown above role selection                                                                     |
| `role_selection_required`           | boolean |          | Whether the user must select at least one role when creating a subsession                            |
| `allow_multiple_roles`              | boolean |          | Whether one subsession can have multiple selected roles                                              |
| `role_options`                      | array   |          | Allowed role options, each with `value` and `label`                                                  |
| `subsession_label`                  | string  |          | Singular label for this subsession type                                                              |
| `subsession_label_plural`           | string  |          | Plural label for this subsession type                                                                |
| `allow_link_regeneration`           | boolean |          | Whether public users can regenerate subsession links                                                 |

### How It Works

1. **User reaches subsession step**: The frontend displays the subsession collection UI
2. **Create subsessions**: User creates one or more subsessions (up to `max_subsessions`)
3. **Share links**: Each subsession has its own public access link to share with third parties
4. **Third parties complete verification**: Each third party completes their subsession independently
5. **Proceed or wait**: Depending on `require_completion_before_proceed`, the user can proceed immediately or must wait

### Completion Behavior

#### When `require_completion_before_proceed: false`

* User can complete the step and proceed immediately after creating subsessions
* Subsessions continue independently
* Parent session can be approved even if subsessions are pending

#### When `require_completion_before_proceed: true`

* User cannot proceed until all created subsessions are completed or approved
* Frontend should show subsession status and block the "Continue" button
* Useful for strict UBO verification requirements

### Status Impact

When `impact_parent_status: true`:

* If any subsession is **rejected**, the parent session may be flagged for manual review
* All subsession results are aggregated in the parent session's processing results
* Watchlist hits or adverse media from subsessions are included in parent session

### Example: UBO Workflow for Subsessions

Create a simple workflow for UBO verification:

```json theme={null}
{
  "name": "UBO Verification",
  "description": "Short verification for beneficial owners",
  "entity_types": ["individual"],
  "steps": [
    {
      "step_id": "id_upload",
      "order": 1,
      "name": "ID Document",
      "type": "document_upload",
      "instructions": "Upload your passport or national ID",
      "document_requirements": [
        {
          "document_type": "id",
          "required": true,
          "auto_extract": true,
          "entity_role": "ubo"
        }
      ]
    },
    {
      "step_id": "liveness",
      "order": 2,
      "name": "Identity Verification",
      "type": "liveness",
      "liveness_config": {
        "min_confidence": 90.0,
        "challenge_type": "FaceMovementChallenge",
        "use_for_face_match": true
      }
    }
  ],
  "validation_config": {
    "run_lists": true,
    "auto_face_match": true
  }
}
```

### Example: Company KYC with UBO Subsessions

```json theme={null}
{
  "name": "Company KYC with UBOs",
  "description": "Full company onboarding with UBO verification",
  "entity_types": ["company"],
  "steps": [
    {
      "step_id": "company_docs",
      "order": 1,
      "name": "Company Documents",
      "type": "document_upload",
      "document_requirements": [
        {"document_type": "articles_of_incorporation", "required": true},
        {"document_type": "beneficial_owners", "required": true}
      ]
    },
    {
      "step_id": "company_info",
      "order": 2,
      "name": "Company Information",
      "type": "form_fill",
      "custom_fields": [
        {"field_id": "company_name", "name": "Company Name", "type": "name", "name_type": "company", "required": true},
        {"field_id": "incorporation_country", "name": "Country of Incorporation", "type": "country", "required": true},
        {"field_id": "registration_number", "name": "Registration Number", "type": "text", "required": true}
      ]
    },
    {
      "step_id": "representative",
      "order": 3,
      "name": "Representative Verification",
      "type": "liveness",
      "instructions": "Complete liveness verification as company representative",
      "liveness_config": {
        "min_confidence": 90.0,
        "use_for_face_match": true
      }
    },
    {
      "step_id": "ubos",
      "order": 4,
      "name": "Beneficial Owner Verification",
      "type": "subsession_collection",
      "instructions": "Add all beneficial owners with 25% or more ownership. Each will receive a verification link.",
      "subsession_config": {
        "workflow_id": "ubo-verification-workflow",
        "max_subsessions": 10,
        "require_completion_before_proceed": true,
        "impact_parent_status": true,
        "ttl_days": 14
      }
    }
  ],
  "validation_config": {
    "run_lists": true,
    "run_adverse_media": true
  }
}
```

### Frontend Integration

The frontend receives the subsession\_collection step configuration and should:

1. Display the step instructions
2. Show a form/button to create new subsessions
3. List existing subsessions with their status
4. Show copy/share buttons for subsession links
5. Allow regenerating links if needed
6. Block progression if `require_completion_before_proceed` is true and subsessions are pending

See [Public Sessions API - Subsessions](/api-reference/sessions-public#subsessions) for the API endpoints used by the frontend.

***

## Complete Workflow Example

```json theme={null}
{
  "name": "Complete Individual KYC",
  "description": "Full KYC with ID, liveness, and form data",
  "entity_types": ["individual"],
  "steps": [
    {
      "step_id": "documents",
      "order": 1,
      "name": "Identity Documents",
      "type": "document_upload",
      "instructions": "Please upload your passport or government ID",
      "document_requirements": [
        {
          "document_type": "id",
          "display_name": "Passport or ID Card",
          "required": true,
          "auto_extract": true
        },
        {
          "document_type": "proof_of_address",
          "display_name": "Proof of Address",
          "required": false,
          "auto_extract": true
        }
      ]
    },
    {
      "step_id": "liveness",
      "order": 2,
      "name": "Identity Verification",
      "type": "liveness",
      "instructions": "Complete the liveness check to verify your identity",
      "liveness_config": {
        "min_confidence": 90.0,
        "challenge_type": "FaceMovementChallenge",
        "save_reference_image": true,
        "use_for_face_match": true,
        "max_retries": 3
      }
    },
    {
      "step_id": "personal_info",
      "order": 3,
      "name": "Personal Information",
      "type": "form_fill",
      "instructions": "Please verify and complete your information",
      "custom_fields": [
        {
          "field_id": "full_name",
          "name": "Full Legal Name",
          "type": "name",
          "name_type": "individual",
          "validate_lists": true,
          "validate_adverse_media": false,
          "required": true
        },
        {
          "field_id": "date_of_birth",
          "name": "Date of Birth",
          "type": "date",
          "required": true
        },
        {
          "field_id": "nationality",
          "name": "Nationality",
          "type": "country",
          "country_type": "nationality",
          "required": true
        },
        {
          "field_id": "residence",
          "name": "Country of Residence",
          "type": "country",
          "country_type": "residence",
          "required": true
        },
        {
          "field_id": "email",
          "name": "Email Address",
          "type": "email",
          "validate_email": true,
          "block_disposable": true,
          "required": true
        },
        {
          "field_id": "phone",
          "name": "Phone Number",
          "type": "phone",
          "format": "international",
          "require_mobile": true,
          "required": true
        },
        {
          "field_id": "pep_status",
          "name": "Are you a Politically Exposed Person (PEP)?",
          "type": "select",
          "options": ["No", "Yes - Current PEP", "Yes - Former PEP", "Yes - Family member of PEP"],
          "required": true
        }
      ]
    }
  ],
  "validation_config": {
    "run_lists": true,
    "run_adverse_media": true,
    "auto_face_match": true,
    "face_match_threshold": 0.85,
    "automation_rules": {
      "enabled": true,
      "auto_process": true,
      "country_rules": [
        {"country_code": "KP", "action": "auto_deny", "applies_to": ["all"]},
        {"country_code": "IR", "action": "manual_review", "applies_to": ["nationality", "residence"]}
      ],
      "form_field_rules": [
        {
          "field_id": "pep_status",
          "operator": "not_equals",
          "value": "No",
          "action": "manual_review",
          "reason": "User declared PEP status"
        }
      ],
      "default_action": "manual_review"
    }
  }
}
```

## Related Documentation

* [Field Types](/api-reference/workflows/fields) - All available field types
* [Automation Rules](/api-reference/workflows/automations) - Automation configuration
* [Sessions](/api-reference/sessions) - Managing KYC sessions
* [Public Sessions - Subsessions](/api-reference/sessions-public#subsessions) - Public API for subsession management
