> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/nfc-wallet-sdk-android/implement-nfc-wallet/enroll-wallet.md).

# Enroll wallet

## Overview

Enroll the digital wallet application after **NFC Wallet SDK** initialization and before you start **Tokenization**.

Wallet enrollment provisions the digital wallet application with the security assets required to use **NFC Wallet** services:

* Run this once per wallet instance.
* Run this only if the digital wallet application uses **NFC Wallet** services.
* Run this only on eligible devices.

{% hint style="warning" %}
Enroll only digital wallet applications that use **NFC Wallet** services.

This avoids unnecessary network traffic from the digital wallet application and unnecessary load on **NFC Wallet**.
{% endhint %}

## Sequence diagram

High-level flow to enroll your wallet application.

<figure><img src="/files/YVC4N2vRqMvRjR5xBmzm" alt=""><figcaption><p>Wallet enrollment high-level flow.</p></figcaption></figure>

{% hint style="info" %}
This flow is technically called **wallet secure enrollment** in **NFC Wallet**.
{% endhint %}

## SDK Integration

### Prerequisites

Before you start, verify the following:

* Your digital wallet application is onboarded in the NFC Wallet backend.
* You initialized the **NFC Wallet SDK**.
* The wallet is not enrolled (see below).

### Perform wallet enrollment

Wallet enrollment is a one-time action in the digital wallet application lifecycle.

Run it after SDK initialization, and only if the wallet is not enrolled.

1. Get a `WalletSecureEnrollmentBusinessService` instance.
2. Check `getState()` returns `WSE_REQUIRED`.
3. If needed, call `startWalletSecureEnrollment()` to start wallet enrollment.
4. Implement `WalletSecureEnrollmentListener` to track progress.

These are the possible callbacks:

* `onProgressUpdate` with state `WSE_STARTED`: The process starts.
* `onProgressUpdate` with state `WSE_COMPLETED`: The process completes successfully.
* `onError`: The process fails with an error.

After wallet enrollment completes successfully, continue with [Tokenize a card](/nfc-wallet-sdk-android/implement-nfc-wallet/tokenize-a-card.md).

```java
public void performWseIfNeeded() {
    // First check current status. Whether we need WSE at all.
    final WalletSecureEnrollmentBusinessService wseService 
                = ProvisioningServiceManager.getWalletSecureEnrollmentBusinessService();
    final WalletSecureEnrollmentState state = wseService.getState();

    switch (state) {
        case WSE_COMPLETED:
        case WSE_NOT_REQUIRED:
            // WSE was already done in current or some previous instance.
            break;
        case WSE_STARTED:
            // WSE was triggered during this instance. Simple wait for the first one to finish.
            return;
        case WSE_REQUIRED:
            // Trigger WS enrollment.
            wseService.startWalletSecureEnrollment(new WalletSecureEnrollmentListener() {
                @Override
                public void onProgressUpdate(final WalletSecureEnrollmentState wseState) {
                    if (wseState == WalletSecureEnrollmentState.WSE_COMPLETED) {
                        // Success
                    }
                    else if (wseState == WalletSecureEnrollmentState.WSE_STARTED) {
                        // Started
                    }
                }

                @Override
                public void onError(final WalletSecureEnrollmentError wbDynamicKeyRenewalServiceError) {
                    // Log error
                }
            });
            break;
        default:
            // Log error as it should not happen
            break;
    }
}   
```

### Error code details

When `WalletSecureEnrollmentListener.onError(...)` is triggered, the SDK provides a `WalletSecureEnrollmentError`.

It includes an error code and a message, plus additional fields depending on the failure type.

#### Parse `WalletSecureEnrollmentError`

The structure of the `WalletSecureEnrollmentError` object is as follows:

* SDK error code: The error type for this operation.
* CPS error code: The numeric error code returned by the CPS module (server-side).
* HTTP status code: The HTTP status code returned for communication errors.
* Message: A human-readable error description.

The error needs to be parsed as follows:

1. Read `getSdkErrorCode()` to get a `WalletSecureEnrollmentErrorCodes` value.
2. If the SDK error code indicates a communication error (`COMM_ERROR`), read `getHttpStatusCode()`.
3. If the SDK error code indicates a server-side error (`SERVER_ERROR`), read `getCpsErrorCode()`.
4. Read `getErrorMessage()` for log-friendly description.
5. If the SDK error code is `DEVICE_SUSPICIOUS`, read `getStatusAdditionalInfo()` and log it for troubleshooting.

Refer to `WalletSecureEnrollmentErrorCodes` in the [Android API](/nfc-wallet-sdk-android/android-api.md) reference for the full list of codes.

#### `WalletSecureEnrollmentErrorCodes`

Use the following recommendations to decide whether to retry, stop, or reset the SDK.

{% hint style="info" %}
Call `SDKDataController.wipeAll()` when the recommendation is to reset the SDK.
{% endhint %}

