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

# Callbacks

Stay informed when events in Link occur, and simplify taking additional action.

Callbacks are activated by events in Link. They return event-specific information that can help automate taking additional related action.

<Note>
  Callbacks are not designed to be a primary source of analytics information. For detailed metrics on step-by-step conversion success rates, visit the **Conversion** area of <a href="https://console.argyle.com/dashboard" target="_blank">Console's Dashboard</a> or contact your customer success manager.
</Note>

## Callback formats

Although optional, adding callbacks is simple. Just add a few lines of code to your Link initialization.

Below are example Link initializations that include every callback:

<Tabs>
  <Tab title="Web">
    ```html theme={}
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <!-- This is needed in order to apply proper scaling on mobile devices -->
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
      </head>

      <body>
        <script src="https://plugin.argyle.com/argyle.web.v5.js"></script>
        <script type="text/javascript">
          const linkInstance = Argyle.create({
            userToken: 'USER_TOKEN',
            sandbox: true, // Set to false for production environment.
            // (Optional) Callback examples:
            onAccountConnected: (payload) => console.log('onAccountConnected', payload),
            onAccountCreated: (payload) => console.log('onAccountCreated', payload),
            onAccountError: (payload) => console.log('onAccountError', payload),
            onAccountRemoved: (payload) => console.log('onAccountRemoved', payload),
            onCantFindItemClicked: (payload) => console.log('onCantFindItemClicked', payload),
            onClose: () => console.log('onClose'),
            onDocumentsSubmitted: (payload) => console.log('onDocumentsSubmitted', payload),
            onFormSubmitted: (payload) => console.log('onFormSubmitted', payload),
            onUIEvent: (payload) => console.log('onUIEvent', payload),
            onError: (payload) => console.log('onError', payload),
            onTokenExpired: (updateToken) => {
              console.log('onTokenExpired');
              // Generate a new user token.
              // updateToken("<New user token>")
            },
          });
          linkInstance.open();
          // linkInstance.close() // Manually close Link (typically the user closes Link).
        </script>
      </body>
    </html>
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={}
    var config = LinkConfig(
        userToken: "USER_TOKEN",
        sandbox: true // Set to false for production environment.
    )
    // (Optional) Callback examples:
    config.onAccountConnected = { data in
        print("Result: onAccountConnected \(data)")
    }
    config.onAccountCreated = { data in
        print("Result: onAccountCreated \(data)")
    }
    config.onAccountError = { data in
        print("Result: onAccountError \(data)")
    }
    config.onAccountRemoved = { data in
        print("Result: onAccountRemoved \(data)")
    }
    config.onCantFindItemClicked = { data in
        print("Result: onCantFindItemClicked \(data)")
    }
    config.onClose = {
        print("Result: onClose")
    }
    config.onDocumentsSubmitted = { data in
        print("Result: onDocumentsSubmitted \(data)")
    }
    config.onFormSubmitted = { data in
        print("Result: onFormSubmitted \(data)")
    }
    config.onUIEvent = { data in
        print("Result: onUIEvent \(data)")
    }
    config.onError = { data in
        print("Result: onError \(data)")
    }
    config.onTokenExpired = { handler in
        print("onTokenExpired")
        // Generate a new user token.
        // handler(newToken)
    }

    ArgyleLink.start(from: viewController, config: config)
    // ArgyleLink.close()   // Manually close Link (typically the user closes Link).
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={}
    val config = LinkConfig(
        userToken = "USER_TOKEN",
        sandbox = true // Set to false for production environment.
    )
    // (Optional) Callback examples:
    config.onAccountConnected = { data ->
        Log.d("Result", "onAccountConnected $data")
    }
    config.onAccountCreated = { data ->
        Log.d("Result", "onAccountCreated $data")
    }
    config.onAccountError = { data ->
        Log.d("Result", "onAccountError $data")
    }
    config.onAccountRemoved = { data ->
        Log.d("Result", "onAccountRemoved $data")
    }
    config.onCantFindItemClicked = { data ->
        Log.d("Result", "onCantFindItemClicked $data")
    }
    config.onClose = {
        Log.d("Result", "onClose")
    }
    config.onDocumentsSubmitted = { data ->
        Log.d("Result", "onDocumentsSubmitted $data")
    }
    config.onFormSubmitted = { data ->
        Log.d("Result", "onFormSubmitted $data")
    }
    config.onUIEvent = { data ->
        Log.d("Result", "onUIEvent $data")
    }
    config.onError = { data ->
        Log.d("Result", "onError $data")
    }
    config.onTokenExpired = { handler ->
    	   // Generate a new user token.
        // handler(newToken)
    }

    ArgyleLink.start(context, config)
    // ArgyleLink.close()   // Manually close Link (typically the user closes Link).
    ```
  </Tab>

  <Tab title="React Native">
    ```js theme={}
    import { ArgyleLink } from '@argyleio/argyle-plugin-react-native';

    // ...

    const config = {
      userToken: 'USER_TOKEN',
      sandbox: true, // Set to false for production environment.
      // (Optional) Callback examples:
      onAccountConnected: (payload) => console.log('onAccountConnected', payload),
      onAccountCreated: (payload) => console.log('onAccountCreated', payload),
      onAccountError: (payload) => console.log('onAccountError', payload),
      onAccountRemoved: (payload) => console.log('onAccountRemoved', payload),
      onCantFindItemClicked: (payload) => console.log('onCantFindItemClicked', payload),
      onClose: () => console.log('onClose'),
      onDocumentsSubmitted: (payload) => console.log('onDocumentsSubmitted', payload),
      onFormSubmitted: (payload) => console.log('onFormSubmitted', payload),
      onUIEvent: (payload) => console.log('onUIEvent', payload),
      onError: (payload) => console.log('onError', payload),
      onTokenExpired: (updateToken) => {
        console.log('onTokenExpired');
        // Generate a new user token.
        // updateToken("<New user token>")
      },
    };

    ArgyleLink.start(config);
    // ArgyleLink.close()   // Manually close Link (typically the user closes Link).
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={}
    import 'package:argyle_link_flutter/link_config.dart';
    // (Required if using callbacks) Callback argument type definitions
    import 'package:argyle_link_flutter/account_data.dart';
    import 'package:argyle_link_flutter/argyle_link.dart';
    import 'package:argyle_link_flutter/form_data.dart';

    // ...

    final config = LinkConfig(
      userToken: 'USER_TOKEN',
      sandbox: true, // Set to false for production environment.
      // (Optional) Callback examples:
      onAccountConnected: (payload) => debugPrint('onAccountConnected'),
      onAccountCreated: (payload) => debugPrint('onAccountCreated'),
      onAccountError: (payload) => debugPrint('onAccountError'),
      onAccountRemoved: (payload) => debugPrint('onAccountRemoved'),
      onCantFindItemClicked: (payload) => debugPrint('onCantFindItemClicked'),
      onClose: () => debugPrint('onClose'),
      onDocumentsSubmitted: (payload) => debugPrint('onDocumentsSubmitted'),
      onFormSubmitted: (payload) => debugPrint('onFormSubmitted'),
      onUIEvent: (payload) => debugPrint('onUIEvent'),
      onError: (payload) => debugPrint('onError'),
      onTokenExpired: (updateToken) => {
        debugPrint('onTokenExpired')
        // Generate a new user token.
        // updateToken(newToken)
      },
    );

    ArgyleLink.start(config);
    // ArgyleLink.close()   // Manually close Link (typically the user closes Link).
    ```
  </Tab>
