Foreign Currency Exchange

Overview

The Foreign Exchange module provides the infrastructure to carry out currency exchanges on behalf of customers —a particularly important feature for platforms that accommodate multiple currencies. This module includes a series of endpoints tailored to the needs of users looking to perform, monitor, and manage asset exchanges for their customers.

Offering functions from quoting to execution, along with detailed tracking mechanisms, the Foreign Exchange module endpoints include:

  1. Get Available Currency Pairs: Provides a full list of currency pairs available for exchange.

  2. Get Account Details: This endpoint will return available source and destination accounts the customer can choose to do the exchange.

  3. Get Quote for Exchange: Provides an estimate for an exchange, detailing the source and destination amount before the actual exchange is executed, ensuring that the customer is informed about the potential transaction.

  4. Execute Exchange: Execute the quote exchange using the id received from the quote for exchange.

Overall, the Exchange module is designed to offer a seamless and secure experience for handling the exchange requirements of customers, ensuring that users can manage these operations effectively with great precision and control.


Get Available Currency Pairs

Provides a full list of asset pairs enabled for the API user. The response will also include information on limits and minimums associated with each asset pair for exchanges.

  • Endpoint: /api/v1/customer/foreign-exchanges/pairs

  • Method: GET

Get available asset pairs for foreign exchange

Request query:

  • PageNumber: list page number (optional, default = 1)
  • PageSize: list page size (optional, default = 10)

Response:

  • array of
    • AssetPair: Asset pair code
GET/api/v1/customer/foreign-exchanges/pairs
Query parameters
Response

OK

Body
statusnullable string
errorsnullable array of AvamaeTemplate.Core.Types.Results.Base.ErrorResultDto (object)
idinteger (int64)
detailsnullable array of AvamaeTemplate.Core.Types.Dtos.CustomerRole.ForeignExchangesModule.ForeignExchangePairDto (object)
pageSizenullable integer (int32)
pageNumbernullable integer (int32)
numberOfPagesnullable integer (int32)
Request
const response = await fetch('/api/v1/customer/foreign-exchanges/pairs', {
    method: 'GET',
    headers: {},
});
const data = await response.json();
Response
{
  "status": "text",
  "errors": [
    {
      "errorType": "text",
      "fieldName": "text",
      "messageCode": "text"
    }
  ],
  "details": [
    {
      "baseAsset": "text",
      "exchangeAsset": "text"
    }
  ]
}

Success Response Example:

{
    "id": 14107,
    "details": [
        {
            "baseAsset": "CNH",
            "exchangeAsset": "SGD"
        },        
        {
            "baseAsset": "EUR",
            "exchangeAsset": "CHF"
        },
        {
            "baseAsset": "GBP",
            "exchangeAsset": "SGD"
        },
        {
            "baseAsset": "USD",
            "exchangeAsset": "SGD"
        }
    ],
    "pageSize": 100,
    "pageNumber": 1,
    "numberOfPages": 1,
    "status": "1",
    "errors": []
}

Get Account Details

Provides list of source and destination accounts based on the source and destination currency provided for the customer.

  • Endpoint: /api/v1/customer/foreign-exchanges/account-details

  • Method: GET

Get source and destination account details for foreign exchange

Request query:

  • CustomerId: non mandatory customerid, if not provided the main customers account details will be returned
  • SourceCurrency: Currency code of the currency to be spent in the exchange.
  • DestinationCurrency: Currency code of the currency to be obtained in the exchange.
  • AssetExchangeType : either Sell or Buy

Response:

  • array of
    • AssetPair: Asset pair code
GET/api/v1/customer/foreign-exchanges/account-details
Query parameters
Response

OK

Body
statusnullable string
errorsnullable array of AvamaeTemplate.Core.Types.Results.Base.ErrorResultDto (object)
idinteger (int64)
detailsAvamaeTemplate.Core.Types.Dtos.CustomerRole.ForeignExchangesModule.GetFXDetailsResultDto (object)
Request
const response = await fetch('/api/v1/customer/foreign-exchanges/account-details', {
    method: 'GET',
    headers: {},
});
const data = await response.json();
Response
{
  "status": "text",
  "errors": [
    {
      "errorType": "text",
      "fieldName": "text",
      "messageCode": "text"
    }
  ],
  "details": {
    "sourceAsset": "text",
    "destinationAsset": "text",
    "fromAccounts": [
      {
        "accountID": "text",
        "displayName": "text",
        "currencySymbol": "text",
        "balance": 0
      }
    ],
    "toAccounts": [
      {
        "accountID": "text",
        "displayName": "text",
        "currencySymbol": "text",
        "balance": 0
      }
    ]
  }
}