<details>

<summary>Error code tables</summary>

<table data-full-width="true"><thead><tr><th width="240">Error code</th><th>When it happens</th><th>Recommended action</th></tr></thead><tbody><tr><td><code>WSE_INTERNAL_ERROR</code></td><td>An internal SDK error occurs.</td><td><p>Retry wallet enrollment.</p><p>If the issue persists, reset the SDK.</p></td></tr><tr><td><code>COMMON_NO_INTERNET</code></td><td>The device has no network connectivity.</td><td>Ask the end user to connect to a network, then retry wallet enrollment.</td></tr><tr><td><code>COMMON_COMM_ERROR</code></td><td>A communication error occurs while retrieving security assets.</td><td>Retry wallet enrollment.</td></tr><tr><td><code>COMMON_SERVER_ERROR</code></td><td>A server-side error occurs while retrieving security assets.</td><td><p>Retry wallet enrollment.</p><p>If the issue persists, contact the Thales delivery team to validate the environment setup.</p></td></tr><tr><td><code>RE_ENROLLMENT_REQUIRED</code></td><td>Re-enrollment is required for security reasons.</td><td>Reset the SDK, then run wallet enrollment again.</td></tr><tr><td><code>WSE_STORAGE_ACCESS_ERROR</code></td><td>The SDK exceeds its internal retry limit when accessing secure storage.</td><td>Reset the SDK, then retry wallet enrollment.</td></tr><tr><td><code>JSON_PARSING_ERROR</code></td><td>The response data cannot be parsed.</td><td><p>Retry wallet enrollment.</p><p>If the issue persists, reset the SDK.</p></td></tr><tr><td><code>WSE_REQUEST_ERROR</code></td><td>The enrollment request fails.</td><td>Retry wallet enrollment.</td></tr><tr><td><code>WSE_DOWNLOAD_ERROR</code></td><td>The security asset download fails.</td><td>Verify network connectivity, then retry wallet enrollment.</td></tr><tr><td><code>WSE_ERROR_INIT_SESSION</code></td><td>WSE session initialization fails (typically authentication-related).</td><td>Retry wallet enrollment.</td></tr><tr><td><code>WSE_ERROR_COMPUTE_AUTH_VALUE_FAILED_PACKAGE_NOT_FOUND</code></td><td>The SDK cannot compute the authentication value because the package name cannot be resolved.</td><td>Verify the application package name used in your onboarding configuration, then retry wallet enrollment.</td></tr><tr><td><code>WSE_ERROR_COMPUTE_AUTH_VALUE_FAILED_CERT_EXCEPTION</code></td><td>The SDK cannot compute the authentication value due to an application signing or public key issue.</td><td>Verify the application signing certificate used in your onboarding configuration, then retry wallet enrollment.</td></tr><tr><td><code>WSE_CPS_COMPONENT_NOT_INITIALIZED</code></td><td>Wallet enrollment starts before the CPS component is initialized.</td><td>Initialize the SDK, then retry wallet enrollment.</td></tr><tr><td><code>WSE_MG_COMPONENT_NOT_INITIALIZED</code></td><td>Wallet enrollment starts before the MobileGateway component is initialized.</td><td>Initialize the SDK, then retry wallet enrollment.</td></tr><tr><td><code>DEVICE_SUSPICIOUS</code></td><td>The SDK detects a device security threat.</td><td><p>Stop the flow and inform the end user that the device cannot be used.</p><p>Capture and share <code>getStatusAdditionalInfo()</code> when contacting Thales support.</p></td></tr><tr><td><code>WSE_KCV_ERROR</code></td><td>The SDK fails to validate downloaded security assets (KCV check fails).</td><td>Retry wallet enrollment.</td></tr></tbody></table>

</details>

## Application binding key (notes)

As described in [onboarding](/nfc-wallet-sdk-android/get-started/configuration/2.-onboarding.md) you must provide the **application binding key.**

If the application binding key is not provided or incorrect, enroll wallet will failed.

Please check warning and note below.

{% hint style="warning" %}

## Signing key rotation / Multiple signers <a href="#receive-this-from-the-thales-delivery-team" id="receive-this-from-the-thales-delivery-team"></a>

If the oldest signing key is not provided as the first signer value in the proof-of-rotation struct, then enroll wallet will fail
{% endhint %}

{% hint style="info" %}

#### Downgrading to earlier versions of NFC Wallet SDK <a href="#downgrading-to-earlier-versions-of-nfc-wallet-sdk" id="downgrading-to-earlier-versions-of-nfc-wallet-sdk"></a>

To downgrade to an earlier version of NFC Wallet SDK, the application has to ensure that the oldest signing key is provided as the first signer in the proof-of-rotation struct.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.payments.thalescloud.io/nfc-wallet-sdk-android/implement-nfc-wallet/enroll-wallet.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
