> ## Documentation Index
> Fetch the complete documentation index at: https://docs.methodfi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Opal Events

export const ParamList = ({items = [], is_child = false}) => {
  return items.map(item => {
    const field_props = {
      id: Math.random().toString(),
      body: item.name,
      name: item.name,
      type: item.type,
      required: item.required
    };
    const enums = item.enums || [];
    const items = item.items || [];
    const has_items = items?.length > 0;
    const has_enums = enums?.length > 0;
    const should_default_open = item.defaultOpen || false;
    const render_child_item = () => {
      const child_props = {
        title: has_enums ? "Possible enum values" : "properties"
      };
      if (should_default_open) child_props.defaultOpen = true;
      const has_inline_enums = has_enums && enums.every(enum_item => typeof enum_item === 'string') && enums.map((enum_item, idx) => {
        const is_last = idx === enums.length - 1;
        const is_2nd_to_last = idx === enums.length - 2;
        return <>
            <code>{enum_item}</code>
            {is_last && ''}
            {is_2nd_to_last && ' or '}
            {!is_last && !is_2nd_to_last && ', '}
          </>;
      });
      const enum_list = has_enums && !has_inline_enums && <Accordion {...child_props}>
          {enums.map((enum_item, index) => <div key={`enum-${index}`}>
              <code>{enum_item.name}</code>
              <br />
              <p>{enum_item.description}</p>
            </div>)}
        </Accordion>;
      const item_list = has_items && <Expandable {...child_props}>
          <ParamList items={items || []} is_child />
        </Expandable>;
      return <>
          <p>
            {item.description}
            {has_inline_enums && [has_inline_enums.length > 1 ? ' One of ' : ' Must be ', ...has_inline_enums]}
          </p>

          {enum_list}
          {item_list}
        </>;
    };
    return is_child ? <ResponseField {...field_props}>{render_child_item()}</ResponseField> : <ParamField {...field_props}>{render_child_item()}</ParamField>;
  });
};

Communication between Opal and your app is handled through a consistent, mode-aware event system. Events are emitted throughout the user session to indicate progress, completion, errors, and important milestones.

## Listening to Events

We strongly recommend using one of the Opal SDKs to receive typed events and lifecycle callbacks. The SDKs provide `onEvent`, `onOpen`, and `onExit` handlers and expose a small enum of well-known events under `OpalEventType` for convenience (e.g., `SESSION_STARTED`, `SESSION_COMPLETED`).

Each Opal mode (`identity_verification`, `connect`, `card_connect`, `account_verification`, `transactions`) emits a set of mode‑specific events in addition to default session events. See below for structure, a complete list, and examples.

## Event Structure

All Opal events follow a consistent structure:

```json theme={null}
{
  "type": "opal.session.started",
  "mode": "opal",
  "object": "session",
  "action": "started",
  "timestamp": "2025-06-10T22:50:53.024Z",
  "data": null
}
```

### Event fields

| Field       | Type           | Description                                                                                                     |
| ----------- | -------------- | --------------------------------------------------------------------------------------------------------------- |
| `type`      | string         | Fully qualified event name: `<flow>.<object>.<action>` or `opal.session.<action>` for default session events.   |
| `mode`      | string         | The active operational mode (e.g., `connect`, `identity_verification`, `account_verification`, `transactions`). |
| `object`    | string         | The related object (e.g., `session`, `flow`, `step`, `identity`, `card`, `accounts`).                           |
| `action`    | string         | The action that occurred (e.g., `started`, `completed`, `verified`, `errored`).                                 |
| `timestamp` | string         | ISO 8601 timestamp of when the event occurred.                                                                  |
| `data`      | object \| null | Additional context that varies by event type; may be `null` for lifecycle events.                               |

### Possible flows:

* `identity_verification`
* `connect`
* `account_verification`
* `transactions`

## Sample Events

### opal.session.started

```json theme={null}
{
  "type": "opal.session.started",
  "mode": "connect",
  "object": "session",
  "action": "started",
  "timestamp": "2025-06-10T22:50:53.024Z",
  "data": null
}
```

