Node Reference
Complete reference for all FaceSign verification node types — parameters, outcomes, and configuration.
This reference documents every FaceSign node type with its full parameter set, outcome keys, and configuration options.
For a conceptual overview of how nodes work and connect, see Node Model. For common flow patterns, see Verification Patterns.
Base node structure
All nodes share these fields:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier within the flow. You assign this. |
type | string | Yes | The node type. Must be one of the values listed below. |
Node type enum
enum FSNodeType {
START = "start",
END = "end",
CONVERSATION = "conversation",
LIVENESS_DETECTION = "liveness_detection",
FACE_SCAN = "face_scan",
DOCUMENT_SCAN = "document_scan",
RECOGNITION = "recognition",
ENTER_EMAIL = "enter_email",
TWO_FACTOR_EMAIL = "two_factor_email",
TWO_FACTOR_SMS = "two_factor_sms",
DATA_VALIDATION = "data_validation",
FACE_COMPARE = "face_compare",
PERMISSIONS = "permissions"
}START
Entry point for every flow. Exactly one START node is required per flow.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcome | string | Yes | The id of the next node to execute. |
Example:
{
"id": "start_node",
"type": "start",
"outcome": "welcome_conversation"
}END
Exit point for a flow. At least one END node is required. The END node has no outcomes -- reaching it marks the session as complete.
Additional fields: None.
Example:
{
"id": "end_node",
"type": "end"
}CONVERSATION
AI-powered conversational interaction. The avatar speaks the prompt and waits for the user to respond. FaceSign's AI evaluates the response against the defined conditions and selects the matching outcome.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | The message the avatar speaks. Use Say: ... prefix for direct speech. Supports {name}, {email} template variables from session data. |
outcomes | array | Yes | Non-empty array of conditional outcomes (see below). |
doesNotRequireReply | boolean | No | If true, the node advances immediately without waiting for a user response. Useful for farewell messages before an END node. |
Outcome structure (FSConditionalOutcome):
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for this outcome. |
targetNodeId | string | Yes | The id of the next node if this condition matches. |
condition | string | Yes | Natural-language description of when this outcome applies. Evaluated by AI. |
Conditions are evaluated in order. The first matching condition wins. Write conditions so they are mutually exclusive when possible.
Example:
{
"id": "ask_name",
"type": "conversation",
"prompt": "Say: Hi there, could you tell me your full name?",
"outcomes": [
{
"id": "tr_has_name",
"targetNodeId": "verify_email",
"condition": "The user provided their name"
},
{
"id": "tr_no_name",
"targetNodeId": "ask_name_again",
"condition": "The user did not provide their name"
}
]
}LIVENESS_DETECTION
Anti-spoofing check to confirm a real person is present. Detects photos, videos, and deepfakes.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
Outcomes:
| Key | Description |
|---|---|
livenessDetected | Node id to execute if a live person is confirmed. |
deepfakeDetected | Node id to execute if a deepfake or replay is detected. |
noFace | Node id to execute if no face is found in the frame. |
Example:
{
"id": "liveness_check",
"type": "liveness_detection",
"outcomes": {
"livenessDetected": "proceed_to_document",
"deepfakeDetected": "verification_failed",
"noFace": "retry_liveness"
}
}FACE_SCAN
Captures the user's face and performs 1:1 matching against a reference image (e.g., from a scanned document or a provided photo).
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
referenceImageKey | string | No | Key in the session's providedData object containing the reference image. |
similarityThreshold | number | No | Match threshold from 0 to 1. Default: 0.85. |
captureInstructions | string | No | Custom instruction text shown to the user during capture. |
requireLivenessChallenge | boolean | No | Whether to require an active liveness challenge during capture. |
requireAILivenessCheck | boolean | No | Whether to run an AI-based liveness check on the captured image. |
enableSound | boolean | No | Enable a capture sound effect. |
enableHaptics | boolean | No | Enable haptic feedback on supported devices. |
Outcomes:
| Key | Description |
|---|---|
passed | Node id if the face matches the reference above the threshold. |
notPassed | Node id if the face does not match. |
cancelled | Node id if the user cancels or exits the capture. |
error | Node id if a technical error occurs. |
Example:
{
"id": "face_matching",
"type": "face_scan",
"outcomes": {
"passed": "verification_complete",
"notPassed": "retry_or_review",
"cancelled": "flow_cancelled",
"error": "technical_error"
},
"referenceImageKey": "primary_doc_face",
"similarityThreshold": 0.90,
"captureInstructions": "Look straight into the camera",
"requireLivenessChallenge": true
}DOCUMENT_SCAN
Captures and verifies an identity document. Supports passports, driver's licenses, and national ID cards.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
scanningMode | string | Yes | "single" scans one side only. "automatic" detects and scans all required sides based on document type. |
allowedDocumentTypes | array | Yes | Array of allowed document types: "passport", "driver_license", "id_card". |
showTorchButton | boolean | No | Show a flashlight toggle in the UI. |
showCameraSwitch | boolean | No | Allow the user to switch between front and rear cameras. |
showMirrorCameraButton | boolean | No | Allow mirrored camera mode. |
Outcomes:
| Key | Description |
|---|---|
scanSuccess | Node id on a successful document scan. |
userCancelled | Node id if the user cancels the scan. |
scanTimeout | Node id if the scan times out. |
Example:
{
"id": "document_verification",
"type": "document_scan",
"scanningMode": "automatic",
"allowedDocumentTypes": ["passport", "driver_license", "id_card"],
"outcomes": {
"scanSuccess": "face_matching",
"userCancelled": "handle_cancellation",
"scanTimeout": "retry_scan"
},
"showTorchButton": true
}RECOGNITION
1:N face recognition. Checks whether the user's face matches any existing entry in your FaceSign database.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
Outcomes:
| Key | Description |
|---|---|
recognized | Node id if the user matches a known face in the database. |
newUser | Node id if no match is found (new user). |
noFace | Node id if no face is detected. |
Example:
{
"id": "check_existing_user",
"type": "recognition",
"outcomes": {
"recognized": "welcome_back",
"newUser": "onboard_new_user",
"noFace": "retry_capture"
}
}ENTER_EMAIL
Presents a form for the user to enter their email address.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
Outcomes:
| Key | Description |
|---|---|
emailEntered | Node id after the user submits their email. |
canceled | Node id if the user cancels. |
Example:
{
"id": "collect_email",
"type": "enter_email",
"outcomes": {
"emailEntered": "send_otp",
"canceled": "handle_cancel"
}
}TWO_FACTOR_EMAIL
Sends a one-time passcode (OTP) via email and verifies the user enters the correct code.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
otpLength | number | No | Number of digits in the OTP. Default: 6. |
expirySeconds | number | No | How long the OTP remains valid, in seconds. |
maxAttempts | number | No | Maximum number of entry attempts allowed. |
resendAfterSeconds | number | No | Minimum seconds before the user can request a new OTP. |
showUI | boolean | No | Whether to display the OTP entry UI. Default: true. |
emailTemplate | string | No | Custom email body template. Use {{otp}} as the placeholder. |
Outcomes:
| Key | Description |
|---|---|
verified | Node id on successful OTP verification. |
delivery_failed | Node id if the email could not be delivered. |
failed_unverified | Node id if the user exhausts attempts or enters an invalid code. |
cancelled | Node id if the user cancels. |
error | Node id on a general error. |
Example:
{
"id": "email_2fa",
"type": "two_factor_email",
"otpLength": 6,
"expirySeconds": 300,
"maxAttempts": 5,
"resendAfterSeconds": 60,
"outcomes": {
"verified": "access_granted",
"delivery_failed": "technical_support",
"failed_unverified": "retry_email_2fa",
"cancelled": "flow_cancelled",
"error": "technical_error"
}
}TWO_FACTOR_SMS
Sends a one-time passcode (OTP) via SMS and verifies the user enters the correct code.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
otpLength | number | No | Number of digits in the OTP. Default: 6. |
expirySeconds | number | No | How long the OTP remains valid, in seconds. |
maxAttempts | number | No | Maximum number of entry attempts allowed. |
resendAfterSeconds | number | No | Minimum seconds before the user can request a new OTP. |
showUI | boolean | No | Whether to display the OTP entry UI. Default: true. |
smsTemplate | string | No | Custom SMS body template. Use {{otp}} as the placeholder. |
Outcomes:
| Key | Description |
|---|---|
verified | Node id on successful OTP verification. |
delivery_failed | Node id if the SMS could not be delivered. |
failed_unverified | Node id if the user exhausts attempts or enters an invalid code. |
cancelled | Node id if the user cancels. |
error | Node id on a general error. |
Example:
{
"id": "sms_2fa",
"type": "two_factor_sms",
"otpLength": 6,
"expirySeconds": 300,
"maxAttempts": 5,
"resendAfterSeconds": 60,
"outcomes": {
"verified": "access_granted",
"delivery_failed": "technical_support",
"failed_unverified": "retry_sms_2fa",
"cancelled": "flow_cancelled",
"error": "technical_error"
}
}DATA_VALIDATION
Performs conditional routing based on collected session data. Evaluates a validation rule against a data field and routes through transitions.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
validation | object | Yes | The validation rule to evaluate (see below). |
transitions | array | Yes | Ordered array of conditional transitions (see below). |
Validation object:
| Field | Type | Required | Description |
|---|---|---|---|
field | string | Yes | The data field to validate (e.g., "age", "email"). |
action | string | Yes | The validation operation: "exists", "matches", "contains", "greater_than", etc. |
value | string | No | The expected value for comparison. |
Transition structure:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for this transition. |
targetNodeId | string | Yes | The id of the next node if this condition matches. |
condition | string | Yes | Description of when this transition applies. |
Transitions are evaluated in order. The first matching condition determines the next node. Make sure your conditions cover all cases.
Example:
{
"id": "validate_age",
"type": "data_validation",
"validation": {
"field": "age",
"action": "greater_than",
"value": "18"
},
"transitions": [
{
"id": "adult",
"targetNodeId": "full_verification",
"condition": "age >= 18"
},
{
"id": "minor",
"targetNodeId": "parental_consent",
"condition": "age < 18"
}
]
}FACE_COMPARE
Compares two face images captured during the session to determine whether they belong to the same person.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
Outcomes:
| Key | Description |
|---|---|
match | Node id if the two faces match. |
noMatch | Node id if the faces do not match. |
error | Node id if a technical error occurs. |
Example:
{
"id": "compare_faces",
"type": "face_compare",
"outcomes": {
"match": "verification_passed",
"noMatch": "verification_failed",
"error": "technical_error"
}
}PERMISSIONS
Requests camera and microphone access from the user's browser. Typically placed early in the flow before any node that requires media access.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
outcomes | object | Yes | Fixed outcome map (see below). |
Outcomes:
| Key | Description |
|---|---|
granted | Node id if the user grants the requested permissions. |
denied | Node id if the user denies permissions. |
Example:
{
"id": "request_permissions",
"type": "permissions",
"outcomes": {
"granted": "start_verification",
"denied": "permissions_required"
}
}Flow validation rules
FaceSign validates your flow at session creation time. Flows that violate any of these rules are rejected with an error:
| Rule | Description |
|---|---|
| Exactly one START | Every flow must have exactly one node with type: "start". |
| At least one END | Every flow must have at least one node with type: "end". |
| No cycles | The graph must be a directed acyclic graph (DAG). No node can be revisited. |
| Valid references | Every outcome must point to the id of an existing node in the flow. |
| Complete outcomes | All non-END nodes must define outcomes covering their required keys. |