KYCIS SDK Docs
Event System

Sending Events

When and how to emit each event type

Event Order

Recommended emission sequence:

  1. identity — when user/session is known
  2. screen_schema — when entering a screen (with registered schema)
  3. component_input — on meaningful input changes
  4. validation_failed — on actionable validation failures

Identity Event

Set when user is identified:

AI.setUser(
  id = "user-123",
  phone = "9876543210",
  phoneMasked = true
)

Backend event: identity

Key fields:

{
  "event": "identity",
  "properties": {
    "user_id": "user-123",
    "phone": "9876543210",
    "phone_masked": true
  }
}

Note: Android SDK sends session_id: "unknown" until real session exists.

Screen Schema Events

Full Schema (registered)

Register schemas before init or on navigation:

// Before init for startup push
AI.registerScreenSchema(
  ScreenSchema(
    screenId = "pan_entry",
    title = "Enter PAN Details",
    components = listOf(
      ComponentSpec(
        id = "pan_field",
        type = "text_input",
        label = "PAN Number",
        validationRules = listOf(
          ValidationRule(
            ruleId = "pan_format",
            pattern = "[A-Z]{5}[0-9]{4}[A-Z]",
            errorMessage = "Invalid PAN format"
          )
        )
      )
    )
  )
)

Backend event: screen_schema

Lazy Schema Beacon (no registration)

When no schema registered for step:

AI.setKycStep("unknown_screen")

Backend event: screen_schema_lazy (minimal, no schema body)

Component Input Events

Report redacted input hints:

AI.reportComponentInput(
  componentId = "pan_field",
  hint = "ABCDE****F",  // Masked/redacted
  masked = true,
  screen = "pan_entry",
  componentType = "text_input"
)

Backend event: component_input

Key fields:

{
  "event": "component_input",
  "component_id": "pan_field",
  "masked": true,
  "properties": {
    "hint": "ABCDE****F"
  }
}

Important:

  • Always mask PII (phone, PAN, Aadhaar)
  • Debounce 300-500ms for text input
  • Only send meaningful changes

Validation Failure Events

Track field-level validation:

// Minimal
AI.trackValidationFailure(
  failureReasonCode = "pan_invalid",
  componentId = "pan_field"
)

// Recommended (explicit metadata)
AI.trackValidationFailure(
  failureReasonCode = "pan_invalid",
  componentId = "pan_field",
  componentType = "text_input",
  expectedPattern = "[A-Z]{5}[0-9]{4}[A-Z]",
  validationRuleId = "pan_format_v1",
  hint = "ABCDE****F",
  masked = true,
  businessStep = "PAN_ENTRY",
  validationIntent = "PAN_FORMAT",
  recoveryPlaybookId = "retry_pan_01"
)

Backend event: validation_failed

Key fields:

{
  "event": "validation_failed",
  "errors": ["pan_invalid"],
  "failure_reason_code": "pan_invalid",
  "component_id": "pan_field",
  "component_type": "text_input",
  "expected_pattern": "[A-Z]{5}[0-9]{4}[A-Z]",
  "validation_rule_id": "pan_format_v1",
  "business_step": "PAN_ENTRY",
  "validation_intent": "PAN_FORMAT",
  "recovery_playbook_id": "retry_pan_01"
}

Error Events

Generic error reporting:

AI.trackError(
  code = "network_timeout",
  properties = mapOf(
    "endpoint" to "/api/submit",
    "retry_count" to "3"
  )
)

Backend event: error_reported

Key fields:

{
  "event": "error_reported",
  "errors": ["network_timeout"],
  "properties": {
    "error_code": "network_timeout",
    "endpoint": "/api/submit",
    "retry_count": "3"
  }
}

Use for:

  • Network failures
  • UX issues
  • Non-field errors

Field Naming Consistency

FieldMeaningAlways Present
user_idStable user identifierYes
session_idUUID per app sessionYes
eventIngestion event typeYes
timestampUnix secondsYes
screen / screen_idCurrent screenWhen applicable
component_idUI componentComponent events
traceparentW3C trace contextRecommended
trace_idRequest correlationRecommended

Avoid Duplication

Keep one canonical location per datum:

  • Don't duplicate hint in multiple payload locations
  • Don't send both screen and screen_id with same value
  • Use properties only for extensible metadata

On this page