# SDK response update 3.1.0.0

As part of the SDK update, starting now we will generate standardized response objects, including the full detail of fields and their possible values.

Additionally, we improved the tagging logic to correctly detect icons and related events. With these improvements, when a spoofing-related event is detected, a transaction will be generated and the event will be recorded with its corresponding details.

If spoofing is detected, an evidence image will also be sent to the customer-provided **webhook**. Moreover, from now on the transaction details (including the transaction number) will be delivered through the webhook to ensure an auditable record of the event.

<p class="callout info">**Expected response:** Transaction details sent to the webhook.</p>

<p class="callout info">**SDK response level (PSA):** This information will be returned by the SDK as part of the standardized response object.</p>

```json
{
  "processType": "liveness",
  "statusCode": 1,
  "detail": {
    "status": "approved",
    "reason": {
      "name": "NOT_ALERT",
      "description": "The transaction was approved."
    },
    "uidDevice": "1da62007d8974a9fa71e18cba76f6fc1",
    "keyProcessLiveness": "69c265aeca9d4863b61b1fc6a8099f52",
    "processId": "3f2b9c1e-7a4d-4f2a-9c0c-6c4c2e9b8d12",
    "image": {
      "encoding": "base64",
      "mimeType": "image/jpeg",
      "data": "<BASE64>"
    }
  }
}
```

<div class="flex flex-col text-sm pb-25" id="bkmrk-field-description%C2%A0-p"><article class="text-token-text-primary w-full focus:outline-none [--shadow-height:45px] has-data-writing-block:pointer-events-none has-data-writing-block:-mt-(--shadow-height) has-data-writing-block:pt-(--shadow-height) [&:has([data-writing-block])>*]:pointer-events-auto scroll-mt-[calc(var(--header-height)+min(200px,max(70px,20svh)))]" data-scroll-anchor="true" data-testid="conversation-turn-14" data-turn="assistant" data-turn-id="request-WEB:acc32a90-76b7-4467-bd78-c7786280444a-6" dir="auto" tabindex="-1">### Field description 

<div class="text-base my-auto mx-auto pb-10 [--thread-content-margin:--spacing(4)] @w-sm/main:[--thread-content-margin:--spacing(6)] @w-lg/main:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:40rem] @w-lg/main:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn" tabindex="-1"><div class="flex max-w-full flex-col grow"><div class="min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&]:mt-1" data-message-author-role="assistant" data-message-id="f90a16b0-4ac0-4830-bfc4-9bda7ad0a0b2" data-message-model-slug="gpt-5-2-thinking" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[1px]"><div class="markdown prose dark:prose-invert w-full wrap-break-word dark markdown-new-styling">- **processType**: Type of process executed.
    
    
    - Possible values: `"liveness" | "cardcapture"`
    - Notes:
        
        
        - If `processType = "liveness"`, the field `keyProcessLiveness` **may be present**.
        - If `processType = "cardcapture"`, `keyProcessLiveness` **must NOT be returned**.
- **Side**: Indicates which side of the document was captured**.  
    - Possible values: `"front" | "back"`
    - Notes: 
        - If `processType = "liveness"`, the field **Side** **must NOT be returned**.
        - If `processType = "cardcapture"`, **Side** **may be present**.
- **statusCode**: Numeric result code of the process.
    
    
    - `1` = approved
    - `2` = rejected
    - `3` = failed
- **detail**: Object containing the detailed outcome.
    
    
    - **status**: Text status of the result.
        
        
        - Possible values: `"approved" | "rejected" | "failed"`
    - **reason**: Human-readable reason for the result.
        
        
        - **name**: Short label describing the reason (e.g., `"No alerts"`).
        - **description**: Longer explanation of the reason (e.g., `"The transaction was approved."`).
    - **uidDevice**: Unique device identifier (string).
    - **keyProcessLiveness** *(only for liveness)*: Unique identifier for the liveness process (string).
        
        
        - Returned **only** when `processType = "liveness"`.
    - **processId**: Unique process identifier (GUID/UUID) generated per execution to correlate SDK responses and webhook events.
    - **image**: Image object associated with the process.
        
        
        - **encoding**: Encoding type used for the image payload.
            
            
            - Typical value: `"base64"`
        - **mimeType**: MIME type of the image data.
            
            
            - Examples: `"image/jpeg"`, `"image/png"`
        - **data**: Base64-encoded image content (string).
            
            
            - Usually provided **without** the `data:image/...;base64,` prefix.