</Tabs>

## Account callbacks

<div className="argyle-divider" />

### `onAccountConnected`

Invoked when an account is successfully authenticated (including MFA) to an Item. Also invoked when a user reconnects a previously disconnected account.

**Returns**:

```json theme={}
AccountData (
    "accountId": String,
    "userId": String,
    "itemId": String
)
```

### `onAccountCreated`

Invoked when a user clicks **Connect** in Link, which creates an account for the user.

<Note>
  This callback is invoked *before* account authentication (successful or unsuccessful) to an Item.
</Note>

**Returns**:

```json theme={}
AccountData (
    "accountId": String,
    "userId": String,
    "itemId": String
)
```

### `onAccountError`

Invoked if an account fails to authenticate to an Item.

**Returns**:

```json theme={}
AccountData (
    "accountId": String,
    "userId": String,
    "itemId": String
)
```

### `onAccountRemoved`

Invoked when a user revokes access to a connected account.

**Returns**:

```json theme={}
AccountData (
    "accountId": String,
    "userId": String,
    "itemId": String
)
```

## User flow callbacks

<div className="argyle-divider" />

### `onCantFindItemClicked`

Invoked when the user selects **"If no results"** in Link, which is shown *only if* you selected the **Callback** [fallback experience](/console/flows/shareable-urls#argyle-link) when customizing any type of <a href="https://console.argyle.com/flows" target="_blank">Link Flow</a> in Console.

This callback closes Link and **returns the user's search query**.

<Note>
  The `onCantFindItemClicked` callback will always precede the `onClose` callback.
</Note>

### `onClose`

Invoked when the user closes Link.

**Returns**:

```json theme={}
UserData (
    "userSubmissionComplete": Boolean,
    "userAttemptedEmployerSelection": Boolean
)
```

* `userSubmissionComplete` — Will be `true` if at least one account is connected. Will remain `false` if no accounts are connected (including when only documents are uploaded or only a form is submitted).
* `userAttemptedEmployerSelection` — Will be `true` only if the user actively searched for an employer within Link.

<Note>
  When [integrations](/integrations/pos-los/ncino) are enabled that require a specific length of employment history, `userSubmissionComplete` will be `true` only when connected accounts meet history length requirements.
</Note>

### `onDocumentsSubmitted`

Invoked when the user selects **Submit** after initially uploading documents through Link's [document upload](/workflows/document-processing) workflow, and every subsequent document upload thereafter.

**Returns**:

```json theme={}
FormData (
    "accountId": String,  //  (deprecated)
    "userId": String
)
```

### `onFormSubmitted`

Invoked when a response form is submitted through Link's **"If no results"** experience (configurable via <a href="https://console.argyle.com/flows" target="_blank">Flows</a> in Console).

**Returns**:

```json theme={}
FormData (
    "accountId": String,
    "userId": String
)
```

### `onUIEvent`

Invoked when specific UI events occur in Link.

<Note>
  This callback and its event-specific return values are detailed in-depth in our [Tracking guide](/link/reference/tracking).
</Note>

## Operational callbacks

<div className="argyle-divider" />

### `onError`

Invoked when Link encounters an internal problem that breaks the flow for the user.

**Returns**:

```json theme={}
LinkError (
    "userId": String,
    "errorType": String (enum),
    "errorMessage": String,
    "errorDetails": String
)
```

* `userId` — ID of the user.
* `errorType` — Which [Link error](/link/reference/error-codes) occurred.
* `errorMessage` — The error message shown to the user.
* `errorDetails` - The "error details" of the Link error.

### `onTokenExpired`

Invoked when a [user token](/link/user-tokens) expires (iOS, Android, React Native, Flutter) or 5 minutes before a user token expires (Web).

<Note>
  After a user token expires, any additional actions taken by the user during the same Link session will result in an `invalid_user_token` error.
</Note>

This callback provides another function as a parameter, which can be used to update the user token for the user's current Link session. This prevents having to close and re-initialize Link for the user.

To use this function:

1. Create a new user token
2. Call the function with the user token as the argument