Success Response Example:

{
    "id": 14107,
    "details": {
        "sourceAsset": "GBP",
        "destinationAsset": "SGD",
        "fromAccounts": [
            {
                "accountID": "3140",
                "displayName": "GBP Account",
                "currencySymbol": "£",
                "balance": 5159.54
            }
        ],
        "toAccounts": [
            {
                "accountID": "3146",
                "displayName": "SGD Account",
                "currencySymbol": "S$",
                "balance": 2399.32
            }
        ]
    },
    "status": "1",
    "errors": []
}

Get Quote for Exchange

This endpoint provides a quoted market price for a proposed asset exchange for a particular customer, detailing the source and destination amount for either a "Buy" or "Sell" exchange type. By specifying details of the desired trade, a customer can see the cost or proceeds they might expect from completing a transaction, including any applicable fees. This helps customers decide whether to proceed with an exchange based on real-time financial data.

  • Endpoint: /api/v1/customer/foreign-exchanges/quote

  • Method: POST

Get quote for an exchange

Request Body:

  • CustomerId: non mandatory customerid, if not provided the main customers account details will be returned
  • SourceCurrency: Currency code of the currency to be spent in the exchange.
  • DestinationCurrency: Currency code of the currency to be obtained in the exchange.
  • SourceAmount: The fixed quantity of source currency to be used in the exchange. Either SourceAmount or DesinationAmount must be provided. (optional)
  • DestinationAmount: The precise quantity of the destination currency which is to be purchased, taking fees into account. Either SourceAmount or DesinationAmount must be provided. (optional)
  • SourceAccountId : Source account id
  • DestinationAccountId: Destination account id ( optional, if there is no destination account, one will be created automatically as part of the exchange)

Response:

  • CustomersId: Customer's Id
  • SourceAsset: The asset being spent in the exchange.
  • DestinationAsset: The asset being acquired in the exchange.
  • SourceAmount: This is provided if the inputted value of SourceAmount was not null. This should match the inputted value, and refers to the net price to be payed with the source currency. (optional)
  • DestinationAmount: This is provided if the inputted value of DestinationAmount was not null. This should match the inputted value, and refers to the net quantity of the destination currency to be acquired, taking fees into account. (optional)
  • QuoteSourceAmount: This is provided if the inputted value of DestinationAmount was not null. This value is the quoted price for how much source currency needs to be spent to obtain the DestinationAmount of DestinationCurrency, taking fees into account. (optional)
  • QuoteDestinationAmount: This is provided if the inputted value of SourceAmount was not null. This value is the quoted amount of DesinationCurrency which will be purchased by spending SourceAmount of SourceCurrency, taking fees into account. (optional)
  • SourceAmountLessFees: This is the amount of SourceCurrency remaining after fees are applied. Only this quantity will actually be exchanged for the DestinationCurrency.
  • TotalFees: Total fees
  • CommissionFee: Exchange commission fee
  • QuotedFXRate: The Exchange rate which will be used for the quoted exchange.
  • QuotedFXRateID: FX rate ID associated with this quote. This is used as an input to ExecuteExchange to apply the quote.
  • QuotedFxRateExpiry: FX rate ID expiry date

Possible validation errors:

  • Required
  • Invalid
  • Price_Too_Low (specified price lower than minimum allowed)
  • Amount_Too_Low (specified amount lower than minimum allowed)
  • Price_Too_High (specified price higher than maximum allowed)
  • Amount_Too_High (specified amount highter than maximum allowed)
  • Insufficient_Customer_Balance (customer does not have sufficient balance for exchange)
POST/api/v1/customer/foreign-exchanges/quote
Body
customerIdnullable integer (int32)
sourceCurrencynullable string
destinationCurrencynullable string
sourceAmountnullable number (double)
destinationAmountnullable number (double)
sourceAccountIdinteger (int32)
destinationAccountIdnullable integer (int32)
Response

OK

Body
statusnullable string
errorsnullable array of AvamaeTemplate.Core.Types.Results.Base.ErrorResultDto (object)
idinteger (int64)
detailsAvamaeTemplate.Core.Types.Dtos.CustomerRole.ForeignExchangesModule.GetFXQuoteResultDto (object)
Request
const response = await fetch('/api/v1/customer/foreign-exchanges/quote', {
    method: 'POST',
    headers: {
      "Content-Type": "application/json-patch+json"
    },
    body: JSON.stringify({}),
});
const data = await response.json();
Response
{
  "status": "text",
  "errors": [
    {
      "errorType": "text",
      "fieldName": "text",
      "messageCode": "text"
    }
  ],
  "details": {
    "sourceAmount": 0,
    "destinationAmount": 0,
    "quoteSourceAmount": 0,
    "quoteDestinationAmount": 0,
    "sourceAmountLessFees": 0,
    "comissionFees": 0,
    "totalFees": 0,
    "quotedFXRate": "text",
    "quotedFxRateExpiry": "2024-09-16T20:09:16.466Z"
  }
}