### opal.session.errored

```json theme={null}
{
  "type": "opal.session.errored",
  "mode": "connect",
  "object": "session",
  "action": "errored",
  "timestamp": "2025-06-10T22:50:53.024Z",
  "data": {
    "type": "INVALID_REQUEST",
    "sub_type": "INVALID_SMS_CODE",
    "message": "Invalid request please try again"
  }
}
```

### connect.flow\.completed

```json theme={null}
{
  "type": "connect.flow.completed",
  "mode": "connect",
  "object": "flow",
  "action": "completed",
  "timestamp": "2025-06-10T22:50:53.024Z",
  "data": {
    "accounts": ["acc_ge9hxMTPGdXmQ"],
    "entity_id": "ent_wrDBN43PR8LKC"
  }
}
```

## Event Categories

### Default session events (always available)

* `opal.session.started` - Opal UI opened and session began
* `opal.session.completed` - User completed the flow successfully
* `opal.session.errored` - A recoverable or terminal error occurred
* `opal.session.exited` - User exited or dismissed Opal

### Generic flow and step events

Emitted in addition to the default session events. These mirror the active mode‑specific events but are prefixed with `opal` and can be emitted for any mode.

#### Flow

* `opal.flow.started` - A sub‑flow of Opal started (e.g., identity verification, account selection, verification).
* `opal.flow.completed` - A sub‑flow of Opal completed. This does not always signify the end of the session; use `opal.session.completed` to detect when Opal is fully completed.

#### Step

* `opal.step.started` - A new step started (e.g., phone input, card selection, CVV input).
* `opal.step.completed` - A step completed and the next page is opening.

Notes:

* Additional mode-specific events may be introduced over time. Your handler should use the `OpalEventType` enum to handle the specific cases you need.

## All Event Types

The following table lists all currently supported event types with their `OpalEventType` mapping, and when they are typically emitted.

| Event (OpalEventType - type)                                              | When you might see it                              |
| ------------------------------------------------------------------------- | -------------------------------------------------- |
| `SESSION_STARTED` - `opal.session.started`                                | Opal UI opened and session began.                  |
| `SESSION_COMPLETED` - `opal.session.completed`                            | User completed the overall Opal flow successfully. |
| `SESSION_ERRORED` - `opal.session.errored`                                | A recoverable or terminal error occurred.          |
| `SESSION_EXITED` - `opal.session.exited`                                  | User closed or dismissed Opal before completion.   |
| `FLOW_STARTED` - `opal.flow.started`                                      | A sub-flow (for any mode) started.                 |
| `FLOW_COMPLETED` - `opal.flow.completed`                                  | A sub-flow (for any mode) completed.               |
| `STEP_STARTED` - `opal.step.started`                                      | A step (screen) started.                           |
| `STEP_COMPLETED` - `opal.step.completed`                                  | A step (screen) completed.                         |
| `IDV_FLOW_STARTED` - `identity_verification.flow.started`                 | Identity Verification flow started.                |
| `IDV_STEP_STARTED` - `identity_verification.step.started`                 | A step in Identity Verification started.           |
| `IDV_STEP_COMPLETED` - `identity_verification.step.completed`             | A step in Identity Verification completed.         |
| `IDV_FLOW_COMPLETED` - `identity_verification.flow.completed`             | Identity Verification flow completed.              |
| `IDV_VERIFICATION_COMPLETED` - `identity_verification.identity.completed` | Identity successfully verified (KYC passed).       |
| `CXN_FLOW_STARTED` - `connect.flow.started`                               | Connect flow started.                              |
| `CXN_STEP_STARTED` - `connect.step.started`                               | A step in Connect started.                         |
| `CXN_STEP_COMPLETED` - `connect.step.completed`                           | A step in Connect completed.                       |
| `CXN_FLOW_COMPLETED` - `connect.flow.completed`                           | Connect flow completed.                            |
| `CXN_ACCOUNTS_SELECTED` - `connect.accounts.selected`                     | User selected one or more accounts to connect.     |
| `AVF_FLOW_STARTED` - `account_verification.flow.started`                  | Account Verification flow started.                 |
| `AVF_STEP_STARTED` - `account_verification.step.started`                  | A step in Account Verification started.            |
| `AVF_STEP_COMPLETED` - `account_verification.step.completed`              | A step in Account Verification completed.          |
| `AVF_FLOW_COMPLETED` - `account_verification.flow.completed`              | Account Verification flow completed.               |
| `AVF_CARD_VERIFIED` - `account_verification.card.verified`                | Card verified successfully.                        |
| `TXN_FLOW_STARTED` - `transactions.flow.started`                          | Transactions flow started.                         |
| `TXN_STEP_STARTED` - `transactions.step.started`                          | A step in Transactions started.                    |
| `TXN_STEP_COMPLETED` - `transactions.step.completed`                      | A step in Transactions completed.                  |
| `TXN_FLOW_COMPLETED` - `transactions.flow.completed`                      | Transactions flow completed.                       |
| `TXN_ACCOUNTS_LINKED` - `transactions.accounts.linked`                    | Accounts linked and subscribed for transactions.   |

