Skip to main content
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

TypeDescriptionUse Case
document_uploadUpload and extract data from documentsID, passport, proof of address
form_fillCustom form fields for data collectionPersonal info, company details
selfieCapture selfie photo for face matchingIdentity verification
livenessAWS Rekognition Face Liveness detectionAnti-fraud, spoof prevention
validationAutomated validation checksCross-validation, final review
subsession_collectionCollect verification from related partiesUBOs, submerchants, directors

Common Step Properties

All step types share these base properties:
PropertyTypeRequiredDescription
step_idstringUnique identifier for the step
orderintegerStep order (1-based, sequential)
namestringStep display name
typestringStep type: document_upload, form_fill, selfie, liveness, validation, or subsession_collection
requiredbooleanWhether this step is required or optional (default: true)
descriptionstringStep description for internal use
instructionsstringInstructions shown to the end user

Document Upload Step

Collect and process documents with automatic data extraction.

Configuration

{
  "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,
      "auto_extract": true,
      "allow_multiple": false,
      "enable_auto_classification": false,
      "extraction_profile": null,
      "post_upload_validations": []
    }
  ]
}

Document Requirement Properties

PropertyTypeRequiredDescription
document_typestringType of document to collect
display_namestringName shown to the user
requiredbooleanWhether document is required (default: true)
auto_extractbooleanAutomatically extract data from document (default: false)
allow_multiplebooleanAllow multiple files for this document type (default: false)
enable_auto_classificationbooleanUse AI to auto-classify document type (default: false)
extraction_profilestringCustom extraction profile ID (optional)
post_upload_validationsarrayValidations to run after upload
entity_rolestringEntity role for watchlist tagging: individual, ubo, director, shareholder, representative. Entities extracted from these documents inherit this tag.
Use entity_role on document requirements when uploading multiple IDs for UBOs or directors. For example:
{
  "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.

Document Types

Individual Documents

TypeDescription
idGovernment-issued ID (passport, driver’s license, national ID)
id_documentAlias for id
passportPassport specifically
proof_of_addressUtility bill, bank statement, etc.
selfieSelfie photo (when uploaded as document)

Company Documents

TypeDescription
company_charterCompany charter or constitution
articles_of_incorporationIncorporation documents
tax_certificateTax registration certificate
shareholder_registryShareholder registry document
beneficial_ownersBeneficial ownership declaration
operating_agreementOperating agreement for LLCs

Business Documents

TypeDescription
business_licenseBusiness operating license
bank_ownershipBank account ownership verification
bank_letterBank reference letter

Generic

TypeDescription
customCustom document type
otherOther document types

Example: Multiple Document Requirements

{
  "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

{
  "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

PropertyTypeRequiredDescription
custom_fieldsarrayArray of field definitions. See Field Types for all available fields.
See the Field Types documentation for complete field type reference including semantic fields like country, name, wallet, domain, and volume.

Selfie Step

Capture a selfie photo for face matching against ID documents.

Configuration

{
  "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

PropertyTypeDescription
require_good_lightingbooleanRequire adequate lighting conditions
require_face_centeredbooleanRequire face to be centered in frame
For production use with higher security requirements, consider using the liveness step type instead of selfie to prevent spoofing attacks.

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

{
  "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

PropertyTypeDescription
min_confidencenumberMinimum confidence threshold (0-100) to pass liveness check. Default: 90.0
challenge_typestringType of liveness challenge: FaceMovementChallenge (simpler) or FaceMovementAndLightChallenge (more secure). Default: FaceMovementChallenge
save_reference_imagebooleanSave high-quality reference image from liveness check to S3. Default: true
save_audit_imagesbooleanSave audit images (up to 4 frames from the video) to S3. Default: false
use_for_face_matchbooleanUse the liveness reference image as source for face matching against ID. Default: true
max_retriesintegerMaximum number of retry attempts allowed (1-10). Default: 3

Challenge Types

ChallengeDescriptionSecurity Level
FaceMovementChallengeUser follows head movement promptsStandard
FaceMovementAndLightChallengeAdds colored light reflections on faceHigh

Frontend Integration

The frontend must integrate with AWS Rekognition Face Liveness SDK:
// 1. Create liveness session via API
const response = await fetch(`/public/sessions/${accessToken}/liveness/create`, {
  method: 'POST'
});
const { session_id: livenessSessionId, region } = await response.json();

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

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

Example: Complete Liveness Workflow

{
  "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
  }
}

Validation Step

Define explicit validation tasks to run at this step.

Configuration

{
  "step_id": "step_4",
  "order": 4,
  "name": "Final Validation",
  "type": "validation",
  "validation_tasks": [
    "cross_validate_documents",
    "run_sanction_check",
    "run_adverse_media"
  ]
}

Validation Tasks

TaskDescription
cross_validate_documentsValidate consistency between uploaded documents
run_sanction_checkRun watchlist/sanctions checks
run_adverse_mediaRun adverse media screening
run_crypto_checkValidate crypto wallet addresses
run_face_matchCompare ID photo to selfie/liveness

Subsession Collection Step

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

Configuration

{
  "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,
    "require_completion_before_proceed": true,
    "impact_parent_status": true,
    "ttl_days": 7
  }
}

Subsession Config Properties

PropertyTypeRequiredDescription
workflow_idstringID of the workflow to use for subsessions
max_subsessionsintegerMaximum number of subsessions allowed (default: 1)
require_completion_before_proceedbooleanIf true, parent session cannot proceed until all subsessions are completed/approved (default: false)
impact_parent_statusbooleanIf true, subsession status can affect parent session status (default: false)
ttl_daysintegerTTL for subsessions in days (overrides default workflow TTL)

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:
{
  "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

{
  "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 for the API endpoints used by the frontend.

Complete Workflow Example

{
  "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"
    }
  }
}