Multi-currency

On this page:

Introduction

NymCard is introducing a multi-currency feature: cards and accounts are created with multiple currency wallets under an account. Users just need to swipe the card and payments are seamlessly made on respective currency wallets.

Below you can find APIs, which are developed/enhanced to define the multi-currency related settings. Important: These APIs will be exposed on API catalog once the multi-currency changes are all implemented.

Prerequisite: The below have to be configured through the NymCard operations team to support multi-currency changes:

  1. Configure FX rate provider*

  2. Define custom rate group

  3. Link custom rate group with FX rate provider

*Fexco is a “Fexco Merchant Services Limited Company” that offers treasury as a service for FX rates. NymCard will integrate with Fexco to get different currency rates and then sell/buy on need basis.

Fexco will also manage all Foreign Exchange aspects as well as daily settlement with VISA on behalf of NymCard.

Note: Multi currency products are applicable only for VISA scheme cards.

Enhancements to existing APIs

Card Product APIs

Impacted APIs:

New parameters introduced in card products:

  • is_multi_currency_product (boolean true/false)

* A new field to identify whether a card product is Single Currency or Multi-Currency. Default value is false.

Note: Card product with multiple currencies in currency_settings is not allowed if is_multi_currency_product = false.

  • wallet_settings

To restrict the wallets, “wallet_settings” new object is introduced with the following fields. If is_multi_currency_product = true then becomes mandatory.

a) initial_num_of_wallets_offered: This field is to specify how many initial wallets are offered whenever a new card is issued. Users don’t have to opt-in for wallets as these will be readily available to utilize.

b) maximum_active_wallets_allowed: This field is to specify how many active wallets a user may have at a time. c) maximum_wallets_allowed_in_sweep: This field is to specify the maximum number of wallets to use in SWEEPING

  • fxrates_settings

This field is to link the custom rate group with card product against different transaction types. It has two child fields to specify transaction_type and custom rate_group_id.

  1. It is applicable if is_multi_currency_product = true.

  2. If not provided then the system auto links the default custom rate group with the card product.

  3. Multiple groups against the same transaction_type are not allowed.

  4. Transaction types are “TRANSFERS” and “SWEEP

  • Purpose of keeping separate TRANSFERS and SWEEP is to apply different currency rates. However it's on the future road map, for now rates are the same. So the same custom group should be for TRANSFERS and SWEEP.

  • if a cardholder converts one currency into another currency, in such cases TRANSFERS are applicable.

  • During authorization like PURCHASE or WITHDRAWAL, if funds are insufficient, then the system automatically pulls the funds from the currency wallets in order to make sufficient funds in the wallet on which the transaction is being posted. In such cases SWEEP is applicable.

Below you can find ‘Create card product’ sample request payload:

{

"is_multi_currency_product": true, 
"wallet_settings":
{
  "initial_num_of_wallets_offered": 3,
  "maximum_active_wallets_allowed": 3,
  "maximum_wallets_allowed_in_sweep": 1
},
  "fxrates_settings": [
    {
      "transaction_type": "TRANSFERS",
      "rate_group_id": "R1"
    },
    {
      "transaction_type": "SWEEP",
      "rate_group_id": "R2"
    }
  ]

Accounts APIs

Following changes are made in the ‘Create account’ API:

  • currencies

A new optional array field is introduced to specify wallet currencies in ‘Create account’ request.

Currencies must match with card product supported currencies.

If not provided then the system creates the account of currency as per card

product priority 1(base currency) currency only.

  • wallet_details

A new object is introduced in response payload of Accounts APIs. It has the

following child fields:

Currency

Represents the currency of the wallet.

Priority

Represents the priority of the wallet. Priority is used for sweeping purposes when due to insufficient funds, the system needs to automatically pull the funds from other wallets. So based on priority number, the system will pick the highest priority first.

Status

Represents the wallet status is ACTIVE or INACTIVE.

Below you can find ‘Create account’ sample request payload:

POST {{baseUrl}}/v1/accounts

{
  "user_id": "user001393",
  "card_product_id": "CP0032",
  "type": "PREPAID",
  "id": "prepaidmulti25",
  "currencies": [
      "USD", "AED", "CAD", "EUR"
  ]
}

Below you can find ‘Create account’ sample response payload:

{
    "id": "prepaidmulti25",
    "user_id": "user001393",
    "card_product_id": "CP0032",
    "type": "PREPAID",
    "balances": {
        "AED": 0.00,
        "EUR": 0.00,
        "USD": 0.00,
        "CAD": 0.00
    },
    "ledger_balances": {
        "AED": 0.00,
        "EUR": 0.00,
        "USD": 0.00,
        "CAD": 0.00
    },
    "status": "ACTIVE",
    "created": "2023-05-24T10:01:10.515Z",
    "modified": "2023-05-24T10:01:10.515Z",
    "default_account": false,
    "currencies": [
        "AED",
        "EUR",
        "USD",
        "CAD"
    ],
    "wallet_details": [
        {
            "currency": "USD",
            "priority": 1,
            "status": "ACTIVE"
        },
        {
            "currency": "AED",
            "priority": 2,
            "status": "ACTIVE"
        },
        {
            "currency": "CAD",
            "priority": 3,
            "status": "ACTIVE"
        },
        {
            "currency": "EUR",
            "priority": 4,
            "status": "ACTIVE"
        }
    ]

Fees APIs

Impacted APIs:

Linking different currencies of fee with card product

Previously, the system did not allow linking a fee plan with the card product if the currency of the fee does not match the priority 1 currency. Here comes the new implementation to unblock the restriction of currency mismatch. New fee types introduced:

1- PURCHASE_FOREIGN_CURRENCY

2- WITHDRAWAL_FOREIGN_CURRENCY

Above two fees are introduced. These fees are charged when a foreign currency transaction is received other than the supported wallets.

For example, there exists 3 wallets AED, USD, EUR under an account. A transaction like PURCHASE is received in OMR currency then the system will additionally charge this fee on top of typical PURCHASE fee if transaction currency matches with the currency of fee PURCHASE_FOREIGN_CURRENCY.

Note

The above fee can also be defined with currency ***. This definition will work as a default foreign currency fee if the dedicated currency fee is not defined.

For Example

There exists 3 wallets AED, USD, EUR under an account and fees PURCHASE_FOREIGN_CURRENCY in currency CAD and PURCHASE_FOREIGN_CURRENCY in currency *** is linked with the card product. A transaction like PURCHASE is received in OMR currency then the system will charge fee PURCHASE_FOREIGN_CURRENCY(with ***) on top of typical PURCHASE.

The currency of fee (PURCHASE_FOREIGN_CURRENCY and WITHDRAWAL_FOREIGN_CURRENCY ) should not match with the supported currencies on the card product while linking the fee with the card product.

Below you can find ‘Create fee’ sample request payload:

{
  "description": "PURCHASE FOREIGN CURRENCY FEE",
  "type": "FLAT",
  "currency": "AED",
  "transaction_type": "PURCHASE_FOREIGN_CURRENCY",
  "transaction_origin": "ANY"
}

Below you can find ‘Create fee’ sample response payload:

{
    "id": "b2c0a34d-da31-42c7-ace4-5058b295fab6",
    "description": "PURCHASE FOREIGN CURRENCY FEE",
    "active": true,
    "type": "FLAT",
    "currency": "AED",
    "amount": 3.00,
    "range": [],
    "transaction_type": "PURCHASE_FOREIGN_CURRENCY",
    "transaction_origin": "ANY",
    "created": "2023-05-24T10:19:56.139Z",
    "modified": "2023-05-24T10:19:56.139Z"
}

Balance Limits APIs

System now allows linking balance limits in different currencies at card product or account. There is a multi-currency card product with 2 currencies of AED (priority 1) and USD (priority 2).

The two balance limits can now be linked either to the card product or account level.

1- Balance limit of currency = AED exists and another balance limit of currency = USD exists and both can be linked with card product.

If a transaction is posted on the USD wallet, the system will check the linked Balance limit of USD currency. If the balance limit of the account remains within the related limit linked, then the transaction is successfully authorized. Otherwise, it is declined.

Similarly if a transaction is posted on AED wallet, the system will check the linked balance limit of AED currency. If the balance limit of the account remains within the related limit linked, then the transaction transaction is successfully authorized. Otherwise, it is declined.

Balance limit linking to card product:

Impacted APIs:

  • Get list of balance limits related to the card product

  • Link balance limits to the card product

  • Unlink balance limits from the card product

Balance limit linking to account:

Impacted APIs:

  • Link balance limit to account

  • Unlink balance limit from account

  • Get balance limits linked to account

  • Get account details

  • Get list of accounts

  • Change account status

Below you can find sample response for ‘Get account details’ API:

{
  "id": "d089a80f-e641-4045-8a80-54841e4a7458",
  "user_id": "gg5a80f-e641-4045-8a80-54841e4a55555",
  "card_product_id": "g189a80f-e641-4045-8a80-54841e4a1234",
  "type": "PREPAID",
  "balances": {
    "USD": 125.58,
    "EUR": 400.2
  },
  "ledger_balances": {
    "USD": 125.58,
    "EUR": 400.2
  },
  "status": "ACTIVE",
  "currencies": [
    "USD"
  ],
  "wallet_details": [
    {
      "currency": "USD",
      "priority": 0,
      "status": "ACTIVE"
    }
  ],
  "created": "2012-05-04T19:42:32.987Z",
  "modified": "2012-05-04T19:42:32.987Z"
}

Note:

A cumulative balance limit in a base currency is also maintained at tenant level. Whenever credit or debit is applied on account, an accumulative balance is calculated by the system and it is checked whether it violates the tenant level balance limit setting or not.

For configuration of accumulative balance limit at tenant level, please contact the NymCard operations team.

Velocity Limits APIs

The system now allows linking of velocity limits in different currencies.

Example: There is a multi-currency card product with 2 currencies of AED (priority 1) and USD (priority 2). Velocity limit of currency = AED exists. Velocity limit of currency = USD exists.

Now both velocity limits can be linked either at card product or card level.

If a transaction is posted on a USD wallet, the system will check the linked velocity limit of USD currency. If the transaction amount falls within the defined velocity limit, the transaction is successfully authorized. Otherwise, it is declined.

Similarly if a transaction is posted on AED wallet, the system will check the linked velocity limit of AED currency. If the transaction amount falls within the defined velocity limit, the transaction is successfully authorized. Otherwise, it is declined.

Velocity limit linking to card product

Impacted APIs:

  • Link velocity limits to the card product

  • Unlink velocity limits from the card product

  • Get list of velocity limits related to the card product

Velocity limit linking at card

Impacted APIs:

  • Set velocity limits for card

  • Remove velocity limits for card

  • Get velocity limits linked to card

Newly created APIs

A new API is developed to get the list of all FX rate providers:

GET v1/fxrates/providers

Below you find an example of response:

{
    "data": [
        {
            "provider_id": "FEXCOID",
            "provider_name": "FEXCO",
            "type": "EXTERNAL",
            "status": "ACTIVE",
            "rate_expiry_buffer_time": 5,
            "fxrate_mode": [
                {
                    "transaction_type": "TRANSFERS",
                    "mode": "ONLINE"
                },
                {
                    "transaction_type": "SWEEP",
                    "mode": "ONLINE"
                }
            ],
            "fxrate_provider_groups": [
                {
                    "provider_group_id": "4",
                    "status": "ACTIVE"
                }
            ],
            "created": "2023-05-24T10:48:28.283Z",
            "modified": "2023-05-24T10:48:28.283Z"
        },  
         ….

A new API is developed to get details of specific FX rate provider:

GET v1/fxrates/providers/{id}

Below you find an example of response:

{
    "provider_id": "FEXCOID",
    "provider_name": "FEXCO",
    "type": "EXTERNAL",
    "status": "ACTIVE",
    "rate_expiry_buffer_time": 5,
    "fxrate_mode": [
        {
            "transaction_type": "TRANSFERS",
            "mode": "ONLINE"
        },
        {
            "transaction_type": "SWEEP",
            "mode": "ONLINE"
        }
    ],
    "fxrate_provider_groups": [
        {
            "provider_group_id": "4",
            "status": "ACTIVE"
        }
    ],
    "created": "2023-05-24T10:48:28.283Z",
    "modified": "2023-05-24T10:48:28.283Z"
}

A new API is developed to get the list of custom rate groups:

GET {{baseUrl}}/v1/fxrates/groups Response:

{
    "data": [
        {
            "id": "customrategroup14",
            "providerId": "FEXCOID",
            "providerGroupId": "group4",
            "status": "ACTIVE",
            "isDefault": false,
            "created": "2023-05-24T11:00:32.230Z"
        }

A new API is developed to get details of specific FX rate group:

GET v1/fxrates/groups/{id}

Below you find an example of response:

{
"id": "R1",
"provider_id": "1",
"provider_group_id": "P1",
"status": "ACTIVE",
"is_default": "true",
"created": "2018-01-02T19:42:32.987Z",
"modified": "2012-05-04T19:42:32.987Z"
}

Update Account’ API

A new API is developed to have capability to manage the wallets; i.e. to add/remove wallets (applicable for products whereby "is_multi_currency_product" = true).

PUT v1/accounts/{id}

Request:

{
  "wallet_details": [
    {
      "currency": "USD",
      "priority": 3,
      "status": "INACTIVE"
    },
    {
      "currency": "SAR",
      "priority": 2,
      "status": "ACTIVE"
    }]
}

Definition: 1- “currency”: Mandatory field - For a multi-currency product this field shows which currency wallets are used in maintaining the funds. 2- “priority”: Mandatory field - For a multi-currency product this field gives the priority in which the currency wallets are used in funds sweeping. 3- “status”: Mandatory field - enums: "ACTIVE" / "INACTIVE

For a multi-currency product, if this field is set to 'INACTIVE' then the wallets of particular currency cannot be used in any transactions.

The system does not allow to change priority 1 currency status.

Few points to mention:

- Changing priority 1 currency status to INACTIVE is not allowed

- Changing the priority of priority 1 currency is not allowed

- Adding a new currency (as long as the total number of wallets does not exceed what is defined in "initial_num_of_wallets_offered": 4)

- Adding new wallets is allowed even if the user has reached the total number of ACTIVE wallets defined in "maximum_active_wallets_allowed" but the newly added wallet will be in INACTIVE status.

- Changing the status of any of the supported currencies to INACTIVE is allowed

- Changing the status of any of the supported currencies is to ACTIVE is allowed as long as the total number of ACTIVE wallets do not exceed what is defined as "maximum_active_wallets_allowed" at product level

- Changing the priority of any of the supported currencies is allowed

A new API is developed for users to convert the amount of a currency into another currency wallet. It's a two step process, initially to determine the exchange rate against different currency pairs, this API is used. This API will return the exchange rate so that users can review it and if rate is acceptable, then a second API ‘Book a quote’ will be used.

POST {{baseUrl}}/v1/fxrates:quote Request:

{
  "from_currency": "USD",
  "to_currency": "AED",
  "amount": 9,
  "account_id": "prepaidmulti23"
}

Response:

{
    "id": "eb2c02dd-3d02-463d-86f5-8923fe6f5371",
    "ts": "2023-05-24T11:30:58.556Z",
    "from_currency": "USD",
    "amount": 10,
    "to_currency": "AED",
    "to_amount": 36.70,
    "exchange_rate": 3.67,
    "status": "OFFERED",
    "expiry": "2023-06-04T11:46:12.937Z",
    "fxrate_provider_id": "FEXCOID",
    "fxrate_provider_name": "FEXCO-ID"
}

A new API is developed to book FX rate quote. This API is a second step for converting the amount of a currency into other currency. Upon receiving this API request, the system will shift the balance from the currency wallet into the other currency wallet. So debit is applied on from currency wallet and credit is applied on to currency wallet.

PUT {{baseUrl}}/v1/fxrates/%quote_id%:book

Response:

{
    "id": "c4f35a93-671f-466a-9829-4e30f20233cb",
    "ts": "2023-05-22T07:05:58.820Z",
    "from_currency": "AED",
    "amount": 8.00,
    "to_currency": "USD",
    "to_amount": 2.17,
    "exchange_rate": 0.27146,
    "status": "BOOKED",
    "transaction_id": "1ff20bd8-974f-440a-8825-e30763885499",
    "fxrate_provider_id": "53",
    "fxrate_provider_name": "FEXCO",
    "fee_amount": 0.00,
    "fee_details": [],
    "account_id": "MUHAYTESTING18MAY23_00",
    "booking_ts": "2023-05-22T07:06:53.703Z",
    "created": "2023-05-22T07:05:58.848Z",
    "modified": "2023-05-22T07:06:53.706Z"
}

This API is used to fetch the details of all existing quotes.

GET v1/fxrates/quotes

Below you find an example of response:

{ 
"after": "MjAxOC0wMS0wMlQxOTo0MjozMi45ODda", "has_more": true, 
"data": [ 
{ 
"id": "bc121529-e6e9-45f1-b820-8c46ce7f005a", "account_id": "bc121529-e6e9-45f1-b820-8c46ce7f0058", "ts": "2020-06-08T14:57:30.123456", 
"booking_ts": "2020-06-08T14:57:30.123456", 
"from_currency": "AED", 
"amount": 500, 
"to_currency": "USD", 
"to_amount": "136.15", 
"exchange_rate": "0.272294" 
"status": "BOOKED", 
"transaction_id": "12dr4", 
"fxrate_provider_id": "1", 
"fxrate_provider_name": "NymCard", 
"fee_amount": "1.5", 
"fee_detail": [ 
{ 
"fee_id": "173427", 
"description": "transaction fee", 
"amount": "1.5", 
"currency": "AED" 
} ], 
"created": "2023-02-06T10:54:02.956Z",
"modified":"2023-02-06T10:54:02.956Z" }] 
}

This API is used to fetch the details of an existing quote.

GET v1/fxrates/quotes/{id}

Below you find an example of response:

{ 
"id": "bc121529-e6e9-45f1-b820-8c46ce7f005a", "account_id": "bc121529-e6e9-45f1-b820-8c46ce7f0058", "ts": "2020-06-08T14:57:30.123456", 
"booking_ts": "2020-06-08T14:57:30.123456", "from_currency": "AED", 
"amount": 500, 
"to_currency": "USD", 
"to_amount": "136.15", 
"exchange_rate": "0.272294" 
"status": "BOOKED", 
"transaction_id": "12dr4", 
"fxrate_provider_id": "1", 
"fxrate_provider_name": "NymCard", 
"fee_amount": "1.5", 
"fee_detail": [ 
{ 
"fee_id": "173427", 
"description": "transaction fee", 
"amount": "1.5", 
"currency": "AED" 
} ], 
"created": "2023-02-06T10:54:02.956Z", 
"modified": "2023-02-06T10:54:02.956Z" 
}

Authorization

Scheme based transactions - Authorization with Sweeping

When an account wallet has insufficient funds then the system needs to pull the funds from another currency wallet of the same account so that sufficient funds are available in order to authorize the transaction.

Example:

A multi-currency card product exists with "maximum_wallets_allowed_in_sweep": 1

An account exists under the multi-currency card product:

[AED, P1, ACTIVE, 40]

[USD, P2, ACTIVE, 30]

[EUR, P3, ACTIVE, 20]

1- A transaction is received of amount = 50 AED

2- There are insufficient funds in AED. The system needs 10 more AEDs to process the transaction

3- The system checks card product field wallet_settings.maximum_wallets_allowed_in_sweep and its value is 1, so the system will use other wallets (as per configuration) to pull the funds and convert into AED and credit it into AED wallet. Here exchange rate USD to AED will be used of type SWEEP.

4- So debit of 2.27 on USD wallet and credit of 10 AED on AED wallet are applied (as per exchange rate) during authorization and transaction is approved. 5- If there are insufficient funds in the USD wallet and given that maximum_wallets_allowed_in_sweep defined in the card product is 1, then the system will not pull funds from the second wallet and will decline the transaction.

Reflecting Sweep Details to users in Webhook and Transaction APIs “Sweep_details” is reflected in the “TRANSACTION” webhook. Also, it is reflected in the response of the below APIs: - Get transaction details API - Search for transactions API

 "sweep_details": [
        {
            "debit_from_currency": "EUR",
            "debit_from_amount": 2.55,
            "credit_to_currency": "AED",
            "credit_to_amount": 10.00,
            "exchange_rate": 3.91552
        }
    ]

Clearing and Reversal

In case of CLEARING, the system will NOT do SWEEPING to pull the funds from the other wallets. If there is insufficient funds then the account goes into overdraft (business as usual). There is also NO SWEEPING in reversals (whether partial or full reversal).

Last updated