### Data Payloads

The following events always include a non-null `event.data` payload:

* `identity_verification.identity.completed`
* `connect.accounts.selected`
* `account_verification.card.verified`
* `transactions.accounts.linked`

Use these payloads to retrieve context such as selected accounts, verification results, or linkage details.

## Enhanced Event Handling

### Using the JavaScript SDK

```javascript theme={null}
import { OpalEventType } from '@methodfi/opal-react';

const config = {
  onEvent: (event) => {
    console.log("Event received:", event.type);

    // Handle specific events using the OpalEventType enum
    switch (event.type) {
      case OpalEventType.SESSION_STARTED:
        // Session lifecycle
        break;
      case OpalEventType.SESSION_COMPLETED:
        // Entire Opal session completed successfully
        break;
      case OpalEventType.SESSION_ERRORED:
        // Handle recoverable or terminal error
        console.error("Opal error:", event.data);
        break;
      case OpalEventType.IDV_VERIFICATION_COMPLETED:
        // Identity verification completed; payload contains verification details
        handleIdentityVerified(event.data);
        break;
      case OpalEventType.CXN_ACCOUNTS_SELECTED:
        // User selected accounts in Connect
        handleAccountsSelected(event.data);
        break;
      case OpalEventType.AVF_CARD_VERIFIED:
        // Card verified in Account Verification
        handleCardVerified(event.data);
        break;
      case OpalEventType.TXN_ACCOUNTS_LINKED:
        // Accounts linked for Transactions
        handleAccountsLinked(event.data);
        break;
      default:
        // Optionally handle generic flow/step events
        break;
    }
  },

  // Specific event handlers
  onSuccess: (payload) => {
    // Called for successful completion events
    console.log("Success:", payload);
  },

  onError: (error) => {
    // Enhanced error handling with detailed information
    console.error("Error:", error.code, error.message);
    console.error("Details:", error.details);
  },
};

const opal = new MethodOpal(config);
```

## PostMessage Communication

For applications not using the Opal SDKs, you can listen to events via PostMessage:

### Setup PostMessage Listener

```javascript theme={null}
window.addEventListener("message", function (event) {
  // Verify origin for security
  if (event.origin !== "https://opal.production.methodfi.com") {
    return;
  }

  const opalEvent = event.data;
  console.log("Opal event:", opalEvent.type, opalEvent.data);

  // Handle events
  switch (opalEvent.type) {
    case OpalEventType.SESSION_STARTED:
      console.log("Opal started");
      break;
    case OpalEventType.SESSION_COMPLETED:
      console.log("Opal completed:", opalEvent.data);
      break;
  }
});
```

## Best Practices

### Event Handling

* Always verify event origins for security
* Use event filtering to reduce noise
* Implement proper error handling for all events
* Log events for debugging and analytics

### Security

* Validate all event data before processing
* Never trust client-side events for critical business logic