Request Example:

{
    "SourceCurrency": "GBP",
    "DestinationCurrency": "SGD",
    "SourceAmount": "100",
    "SourceAccountId": 3140,
    "DestinationAccountId":3146
}

Success Response Example:

{
    "id": 1,
    "details": {
        "sourceAmount": 100,
        "destinationAmount": null,
        "quoteSourceAmount": null,
        "quoteDestinationAmount": 167.89,
        "sourceAmountLessFees": 99.5,
        "comissionFees": 0.5,
        "totalFees": 0.5,
        "quotedFXRate": "1.687312",
        "quotedFXRateID": 1423,
        "quotedFxRateExpiry": "2024-08-19T14:13:22.6153953Z"
    },
    "status": "1",
    "errors": []
}

Possible Error Codes

Error Message CodeDescription

Required

Named field missing or zero

Invalid

Value given for named field is invalid

No_Account

No source account details found

Insufficient_Funds

Source account do not have enough funds to performa the exchange


Execute Exchange

This endpoint is designed to initiate a sell exchange, allowing a customer to sell an asset at a given price or for a specific amount.

  • Endpoint: /api/v1/customer/foreign-exchanges/executeexchange

  • Method: POST

Execute an exchange

Request Body:

  • CustomersId: Customer's Id
  • FxRateId: The Foreign Exchange rate id, which was returned by calling the GetQuoteAsync endpoint
  • PurposeCode: Reason code for the transfer to the payee (required for foreign exchanges). E.g. 'PUC001'

Response:

  • Id: Exchange Id
  • ExchangeType: Exchange type (possible values: Buy, Sell)
  • Status: Exchange status (possible values: WaitingForApproval, Rejected, WaitingForConfirmation, AwaitingRfi, Pending, Completed, Failed)
  • FromTransactionsId: Associated exchange transaction from debited managee asset account
  • ToTransactionsId: Associated exchange transaction to credited managee asset account
  • ManageesId: Managee's Id
  • AssetPair: Asset pair
  • RequestAmount: Amount requested
  • RequestPrice: Price requested
  • ExecutedAmount: Amount executed
  • ExecutedPrice: Price executed
  • CommissionFee: Commission fee
  • PayeesId: If receiving account is a passthrough account, receiving payee's Id
  • TransferType: If receiving account is a passthrough account, type of transfer from passthrough account to payee (possible values: Wire, ACH)
  • bHasOpenRfi: Flag indicating if request for information is pending to be submitted (FX only)

Possible validation errors:

  • Required
  • Invalid
  • Price_Too_Low (specified price lower than minimum allowed)
  • Amount_Too_Low (specified amount lower than minimum allowed)
  • Price_Too_High (specified price higher than maximum allowed)
  • Amount_Too_High (specified amount highter than maximum allowed)
  • Screening_Failed (transfer to an external payee screening failed, exchange not permitted)
  • Insufficient_Customer_Balance (managee does not have sufficient balance for exchange)
  • Price_Updated (Asset price has updated, exchange cannot be executed at requested price)
POST/api/v1/customer/foreign-exchanges/executeexchange
Body
customerIdnullable integer (int32)
fxRateIdinteger (int32)
purposeCodenullable string
Response

OK

Body
statusnullable string
errorsnullable array of AvamaeTemplate.Core.Types.Results.Base.ErrorResultDto (object)
idinteger (int64)
detailsAvamaeTemplate.Core.Types.Dtos.CustomerRole.ForeignExchangesModule.ExecuteFXResultDto (object)
Request
const response = await fetch('/api/v1/customer/foreign-exchanges/executeexchange', {
    method: 'POST',
    headers: {
      "Content-Type": "application/json-patch+json"
    },
    body: JSON.stringify({}),
});
const data = await response.json();
Response
{
  "status": "text",
  "errors": [
    {
      "errorType": "text",
      "fieldName": "text",
      "messageCode": "text"
    }
  ]
}

Request Body Example:

{
    "FxRateId": 1423,
    "PurposeCode": "test"
}

Success Response Example:

{
    "id": 14589,
    "details": {},
    "status": "1",
    "errors": []
}

Possible Error Codes

Error Message CodeDescription

Required

Named field missing or zero

Invalid

Value given for named field is invalid

Documents_Not_Verified

Cannot perform this action for this customer due to the KYC state


Last updated