</div></div></div></div></div></div>**The component’s possible responses are split by functionality:** **CardCapture** (document capture) or **Liveness** (proof of life). Below is a practical, complete list of outcomes you should handle (success, pending, failures, cancellations, and technical errors).

</article></div>***Liveness***

<table id="bkmrk-status-%28code%29-nombre" style="width: 100%;"><thead><tr><th style="width: 10.7517%;">Status (code)</th><th style="width: 19.0381%;">Nombre (name)</th><th style="width: 18.9122%;">Descripción (description)</th><th style="width: 51.2979%;">Objeto (reason)</th></tr></thead><tbody><tr><td style="width: 10.7517%;">`NONE`</td><td style="width: 19.0381%;">`NOT_ALERT`</td><td style="width: 18.9122%;">The transaction was approved with no alerts detected.</td><td style="width: 51.2979%;">`{"code":"NONE","name":"NOT_ALERT","description":"The transaction was approved with no alerts detected."}`</td></tr><tr><td style="width: 10.7517%;">`NOT_ALIVE`</td><td style="width: 19.0381%;">`Not alive detected`</td><td style="width: 18.9122%;">The liveness check indicates the subject is not alive.</td><td style="width: 51.2979%;">`{"code":"NOT_ALIVE","name":"Not alive detected","description":"The liveness check indicates the subject is not alive."}`</td></tr><tr><td style="width: 10.7517%;">`CLOSED_EYES`</td><td style="width: 19.0381%;">`Eyes closed detected`</td><td style="width: 18.9122%;">The subject's eyes were detected as closed during the capture.</td><td style="width: 51.2979%;">`{"code":"CLOSED_EYES","name":"Eyes closed detected","description":"The subject's eyes were detected as closed during the capture."}`</td></tr><tr><td style="width: 10.7517%;">`SPOOFING`</td><td style="width: 19.0381%;">`Spoofing detected`</td><td style="width: 18.9122%;">A potential spoofing attempt was detected during the liveness process.</td><td style="width: 51.2979%;">`{"code":"SPOOFING","name":"Spoofing detected","description":"A potential spoofing attempt was detected during the liveness process."}`</td></tr><tr><td style="width: 10.7517%;">`PAD`</td><td style="width: 19.0381%;">`Presentation attack detected (PAD)`</td><td style="width: 18.9122%;">A potential presentation attack was detected (PAD confidence triggered).</td><td style="width: 51.2979%;">`{"code":"PAD","name":"Presentation attack detected (PAD)","description":"A potential presentation attack was detected (PAD confidence triggered)."}`</td></tr><tr><td style="width: 10.7517%;">`PERMISSION_DENIED`</td><td style="width: 19.0381%;">`Camera permission denied`</td><td style="width: 18.9122%;">Camera access was denied by the user or the operating system.</td><td style="width: 51.2979%;">`{"code":"PERMISSION_DENIED","name":"Camera permission denied","description":"Camera access was denied by the user or the operating system."}`</td></tr><tr><td style="width: 10.7517%;">`CAMERA_NOT_FOUND`</td><td style="width: 19.0381%;">`Camera not found`</td><td style="width: 18.9122%;">No camera was detected on the device, or it is unavailable.</td><td style="width: 51.2979%;">`{"code":"CAMERA_NOT_FOUND","name":"Camera not found","description":"No camera was detected on the device, or it is unavailable."}`</td></tr><tr><td style="width: 10.7517%;">`FACE_NOT_DETECTED`</td><td style="width: 19.0381%;">`Face not detected`</td><td style="width: 18.9122%;">No face was detected in the camera frame.</td><td style="width: 51.2979%;">`{"code":"FACE_NOT_DETECTED","name":"Face not detected","description":"No face was detected in the camera frame."}`</td></tr><tr><td style="width: 10.7517%;">`NETWORK_ERROR`</td><td style="width: 19.0381%;">`Network error`</td><td style="width: 18.9122%;">A network issue prevented the process from completing.</td><td style="width: 51.2979%;">`{"code":"NETWORK_ERROR","name":"Network error","description":"A network issue prevented the process from completing."}`</td></tr><tr><td style="width: 10.7517%;">`SDK_ERROR`</td><td style="width: 19.0381%;">`SDK error`</td><td style="width: 18.9122%;">An internal SDK error occurred during the process.</td><td style="width: 51.2979%;">`{"code":"SDK_ERROR","name":"SDK error","description":"An internal SDK error occurred during the process."}`</td></tr><tr><td style="width: 10.7517%;">`USER_CANCELED`</td><td style="width: 19.0381%;">`User canceled`</td><td style="width: 18.9122%;">The user canceled the process before completion.</td><td style="width: 51.2979%;">`{"code":"USER_CANCELED","name":"User canceled","description":"The user canceled the process before completion."}`</td></tr><tr><td style="width: 10.7517%;"> </td><td style="width: 19.0381%;"> </td><td style="width: 18.9122%;"> </td><td style="width: 51.2979%;">  
</td></tr></tbody></table>

