> 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/transaction-control/implement-transaction-control/implement-domain-controls/manage-in-app-card-controls.md).

# Manage in-app card controls

Let end users view and update domain controls from the **issuer application** using the **D1 SDK**.

## Sequence Diagram

Use the D1 SDK to retrieve current settings, render your UI, then submit updates.

**Pre-requisites**

* Consumer and card already created/registered in D1.
* SDK is properly initialised.
* Issuer App called D1 SDK login API.
* Before calling of updateCardControlSettings or updateCardLimitSettings API, please call getCardSettings API first.

<figure><img src="/files/JgMMCfpymyn30YsTyou1" alt=""><figcaption></figcaption></figure>

## D1 SDK Integration

D1 SDK uses these public APIs for cards managed in D1:

* `CardService.getCardSettings()`: To retrieve the card settings.
* `CardService.updateCardControlSettings()`: To update the card control settings.

### Retrieve current settings

`CardService.getCardSettings()` returns two groups of settings:

* Card control settings (domain controls)
* Card limit setting (spending limits) refer to the [API documentation](https://thalesgroup.github.io/d1sdk-docs/d1-sdk/latest/android/index.html) for the detailed field-level information on card control and card limit settings.

See the [D1 SDK API reference](https://thalesgroup.github.io/d1sdk-docs/d1-sdk/latest/android/index.html) for field-level details.

If you also implement spending limits, see [Implement Spending Limits](/transaction-control/implement-transaction-control/implement-spending-limits-controls.md).

{% tabs %}
{% tab title="Android" %}

```java
//get card settings
String cardID = ""; //cardID received from the backend.
final CardSettings[] cardSettingsCached = new CardSettings[0];

CardService cardService = d1Task.getCardService();
D1Task.Callback<CardSettings> callback = new D1Task.Callback<CardSettings>() {
    @Override
    public void onSuccess(CardSettings cardSettings) {
        // cache the settings in the app
        cardSettingsCached[0] = cardSettings;
    }

    @Override
    public void onError(D1Exception exception) {
        // Refer to D1 SDK Integration – Error Management section.
    }
};
cardService.getCardSettings(cardID, callback);
```

{% endtab %}

{% tab title="iOS" %}

```swift
let cardID = "" // obtained e.g. from server
let cardService = d1Task.cardService()
cardService.cardSettings(cardID) { [weak self] cardSettings, error in
    if let error = error {
       // Handle error
    } else if let cardSettings = cardSettings {
        cardSettingsCached = cardSettings
        // Proceed with subsequent flows e.g. display card control/limit settings UI
    }
}
```

{% endtab %}
{% endtabs %}

### Render card control settings in your UI

Read card controls from the `CardSettings` object, then render only the controls that exist.

Some controls are optional at Card Product level. D1 returns them as `null`. Hide those controls.

{% tabs %}
{% tab title="Android" %}

```java
//get card settings
String cardID = ""; //cardID received from the backend.
final static CardSettings cardSettingsCached;// Card settings from cached or retrieve from `Cardservice.getCardSettings()` API
CardControlSettings cardControlSettings = cardSettingsCached.getControl();    
        

//
// ==== Payment status section =====
//
// Enable/disable online payment status
Switch onlinePaymentSwitch;
onlinePaymentSwitch.setChecked(cardControlSettings.isOnlinePaymentEnabled());

// Enable/disable abroad payment status
Switch abroadPaymentSwitch;
abroadPaymentSwitch.setChecked(cardControlSettings.isAbroadPaymentEnabled());

// Enable/disable contactless payment status.
if(cardControlSettings.isContactlessEnabled() != null) {
    // Note: Only display this setting if isContactlessEnabled attribute is available in `CardService.getCardSettings()` API response.
    Switch contactlessSwitch;
    contactlessSwitch.setChecked(cardControlSettings.isContactlessEnabled());
}

// Enable/disable magneticStripe payment status
if(cardControlSettings.isMagneticStripeEnabled() != null) {
    // Note: Only display this setting if isMagneticStripeEnabled attribute is available in `CardService.getCardSettings()` API response.
    Switch magneticStripeSwitch;
    magneticStripeSwitch.setChecked(cardControlSettings.isMagneticStripeEnabled());
}

// Enable/disable ATM withdrawal status
if(cardControlSettings.isATMWithdrawalEnabled() != null) {
    // Note: Only display this setting if isATMWithdrawalEnabled attribute is available in `CardService.getCardSettings()` API response.
    Switch atmWithdrawalSwitch;
    atmWithdrawalSwitch.setChecked(cardControlSettings.isATMWithdrawalEnabled());
}

//
// ==== Denied currency list section =====
//
// Display denied currency list section
List<String> deniedCurrencies = cardControlSettings.getDeniedCurrencyList();
RecyclerView deniedCurrencyListRecyclerview;
DeniedCurrencyListAdapter deniedCurrencyAdapter = new DeniedCurrencyListAdapter(deniedCurrencies);
deniedCurrencyListRecyclerview.setAdapter(deniedCurrencyAdapter);


//
// ==== Geography section =====
//
// Display geography settings section
CardControlSettings.Geography geography = cardControlSettings.getGeography();
List<CardControlSettings.Region> regionList = geography.getRegionList();
RecyclerView regionListRecyclerview;
RegionListAdapter regionAdapter = new RegionListAdapter(regionList);
regionListRecyclerview.setAdapter(regionAdapter);


List<String> countryList = geography.getCountryList();
RecyclerView countryListRecyclerview;
CountryListAdapter countryAdapter = new CountryListAdapter(countryList);
countryListRecyclerview.setAdapter(countryAdapter);

//
// ==== Merchant section =====
//
// Display merchant section
CardControlSettings.Merchant merchant = cardControlSettings.getMerchant();
// Enable/disable payment on gambling merchant
Switch gamblingMerchantSwitch;
gamblingMerchantSwitch.setChecked(merchant.isGamblingMerchantEnabled());

// Enable/disable payment on adult merchant
Switch adultMerchantSwitch;
adultMerchantSwitch.setChecked(merchant.isAdultMerchantEnabled());

// Enable/disable payment on risky merchant
Switch riskyMerchantSwitch;
riskyMerchantSwitch.setChecked(merchant.isRiskyMerchantEnabled());
```

{% endtab %}

{% tab title="iOS" %}

```swift
// Examples of UI display
let onlinePaymentSwitch = UISwitch()
let contactlessSwitch = UISwitch()
let magneticStripeSwitch = UISwitch()
let atmWithdrawalSwitch = UISwitch()
let abroadPaymenSwitch = UISwitch()
let deniedCurrencyListTextView = UITextView()
let countryListTextView = UITextView()
let regionListTextView = UITextView()
let gamblingMerchantSwitch = UISwitch()
let adultMerchantSwitch = UISwitch()
let riskyMerchantSwitch = UISwitch()

let cardControlSettings = cardSettingsCached.control

//
// ===== Payment status section =====
//

// Enable/disable online payment
onlinePaymentSwitch.isOn = cardControlSettings.isOnlinePaymentEnabled

// Enable/disable contactless payment
if let isContactlessEnabled = cardControlSettings.isContactlessEnabled {
    contactlessSwitch.isOn = isContactlessEnabled
} else {
    // Note: Only display the settings if the value is not nil
    contactlessSwitch.isHidden = true
}

// Enable/disable magneticStripe
if let isMagneticStripeEnabled = cardControlSettings.isMagneticStripeEnabled {
    magneticStripeSwitch.isOn = isMagneticStripeEnabled
} else {
    // Note: Only display the settings if the value is not nil
    magneticStripeSwitch.isHidden = true
}

// Enable/disable ATM withdrawal
if let isATMWithdrawalEnabled = cardControlSettings.isATMWithdrawalEnabled {
    atmWithdrawalSwitch.isOn = isATMWithdrawalEnabled
} else {
    // Note: Only display the settings if the value is not nil
    atmWithdrawalSwitch.isHidden = true
}

// Enable/disable abroad payment status
abroadPaymenSwitch.isOn = cardControlSettings.isAbroadPaymentEnabled

//
// ===== Denied currency list section =====
//

// Display denied currency list section, e.g. in UITextView or UITableView
for currency in cardControlSettings.deniedCurrencyList {
    deniedCurrencyListTextView.text = "\(deniedCurrencyListTextView.text)\n\(currency)"
}

//
// ===== Geography section =====
//

// Display geography settings section, e.g. in UITextView or UITableView
for country in cardControlSettings.geography.countryList {
    countryListTextView.text = "\(countryListTextView.text)\n\(country)"
}
for region in cardControlSettings.geography.regionList {
    regionListTextView.text = "\(countryListTextView.text)\n\(region)"
}

//
// ===== Merchant section =====
//

// Display merchant section
// Enable/disable payment on gambling merchant
gamblingMerchantSwitch.isOn = cardControlSettings.merchant.isGamblingMerchantEnabled
// Enable/disable payment on adult merchant
adultMerchantSwitch.isOn = cardControlSettings.merchant.isAdultMerchantEnabled
// Enable/disable payment on risky merchant
riskyMerchantSwitch.isOn = cardControlSettings.merchant.isRiskyMerchantEnabled
```

{% endtab %}
{% endtabs %}

### Update card control settings

{% hint style="warning" %}
Treat card control updates as a sensitive operation.

* Perform additional authentication before modifying card settings.
* Always start from a `CardSettings` object returned by `CardService.getCardSettings()`.
* Never create a `CardSettings` object yourself.

If you send a self-initialized object to `CardService.updateCardControlSettings()`, you can overwrite existing values on the **D1 backend**. You can also trigger errors like `ERROR_CARD_SETTINGS_OPERATION_NOT_ALLOWED`, `ERROR_CARD_SETTINGS_INVALID_FORMAT`, or `ERROR_CARD_SETTINGS_INVALID_VALUE`.
{% endhint %}

#### Prerequisites and allowed updates

Before you update a control, verify that D1 returned the corresponding attribute in `getCardSettings()`.

D1 SDK returns `ERROR_CARD_SETTINGS_OPERATION_NOT_ALLOWED` when the end user updates a control that is not available.

The following table shows the prerequisite for the respective control settings:

| Card Control Setting                                            | Prerequisite                                                                                                                               |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `CardControlSettings.setOnlinePaymentEnabled(true)`             | N/A                                                                                                                                        |
| `CardControlSettings.setAbroadPaymentEnabled(true)`             | N/A                                                                                                                                        |
| `CardControlSettings.setDeniedCurrencyList()`                   | N/A                                                                                                                                        |
| `CardControlSettings.Merchant.setGamblingMerchantEnabled(true)` | N/A                                                                                                                                        |
| `CardControlSettings.Merchant.setAdultMerchantEnabled(true)`    | N/A                                                                                                                                        |
| `CardControlSettings.Merchant.setRiskyMerchantEnabled(true)`    | N/A                                                                                                                                        |
| `CardControlSettings.setContactlessEnabled(true)`               | If the `isContactlessEnabled` attribute is retrieved from the `CardService.getCardSettings()` API, then an update operation is allowed.    |
| `CardControlSettings.setMagneticStripeEnabled(true)`            | If the `isMagneticStripeEnabled` attribute is retrieved from the `CardService.getCardSettings()` API, then an update operation is allowed. |
| `CardControlSettings.setATMWithdrawalEnabled(true)`             | If the `isATMWithdrawalEnabled` attribute is retrieved from the `CardService.getCardSettings()` API, then an update operation is allowed.  |

#### Input validation and errors

D1 SDK can return:

* The `ERROR_CARD_SETTINGS_INVALID_FORMAT` error code to the issuer application when the end user tries to update the card control setting with an invalid formatted input.
* The `ERROR_CARD_SETTINGS_INVALID_VALUE` error code when the end user tries to update card control settings where the format is correct but the input value is incorrect.

Use the following formats for list-based controls:

| Card Control Setting                                  | Format                                                                                                                                                                                                                                                                                                                                                |
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CardControlSettings.getGeography().setCountryList()` | Refer to [ISO 3166-1 alpha-2 format](https://www.iban.com/country-codes) for the country code formats allowed. If the format is invalid, D1 SDK will propagate the error to the issuer application. Refer to the [Android Country API](https://developer.android.com/reference/java/util/Locale#getCountry\(\)) to prevent such error from happening. |
| `CardControlSettings.setDeniedCurrencyList()`         | Refer to [ISO 4217 alpha code format](https://www.iban.com/currency-codes) for allowed currencies code formats. If the format is invalid, D1 SDK will propagate the error to the issuer application. Refer to [Android Currency API](https://developer.android.com/reference/android/icu/util/Currency) to prevent such error from happening.         |

Use the following examples to submit updates:

{% tabs %}
{% tab title="Android" %}

```java
String cardID = ""; //cardID received from the backend.

CardService cardService = d1Task.getCardService();
CardSettings cardSettings = null; // Get Card settings from API or use from cache

CardControlSettings cardControlSettings = cardSettings.getControl();

// Enable/disable online payment status
cardControlSettings.setOnlinePaymentEnabled(true); // or false

// Enable/disable contactless payment status
// if isContactlessEnabled attribute retrieved from `CardService.getCardSettings()` API then below operation is allowed       
if (cardControlSettings.isContactlessEnabled() != null) {
    cardControlSettings.setContactlessEnabled(true); // or false
}

// Enable/disable magneticStripe payment status
// if isMagneticStripeEnabled attribute retrieved from `CardService.getCardSettings()` API then below operation is allowed        
if (cardControlSettings.isMagneticStripeEnabled() != null) {
    cardControlSettings.setMagneticStripeEnabled(true); // or false
}

// Enable/disable atm withdrawal status
// if isATMWithdrawalEnabled attribute retrieved from `CardService.getCardSettings()` API then below operation is allowed        
if (cardControlSettings.isATMWithdrawalEnabled() != null) {
    cardControlSettings.setATMWithdrawalEnabled(true); // or false
}

// Enable/disable abroad payment status
cardControlSettings.setAbroadPaymentEnabled(true);     // or false

// Update denied currency list
ArrayList<String> deniedCurrencies = new ArrayList<>();

// Please refer Android Currency API [Android Currency API](https://developer.android.com/reference/android/icu/util/Currency)
// for example:         
// Currency currency = Currency.getInstance(Locale.CANADA);
// String currencyCode = currency. getCurrencyCode(); 
        
deniedCurrencies.add("USD");
deniedCurrencies.add("GBP");
cardControlSettings.setDeniedCurrencyList(deniedCurrencies);

// Geography settings
CardControlSettings.Geography geography = cardControlSettings.getGeography();
// Update region list
ArrayList<CardControlSettings.Region> regionList = new ArrayList<>();
regionList.add(CardControlSettings.Region.ASIA);
regionList.add(CardControlSettings.Region.SCHENGEN_AREA);
geography.setRegionList(regionList);

// Update country list
ArrayList<String> countryList = new ArrayList<>();
// Please refer Android Country API [Android Country API](https://developer.android.com/reference/java/util/Locale#getCountry())
// Also can refer below example:
// String[] countries = Locale.getISOCountries();        
countryList.add("SG");
countryList.add("FR");
geography.setCountryList(countryList);

// Merchant settings
CardControlSettings.Merchant merchant = cardControlSettings.getMerchant();
// Enable/disable payment on gambling merchant
merchant.setGamblingMerchantEnabled(true);          // or false
// Enable/disable payment on adult merchant
merchant.setAdultMerchantEnabled(true);             // or false
// Enable/disable payment on risky merchant
merchant.setRiskyMerchantEnabled(true);             // or false

cardService.updateCardControlSettings(cardID, cardControlSettings, new D1Task.Callback<Void>() {
    @Override
    public void onSuccess(Void data) {
            // Proceed with the subsequent flows, for example, update UI.
    }
    @Override
    public void onError(@NonNull D1Exception exception) {
            // Refer to D1 SDK Integration – Error Management section.
    }
});
```

{% endtab %}

{% tab title="iOS" %}

```swift
// e.g. update encountered error
let cardService = d1Task.cardService()
let cardID = "" // obtained e.g. from server
cardService.updateCardControlSettings(cardID, settings: cardControlSettings) { error in
    if let error = error {
        // Restore the settings to initial state before update
        cardControlSettings.restore()
    } else {
        // Proceed with subsequent flows e.g. update UI
    }
}
```

{% endtab %}
{% endtabs %}

### Next steps

* If you use geography by region, see [Supported Regions](/transaction-control/implement-transaction-control/implement-domain-controls/supported-regions.md).
* If you need the default MCC groups, see [Default Merchant type](/transaction-control/implement-transaction-control/implement-domain-controls/default-merchant-types.md).


---

# 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/transaction-control/implement-transaction-control/implement-domain-controls/manage-in-app-card-controls.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.
