Real Time Event Notifications
Objective
Real-time events are milestone notifications emitted by the SDK during the user's onboarding journey. These events provide visibility into the user's progress through each step of the process.
Real-Time Event Notifications provide immediate insights into user journeys through event-based architecture.
These events can be integrated with your CRM systems, analytics tools, or notification tools, enabling:
- Real-time tracking of user progress
- Trigger-based interventions (e.g., reminders, agent calls)
- Enhanced funnel analytics and proactive drop-off management
Real-time event notifications must be enabled for your account before you can receive them. Even if you implement the event listeners correctly, you will not receive any events unless this feature is enabled. Please contact HyperVerge to enable real-time events for your account.
Prerequisites
Before integrating real-time events, ensure your SDK meets the following version requirements:
| Platform | Requirement |
|---|---|
| Web SDK | Version ≥ 10.0.0 |
| Mobile SDKs (Android, iOS, React Native, Flutter) | Webcore must be enabled with version ≥ 10.0.0. Contact HyperVerge support to confirm the minimum native SDK version for your platform. |
Event Details
When is it triggered?
Events are triggered when a user reaches a milestone in their journey, such as starting or completing a step or substep with event triggers enabled.
Supported Events
Real-time event notifications emit the following six events:
| Event Name | Triggered When |
|---|---|
workflow_started | The user begins the onboarding workflow |
step_started | The user begins a step |
substep_started | The user begins a substep |
step_completed | The user completes a step |
substep_completed | The user completes a substep |
workflow_completed | The user completes the onboarding workflow |
Event Schema
All events follow this generic schema:
{
"schemaVersion": "2.0.0",
"eventName": "step_completed",
"timestamp": "2025-04-21T10:35:40.321Z",
"sdkVersion": "0.45.0",
"transactionId": "transactionId_1234",
"workflowId": "onboarding",
"workflowVersion": "1.2.3",
"appId": "abcdef",
"stepId": "digilocker",
"subStepId": "digilocker_instructions_form",
"properties": {}
}
Field Descriptions
| Field | Type | Description |
|---|---|---|
schemaVersion | string | The schema version. Use this to distinguish v2 events from v1 |
eventName | string | The name of the event |
timestamp | string | The UTC time of the event. Important for sequencing |
sdkVersion | string | The version of the SDK that sent the event |
transactionId | string | The unique identifier of the application |
workflowId | string | The unique identifier of the workflow |
workflowVersion | string | The version of the workflow configuration |
appId | string | The appId mapped to the application |
stepId | string | The identifier of the step. Empty for workflow-level events |
subStepId | string | The identifier of the substep. Present only for substep-related events, empty otherwise |
properties | JSON object | Additional attributes configured via the workflow builder, forwarded in all events |
Event Payload Examples
- Workflow Started
- Step Started
- Substep Started
{
"eventName": "workflow_started",
"stepId": "",
"subStepId": "",
"properties": {
"key": "value"
}
}
{
"eventName": "step_started",
"stepId": "step_A",
"subStepId": "",
"properties": {
"key": "value"
}
}
{
"eventName": "substep_started",
"stepId": "step_A",
"subStepId": "substep_A1",
"properties": {
"key": "value"
}
}
- Step Completed
- Substep Completed
- Workflow Completed
{
"eventName": "step_completed",
"stepId": "step_A",
"subStepId": "",
"properties": {
"key": "value"
}
}
{
"eventName": "substep_completed",
"stepId": "step_A",
"subStepId": "substep_A1",
"properties": {
"key": "value"
}
}
{
"eventName": "workflow_completed",
"stepId": "",
"subStepId": "",
"properties": {
"key": "value"
}
}
SDK Integration
Use the SDK-provided addEventListener API to subscribe to real-time milestone events. Implement these listeners before launching the HyperKYC SDK to ensure you don't miss any events.
Android
Implement real-time event notifications in your Android app using Java or Kotlin.
- Java
- Kotlin
HyperKyc.addEventListener(jsonObject -> {
// Handle real-time events
// ....
return Unit.INSTANCE;
});
HyperKyc.removeAllEventListeners();
HyperKyc.addEventListener { event ->
// Handle real-time events
}
HyperKyc.removeAllEventListeners()
iOS
Implement real-time event notifications in your iOS app using Swift closures.
HyperKyc.addEventListener { event in
// Handle real-time events
}
HyperKyc.removeAllEventListeners()
React Native
Implement real-time event notifications in your React Native app using JavaScript callbacks.
// Import HyperKyc from react-native-hyperkyc-sdk
import HyperKyc from 'react-native-hyperkyc-sdk';
// [Recommended] Attach event listeners before launching HyperKYC SDK
HyperKyc.addEventListener((event) => {
// Handle real-time events
});
// [Recommended] Remove all event listeners after receiving the SDK response
HyperKyc.removeAllEventListeners();
Flutter
Implement real-time event notifications in your Flutter app using stream-based listeners.
// [Recommended] Attach event listeners before launching HyperKYC SDK
HyperKyc.addEventListener(listener: (event) {
// Handle real-time events
});
// [Recommended] Remove all event listeners after receiving the SDK response
await HyperKyc.removeAllEventListeners();
Advanced Use Case
You only need to implement the following setup if:
- You are targeting devices where:
- "Don't Keep Activities" is enabled, or
- Low-memory scenarios are likely
Without this setup, addEventListener() and removeAllEventListeners() may stop working when navigating between native and Flutter screens in the above mentioned scenarios.
Setup for Reliable Event Handling
In MainApplication.java
@Override
public void onCreate() {
super.onCreate();
FlutterEngine flutterEngine = new FlutterEngine(this);
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
FlutterEngineCache.getInstance().put("unique_engine_id", flutterEngine);
}
In MainActivity.java
public class MainActivity extends FlutterActivity {
@Override
public FlutterEngine provideFlutterEngine(Context context) {
return FlutterEngineCache.getInstance().get("unique_engine_id");
}
}
If your application already implements a cached FlutterEngine, you can reuse it instead of creating a new instance.
FAQs
| Question | Answer |
|---|---|
| Do I need this setup in all cases? | No. Only if your app uses Flutter + native Android and may run on devices with aggressive memory clearing. |
| What happens without this setup? | addEventListener() and similar callbacks may stop working after FlutterActivity gets destroyed. |
| We already use a cached FlutterEngine. Can we reuse it? | Yes, reuse the same engine name. |
| Is this needed for iOS? | No. iOS retains the Flutter engine across transitions by default. |
Risk Assessment
| Touchpoint | Description | Risk | Impact |
|---|---|---|---|
| App Startup Time | Slightly slower due to FlutterEngine init | Low | ~30–80ms |
| Memory Usage | One FlutterEngine stays in memory | Low–Medium | ~5–15MB |
| Plugin Conflicts | Sharing engine with other plugins | Very Low | N/A |
| Dev Effort | Minor changes to MainActivity and MainApplication | Low | ~10–15 lines |
| If Setup is Skipped | Event listeners may stop working | High | 100% event loss in edge cases |
Summary Table
| Requirement | Purpose | Optional? | iOS Impact? | Can Be Shared? |
|---|---|---|---|---|
provideFlutterEngine() override | Keeps Flutter alive across native screens | Only if needed | Not needed | Yes |
FlutterEngineCache.put(...) | Globally accessible engine | Only if needed | Not needed | Yes |
Recommendation
- Add this setup only if your app frequently navigates between Flutter and native Android screens and you anticipate low-memory situations or "Don't Keep Activities" to be relevant for your user base.
- If a cached engine already exists, reuse it to reduce duplication.
- No action required for iOS. FlutterEngine detachment isn't an issue there.
Web
Implement real-time event notifications in your web application using the HyperKYCModule.
HyperKYCModule.addEventListener((event) => {
// Handle real-time events
})
HyperKYCModule.removeAllEventListeners()
addEventListener()is not the same as DOM event listeners; it simply acts as a callback mechanism.removeAllEventListeners()clears any internal references. Must be called at the end of the journey to avoid dangling references.- Calling
removeAllEventListeners()inside an event listener does not cancel pending future events (in Android & Web platforms, yet).
Best Practices
- Attach event listeners before launching the HyperKYC SDK.
- Do not execute blocking code (e.g., synchronous heavy logic) inside the event listener callback.
- Especially important for JavaScript-based environments which run on a single thread.
- Use async/await, setTimeout, or background queues.
- Do not execute main-thread blocking code inside the event listener callback.
- Always call
removeAllEventListeners()after SDK completion to avoid memory leaks.