***Example:***

*As an example response, the JSON below represents a **rejected transaction (Status 2)**.  
The **`reason`** field may come as an **object**, including the **rejection reason details** and its **description**.  
It also includes identifiers such as **`uidDevice`** and **`keyProcessLiveness`**, plus **`processId`** (the unique process UID).  
Evidence (e.g., an image) can be returned as **Base64**, including the **encoding type**.*

```
{
  "processType": "liveness",
  "statusCode": 2,
  "detail": {
    "status": "rejected",
    "reason": {
      "name": "SPOOFING",
      "description": "The liveness check indicates the subject is not alive."
    },
    "uidDevice": "1da62007d8974a9fa71e18cba76f6fc1",
    "keyProcessLiveness": "69c265aeca9d4863b61b1fc6a8099f52",
    "processId": "3f2b9c1e-7a4d-4f2a-9c0c-6c4c2e9b8d12",
    "image": {
      "encoding": "base64",
      "mimeType": "image/jpeg",
      "data": "<BASE64>"
    }
  }
}
```

***CardCapture***

<table id="bkmrk-status-%28code%29-nombre-1" style="width: 107.284%;"><thead><tr><th style="width: 12.1151%;">Status (code)</th><th style="width: 27.0691%;">Nombre (name)</th><th style="width: 23.4858%;">Descripción (description)</th><th style="width: 37.33%;">Objeto (reason)</th></tr></thead><tbody><tr><td style="width: 12.1151%;">`NONE`</td><td style="width: 27.0691%;">`NOT_ALERT`</td><td style="width: 23.4858%;">The transaction was approved with no alerts detected.</td><td style="width: 37.33%;">`{"code":"NONE","name":"NOT_ALERT","description":"The transaction was approved with no alerts detected."}`</td></tr><tr><td style="width: 12.1151%;">`PERMISSION_DENIED`</td><td style="width: 27.0691%;">`Camera permission denied`</td><td style="width: 23.4858%;">Camera access was denied by the user or the operating system.</td><td style="width: 37.33%;">`{"code":"PERMISSION_DENIED","name":"Camera permission denied","description":"Camera access was denied by the user or the operating system."}`</td></tr><tr><td style="width: 12.1151%;">`CAMERA_NOT_FOUND`</td><td style="width: 27.0691%;">`Camera not found`</td><td style="width: 23.4858%;">No camera was detected on the device, or it is unavailable.</td><td style="width: 37.33%;">`{"code":"CAMERA_NOT_FOUND","name":"Camera not found","description":"No camera was detected on the device, or it is unavailable."}`</td></tr><tr><td style="width: 12.1151%;">`CAMERA_IN_USE`</td><td style="width: 27.0691%;">`Camera in use`</td><td style="width: 23.4858%;">The camera is currently being used by another application.</td><td style="width: 37.33%;">`{"code":"CAMERA_IN_USE","name":"Camera in use","description":"The camera is currently being used by another application."}`</td></tr><tr><td style="width: 12.1151%;">`NOT_SUPPORTED`</td><td style="width: 27.0691%;">`Device not supported`</td><td style="width: 23.4858%;">The device does not meet the requirements for this capture process.</td><td style="width: 37.33%;">`{"code":"NOT_SUPPORTED","name":"Device not supported","description":"The device does not meet the requirements for this capture process."}`</td></tr><tr><td style="width: 12.1151%;">`DOCUMENT_NOT_DETECTED`</td><td style="width: 27.0691%;">`Document not detected`</td><td style="width: 23.4858%;">No document was detected in the camera frame.</td><td style="width: 37.33%;">`{"code":"DOCUMENT_NOT_DETECTED","name":"Document not detected","description":"No document was detected in the camera frame."}`</td></tr><tr><td style="width: 12.1151%;">`NETWORK_ERROR`</td><td style="width: 27.0691%;">`Network error`</td><td style="width: 23.4858%;">A network issue prevented the process from completing.</td><td style="width: 37.33%;">`{"code":"NETWORK_ERROR","name":"Network error","description":"A network issue prevented the process from completing."}`</td></tr><tr><td style="width: 12.1151%;">`SDK_ERROR`</td><td style="width: 27.0691%;">`SDK error`</td><td style="width: 23.4858%;">An internal SDK error occurred during the process.</td><td style="width: 37.33%;">`{"code":"SDK_ERROR","name":"SDK error","description":"An internal SDK error occurred during the process."}`</td></tr><tr><td style="width: 12.1151%;">`USER_CANCELED`</td><td style="width: 27.0691%;">`User canceled`</td><td style="width: 23.4858%;">The user canceled the process before completion.</td><td style="width: 37.33%;">`{"code":"USER_CANCELED","name":"User canceled","description":"The user canceled the process before completion."}`</td></tr><tr><td style="width: 12.1151%;">`FOCUS_LOST`</td><td style="width: 27.0691%;">`Focus lost / component interrupted`</td><td style="width: 23.4858%;">The process was interrupted because the app lost focus or the component was closed, minimized, or moved to the background.</td><td style="width: 37.33%;">`{"code":"FOCUS_LOST","name":"Focus lost / component interrupted","description":"The process was interrupted because the app lost focus or the component was closed, minimized, or moved to the background."}`</td></tr></tbody></table>

