# Event Callbacks

:::note
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation [here](/sdk-reference/web-sdk-reference).  Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade. <br /><br />Full rollout to all clients still TBD.
:::

The SDK provides callbacks to integrate with your application's logic.

> The snippets below show the callback shapes you'd assign to the element (e.g. `flow.onFinish = ...`) or set inside `config`. For full mounting examples (vanilla, React, Angular, Vue) see [IncodeFlow Component](/sdk-reference/web-sdk-2-incodeflow-component/) and [Framework Integration](/sdk-reference/web-sdk-2-framework-integration/).

## IncodeFlow Callbacks

### onFinish

Called when the verification flow finishes. This is the **primary** callback you should set:

```ts
flow.onFinish = (result) => {
  console.log('Action:', result?.action); // 'approved' | 'rejected' | 'none'
  console.log('Status:', result?.scoreStatus); // 'OK' | 'WARN' | 'FAIL' | ...
  console.log('Redirect:', result?.redirectionUrl);

  if (result?.action === 'approved') {
    // Proceed with your flow
  }
};
```

`result` may be `undefined` (the signature is `(result?: FinishStatus) => void`), so always null-check.

### onError

Called when an error occurs:

```ts
flow.onError = (error, code) => {
  console.error('Verification error:', error, code);
  // Show error UI or redirect
};
```

### onModuleLoading / onModuleLoaded

Track lazy-loading of each module's UI chunk. These are config callbacks, not element callbacks:

```ts
flow.config = {
  token: session.token,
  onModuleLoading: (moduleKey) => setLoading(moduleKey),
  onModuleLoaded: (moduleKey) => setLoading(null),
};
```

### onWasmWarmup

Called when ML models begin loading:

```ts
flow.config = {
  token: session.token,
  onWasmWarmup: (pipelines) => console.log('Loading ML models:', pipelines),
};
```

### onFlowEvent

Subscribe to curated flow milestones. For raw analytics events such as `screenOpened` or `elementClicked`, use `subscribeEvent` from `@incodetech/core/events` instead.

```ts
flow.config = {
  token: session.token,
  onFlowEvent: (event) => console.log('Flow event:', event.type, event),
};
```

Branch on `event.type`. The `FlowEvent` union and its member types are exported from `@incodetech/core/flow-events`:

```ts
import type { FlowEvent } from '@incodetech/core/flow-events';

flow.config = {
  token: session.token,
  onFlowEvent: (event: FlowEvent) => {
    if (event.type === 'flow.module.started') {
      console.log(`Starting ${event.module}`);
    }
  },
};
```

| `event.type`             | Type                       | Additional fields                                                            |
| ------------------------ | -------------------------- | ---------------------------------------------------------------------------- |
| `flow.started`           | `FlowStartedEvent`         | –                                                                            |
| `flow.ready`             | `FlowReadyEvent`           | `payload`: `{ flow, steps, currentStep?, currentStepIndex }`                  |
| `flow.module.started`    | `FlowModuleStartedEvent`   | `module`, `payload`: `{ moduleIndex?, totalModules? }`                        |
| `flow.module.completed`  | `FlowModuleCompletedEvent` | `module`, `payload`: `{ moduleIndex?, totalModules? }`                        |
| `flow.completed`         | `FlowCompletedEvent`       | `payload?`: the finish status                                                 |
| `flow.error`             | `FlowErrorEvent`           | `error`: the error message                                                    |
| `flow.closed`            | `FlowClosedEvent`          | –                                                                            |

Every event also carries `timestamp` (epoch milliseconds) and an optional `interviewId`. All events except `flow.started` also carry an optional `flowId`.

`FlowEventListener` types the callback itself, and `FlowEventSubscribable` types a manager that exposes this stream.

## Individual Module Callbacks

The standalone module elements (`<incode-phone>`, `<incode-selfie>`, `<incode-id>`, …) follow the same property-assignment pattern.

### onFinish

```ts
phone.onFinish = () => console.log('Phone verified!');
```

### onError

```ts
selfie.onError = (error) => console.error('Selfie error:', error);
```

## Finish Status

The `onFinish` callback on `IncodeFlow` receives a `FinishStatus` object:

```typescript
import type { FinishStatus } from '@incodetech/core/flow';

// FinishStatus shape:
// {
//   redirectionUrl: string;
//   action: 'approved' | 'rejected' | 'none';
//   scoreStatus: 'OK' | 'WARN' | 'MANUAL_OK' | 'FAIL' | 'UNKNOWN' | 'MANUAL_FAIL';
// }
```

`FinishStatus` is also re-exported from `@incodetech/core/session` if you prefer that grouping.

| Field            | Description                      |
| ---------------- | -------------------------------- |
| `action`         | Final verification decision      |
| `scoreStatus`    | Detailed status from scoring     |
| `redirectionUrl` | Configured redirect URL (if any) |

## Dashboard Events

For tracking events to the Incode dashboard (module opens, screen transitions, custom events), see [Dashboard Events](/sdk-reference/web-sdk-2-events/).

## See Also

- [IncodeFlow Component](/sdk-reference/web-sdk-2-incodeflow-component/): Full component reference
- [Individual Modules](/sdk-reference/web-sdk-2-individual-modules/): Module-specific callbacks
- [Dashboard Events](/sdk-reference/web-sdk-2-events/): Tracking events to the dashboard
