> For the complete documentation index, see [llms.txt](https://docs.vida.id/identity-stack/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vida.id/identity-stack/verify/liveness/integration/liveness-web-sdk/customization/callback-methods.md).

# Callback Methods

### Response structure for callback methods - Samples <a href="#response-structure-for-callback-methods-samples" id="response-structure-for-callback-methods-samples"></a>

{% code expandable="true" %}

````js
# Liveness Workflow — Callback Methods & Response Structure

## Overview

The liveness workflow provides callback methods to handle the result of liveness verification. The two primary callbacks are **`onComplete`** and **`onError`**.

By default, `onComplete` fires only when liveness passes — so you can treat it as a success callback. All failure scenarios are routed to `onError`.

## Usage

```js
onComplete: (data) => {
  console.log('Completed', data);
},

onError: (data) => {
  console.log('Error', data);
}
```

---

## Primary Callbacks

### `onComplete`

Called when liveness verification passes successfully. We recommend checking `code` and `liveImage` in the response for additional confirmation.

**Response structure:**

```js
{
  "score": 0.266861,
  "liveImage": true,
  "message": "Selfie photo is a live photo",
  "code": 1043,
  "imgManipulationScore": 0.093356,
  "transactionId": "fa581b84-6d90-9cdd-f073-18fd020be300",
  "base64Image": "data:image/jpeg;base64,..."
}
```
**Color flash (smart liveness) response:**

When color flash is enabled, the response includes a `livenessScores` array with individual scores for each verification method:

```js
{
  "score": 0.277815,
  "liveImage": true,
  "message": "Smart liveness success",
  "code": 1043,
  "transactionId": "2a58d634-d137-44c1-9527-cec61891e8df",
  "base64Image": "data:image/jpeg;base64,...",
  "attemptedTransactionIds": ["2a58d634-d137-44c1-9527-cec61891e8df"],
  "livenessScores": [
    { "type": "passiveLiveness", "score": 0.171321 },
    { "type": "imageManipulation", "score": 0.093166 },
    { "type": "colorCaptcha", "score": 0.277815 }
  ]
}
```

**`attemptedTransactionIds`:**

If there were multiple retry attempts, an `attemptedTransactionIds` array is included containing the transaction IDs from all attempts. This field is only present when there are more than 1 attempt.

```js
{
  "score": 0.266861,
  "liveImage": true,
  "message": "Selfie photo is a live photo",
  "code": 1043,
  "transactionId": "latest-txn-id",
  "attemptedTransactionIds": ["first-attempt-txn-id", "second-attempt-txn-id", "latest-txn-id"],
  "base64Image": "data:image/jpeg;base64,..."
}
```

---

### `onError`

Called when an error occurs during the liveness flow. This includes api errors, frontend errors (camera, network, timeout, user cancellation) and max retries exhausted.

**When `skipSelfieReviewScreen: false` (Default):**

- Liveness failures due to image quality or threshold are retried by the user — `onError` fires only when max retries are exhausted or when api fails due to system error or any unknown error, with the last API response included in the `response` field
- `onComplete` does NOT fire for failures — it only fires on success

**When `skipSelfieReviewScreen: true`:**

- Liveness failures due to image quality or threshold go to `onError` immediately since there is no review/retry screen and its the end of the flow. All other errors mentioned above also go to `onError`

**Network error:**

```js
{
  "code": 40001,
  "message": "Unable to proceed, please check your connection"
}
```

**Network timeout:**

```js
{
  "code": 40002,
  "message": "Unable to proceed due to network timeout, please check your connection"
}
```

**Token expired / unauthorized:**

```js
{
  "code": 40003,
  "message": "Unable to proceed, ensure authorization method is correct and token is not expired"
}
```

**Camera permission denied:**

```js
{
  "code": 70001,
  "message": "Unable to proceed, the functionality will not work without Camera permissions"
}
```

**Face detection model download failed:**

```js
{
  "code": 70002,
  "message": "Unable to proceed, failed to download face landmark models"
}
```

**Unsupported device/browser:**

```js
{
  "code": 70003,
  "message": "Unable to proceed, browser or device doesn't support this functionality"
}
```

**Camera not found:**

```js
{
  "code": 70005,
  "message": "Unable to proceed, No camera device found"
}
```

**Detection timeout:**

```js
{
  "code": 70007,
  "message": "Detection timed out"
}
```

**User cancelled (closed modal):**

```js
{
  "code": 70008,
  "message": "User cancelled liveness process by closing the modal"
}
```

When the user manually closes the modal after a liveness API failure, the error response includes the last liveness error details along with the selfie image:

```js
{
  "code": 70008,
  "message": "User cancelled liveness process by closing the modal",
  "response": {
    "score": -1,
    "liveImage": false,
    "message": "Detect Un-standardized Image Quality",
    "code": 1051,
    "transactionId": "d61f047d-3435-bf8c-2138-4b8a2fc05e87",
    "base64Image": "data:image/jpeg;base64,..."
  }
}
```

**Max retry exhausted:**

Includes the last liveness API response wrapped inside a `response` key:

```js
{
  "code": 70010,
  "message": "Maximum attempt to retry liveness has exhausted, Try again later",
  "response": {
    "score": -1,
    "liveImage": false,
    "message": "Detect Un-standardized Image Quality",
    "code": 1051,
    "transactionId": "d61f047d-3435-bf8c-2138-4b8a2fc05e87",
    "base64Image": "data:image/jpeg;base64,..."
  }
}
```

**Color flash upload error:**

```js
{
  "code": 50006,
  "message": "Unknown error occurred during color flash image upload, please try again later"
}
```

**Unknown error:**

```js
{
  "code": 50005,
  "message": "Unknown error occurred, please try again later"
}
```

#### Frontend Error Codes Reference

| Code  | Description                          |
| ----- | ------------------------------------ |
| 40001 | Network offline                      |
| 40002 | Network timeout                      |
| 40003 | Token expired or unauthorized        |
| 50005 | Unknown error                        |
| 50006 | Color flash image upload error       |
| 70001 | Camera permission denied             |
| 70002 | Face detection model download failed |
| 70003 | Unsupported device/browser           |
| 70004 | Video frame processing failed        |
| 70005 | No camera device found               |
| 70006 | Image capture failed                 |
| 70007 | Face detection timeout               |
| 70008 | User cancelled (closed modal)        |
| 70009 | Camera failed to start               |
| 70010 | Max retry attempts exhausted         |
| 70011 | Virtual camera detected              |

---

## Intermediate Callbacks (Optional)

### `onLivenessApiError`

Fired immediately when the liveness API call fails. Use this only if you need to react to API failures in real-time (e.g., logging, analytics). For handling the final outcome of the flow, use `onError` instead.

```js
onLivenessApiError: (data) => {
  console.log('Liveness API error', data.code, data.message);
};
```

### `onSelfieCapture`

Called when a selfie is captured. Receives the base64 image string. Useful for custom processing or analytics before the liveness API is called.

```js
onSelfieCapture: (image) => {
  // image is a base64 encoded JPEG string
  console.log('Selfie captured', image);
};
```

## Key Fields Reference

| Field                     | Description                                                                           |
| ------------------------- | ------------------------------------------------------------------------------------- |
| `code`                    | Response code. `1043` = liveness passed. Other codes indicate specific failures.                      |
| `liveImage`               | `true` if liveness passed, `false` otherwise. **Always check this field.**                            |
| `score`                   | Liveness confidence score                                                                             |
| `message`                 | Human-readable result description                                                                     |
| `imgManipulationScore`    | Image manipulation detection score                                                                    |
| `transactionId`           | Transaction ID of the latest attempt                                                                  |
| `attemptedTransactionIds` | Array of all attempt transaction IDs. Only present when there were multiple attempts.                 |
| `base64Image`             | Captured selfie image (base64 JPEG)                                                                   |
| `livenessScores`          | Array of individual scores per verification method (color flash only). Each entry has `type` and `score`. Types: `passiveLiveness`, `imageManipulation`, `colorCaptcha`. |

````

{% endcode %}