**Example**:

For the **document capture** process, it will be mapped under **`processType: "cardCapture"`** and will use **`statusCode: 3`**, which groups any **cancellation scenario** that affects the execution of the flow, for example:

- **Process cancelled by the user.**
- **Component focus loss during the session** (e.g., the app goes to the background or the user navigates to another screen).

The response will include the **`reason`** (cancellation reason) and **`status`** (state), as well as the **`processId`** (unique process identifier) and its **linked ID** (if applicable). Additionally, the **`imageDetail`** object will be returned, where the result of the processed image will be provided.

```
{
  "processType": "cardcapture",
  "side":"front",
  "statusCode": 3,
  "detail": {
    "status": "failed",
    "reason": {
      "name": "USER_CANCELED",
      "description": "The user canceled the process before completion."
    },
    "uidDevice": "1da62007d8974a9fa71e18cba76f6fc1",
    "processId": "3f2b9c1e-7a4d-4f2a-9c0c-6c4c2e9b8d12",
    "image": {
      "encoding": "base64",
      "mimeType": "image/jpeg",
      "data": "<BASE64>"
    }
  }
}
```

This process will trigger an **event to the webhook**, where a record will be **registered** and linked by a **UID** (for example, `processId` as the unique process identifier). The relationship between the **transaction** and the **webhook event** will be kept for traceability.

<p class="callout info">The payload sent will follow the structure below. This response **only applies to the webhook** when `reasonCode` is one of the following values: **`SPOOFING`**, **`PAD`**, **`CLOSED_EYES`**, **`NOT_ALIVE`**.</p>

```json
{
    "transactionId": "10743",
    "processId": "3f2b9c1e-7a4d-4f2a-9c0c-6c4c2e9b8d12",
    "transactionStatus": "rejected",
    "stages": [
        {
            "processType": "liveness",
            "status": “Spoofing”,
            "reason": {
                "name": "SPOOFING",
                "description": "A potential spoofing attempt was detected during the liveness process."
            },
            "uidDevice": "1da62007d8974a9fa71e18cba76f6fc1",
            "keyProcessLiveness": "69c265aeca9d4863b61b1fc6a8099f52",
            "processId": "3f2b9c1e-7a4d-4f2a-9c0c-6c4c2e9b8d12"
        }
    ]
}
```

[webhook-risk-validation.yaml](https://docs.ado-tech.com/attachments/1)