Digital Asset Managed Transfers with APIs Guide

This page will help you get started with Mesh APIs to authenticate an account and configure, preview, and execute a transfer.

Overview

One of the unique features with Mesh is enabling clients to build embedded experiences that enables retail users to transfer digital assets from either centralized exchanges or self-custody wallets to the client application without needing to copy and paste a target address on a separate platform. This document will guide you through integrating with our Link SDK and server-side APIs to build a native transfer experience from centralized exchanges for your users.

Mesh APIs handle credential validation, multi-factor authentication, and error handling when connecting to each account. After an end user authenticates with their account credentials, clients will be passed authentication tokens to provide access to the account which allows client applications to initiate transfers on behalf of the user on the originating platform. Clients have the option of using Mesh's pre-built transfer UI or building the experience natively using server-side calls.

You can test the authentication and transfers functionality for yourself in our interactive demo.

Using Mesh APIs, you can easily connect and transfer digital assets from:

  • Centralized exchanges
    • To transfer from self-custody wallets, view our guide [link] to transfer using our drop-in UI

Our v2 Transfers APIs facilitate a structured transfer flow that allows the end user to configure, preview, a transfer before committing to execute their transfer. Mesh's Transfer Risk Engine runs checks on the transfer to help protect against misconfigured transfers that fail and can not be retrieved.

  • Configure - setup transfer with the appropriate target addresses so that Mesh can provide relevant information (eg. eligibility, min/max transfer amount, estimated gas fees, platform fees) to help configure the transfer
  • Preview - provides a detailed preview of the transfer, including target address, origin address, transfer amount, and associated transfer fees.
  • Execute - processes the transfer by instructing the originating platform to execute the transfer with the given parameters.

You can use Mesh Transfer APIs directly for transfers from centralized exchanges to build the experience natively on your platform. Alternatively, using the Link + Transfer SDKs, you can use Mesh's pre-built transfer UI to easily enable transfers on your platform.

Introduction

The fastest to get started with Meshs's Transfers product is by testing the functionality via our Interactive Demo. Then, you’ll need to generate API keys, which are accessible after signing up for Mesh.

You can generate two different API keys (one for Sandbox and another for Production), you should store the API keys immediately after generating them as they will no longer be viewable after leaving the page.

You should add any 'Allowed callback URLs' for your local, staging and production environments, this will enable the Link SDK to correctly load. Note: you should add full URLs (eg. http://localhost:3000/settings/user)

How the Link Authentication and Transfer APIs work

You will client-side components to authenticate with Mesh, then server-side components to transfer with Mesh.

Link Authentication

  1. Call /api/v1/cataloglink to create a link URL
    to create a temporary and unique URL that your
    user can connect their account.

  2. Pass the iFrameURL to the appropriate Link SDK

    1. Web Link SDK
    2. iOS Link SDK
    3. Android Link SDK
  3. Your user will be able to filter and search for the account
    they want to connect. Mesh will manage the authentication
    flow and handle MFAs for all supported integrations.

  4. After a user successfully enters their credentials, in the return method you will receive an auth_token.

  5. Client stores the auth_token (and refresh_token) for use in subsequent transfer calls.

Transfer APIs

Overview

  1. Call [[/api/v1/transfers/managed/networks](https://docs.meshconnect.com/reference/get_api-v1-transfers-managed-networks) to get a list of networks supported by Mesh along with the network IDs that will be required to configure a transfer. These network IDs are static, so that it is recommended to store these in your database.

Request

curl -X GET [https://sandbox-integration-api.getfront.com/](https://sandbox-integration-api.getfront.com/api/v1/cataloglink)api/v1/transfers/managed/networks
-H 'Content-Type: application/json' \
-H 'X-Client-Id: CLIENT_ID' \
-H 'X-Client-Secret: CLIENT_SECRET' \

Response

{
    "content": {
        "networks": [
            {
                "id": "7436e9d0-ba42-4d2b-b4c0-8e4e606b2c12",
                "name": "Polygon",
                "chainId": "137",
                "supportedTokens": [
                    "MATIC",
                    "USDC"
                ],
                "supportedBrokerTypes": [
                    "binanceInternational",
                    "kraken",
                    "robinhood"
                ]
            },
            {
                "id": "e3c7fdd8-b1fc-4e51-85ae-bb276e075611",
                "name": "Ethereum",
                "chainId": "1",
                "supportedTokens": [
                    "ETH",
                    "USDC"
                ],
                "supportedBrokerTypes": [
                    "binanceInternational",
                    "kraken",
                    "robinhood"
                ]
            },
            {
                "id": "0291810a-5947-424d-9a59-e88bb33e999d",
                "name": "Solana",
                "chainId": "101",
                "supportedTokens": [
                    "SOL",
                    "USDC"
                ],
                "supportedBrokerTypes": [
                    "binanceInternational",
                    "kraken"
                ]
            }
        ]
    },
    "status": "ok",
    "message": ""
}

Request

curl -X GET [https://sandbox-integration-api.getfront.com/](https://sandbox-integration-api.getfront.com/api/v1/cataloglink)[api/v1/transfers/managed/configure](https://dashboard.getfront.com/docs/api-reference#post-/api/v1/transfers/managed/configure)
-H 'Content-Type: application/json' \
-H 'X-Client-Id: CLIENT_ID' \
-H 'X-Client-Secret: CLIENT_SECRET' \

{
    "FromAuthToken": "{{auth_token}}", // Connected Metamask token
    "FromType": "kraken",
    "ToAddresses": [{
        "NetworkId": "e3c7fdd8-b1fc-4e51-85ae-bb276e075611", // Ethereum network
        "Symbol": "ETH",
        "Address": "0x9Bf6207f8A3f4278E0C989527015deFe10e5D7c6"
    },{
        "NetworkId": "e3c7fdd8-b1fc-4e51-85ae-bb276e075611", // Ethereum network
        "Symbol": "USDC",
        "Address": "0x9Bf6207f8A3f4278E0C989527015deFe10e5D7c6"
    },{
        "NetworkId": "0291810a-5947-424d-9a59-e88bb33e999d", // Solana network
        "Symbol": "USDC",
        "Address": "HN7cABqLq46Es1jh92dQQisAq662SmxELLLsHHe4YWrH"
    },{
        "NetworkId": "0291810a-5947-424d-9a59-e88bb33e999d", // Solana network
        "Symbol": "SOL",
        "Address": "HN7cABqLq46Es1jh92dQQisAq662SmxELLLsHHe4YWrH"
    }]
}

Response

{
    "content": {
        "status": "succeeded",
        "holdings": [
            {
                "symbol": "ETH",
                "availableBalance": 0.003591685289408172, // Balance in ETH
                "availableBalanceInFiat": 6.86, // Balance in USD
                "eligibleForTransfer": true, // Indicates that ETH can be generally sent
                "networks": [ 
                    {
                        "name": "Ethereum",
                        "id": "e3c7fdd8-b1fc-4e51-85ae-bb276e075611",
                        "minimumAmount": 0.000000000000000001,
                        "maximumAmount": 0.002836873765928172,
                        "totalEstimatedTransferFeeInFiat": 1.44,
                        "minimumAmountInFiat": 0.00,
                        "estimatedNetworkGasFee": {
                            "fee": 0.00075481152348, // Average estimated fee
                            "feeCurrency": "ETH",
                            "feeInFiat": 1.4408748134014416 // Fee converted to fiat
                        },
                        "institutionTransferFee": {
                            "fee": 0,
                            "feeInFiat": 0
                        },
                        "eligibleForTransfer": true
                    }
                ]
            },
            {
                "symbol": "USDC",
                "availableBalance": 15,
                "availableBalanceInFiat": 15.00,
                "eligibleForTransfer": true,
                "networks": [
                    {
                        "name": "Ethereum",
                        "id": "e3c7fdd8-b1fc-4e51-85ae-bb276e075611",
                        "minimumAmount": 0.000000000000000001,
                        "maximumAmount": 15,
                        "totalEstimatedTransferFeeInFiat": 2.89,
                        "minimumAmountInFiat": 0.00,
                        "maximumAmountInFiat": 15.00,
                        "estimatedNetworkGasFee": {
                            "fee": 0.0015155537089302,
                            "feeCurrency": "ETH",
                            "feeInFiat": 2.893070786051037384
                        },
                        "institutionTransferFee": {
                            "fee": 0,
                            "feeInFiat": 0
                        },
                        "eligibleForTransfer": true
                    }
                ]
            }
        ]
    },
    "status": "ok",
    "message": ""
}
  1. A user should be able to configure their transfer and select token, network (optional) and input amount to transfer

  2. Call /api/v1/transfers/managed/preview with the auth_token and the selected token, network and amount inputted by the user and the target address provided in the configure response.

Request

curl -X GET [https://sandbox-integration-api.getfront.com/](https://sandbox-integration-api.getfront.com/api/v1/cataloglink)[api/v1/transfers/managed/configure](https://dashboard.getfront.com/docs/api-reference#post-/api/v1/transfers/managed/configure)
-H 'Content-Type: application/json' \
-H 'X-Client-Id: CLIENT_ID' \
-H 'X-Client-Secret: CLIENT_SECRET' \

{
  "FromAuthToken": "{auth_token}",
  "FromType": "kraken",
  "NetworkId": "e3c7fdd8-b1fc-4e51-85ae-bb276e075611",
  "Symbol": "USDC",
  "ToAddress": "0x9Bf6207f8A3f4278E0C989527015deFe10e5D7c6",
  "Amount": 10
}

Response

{
  "Status": "Succeeded",
  "ErrorMessage": null,
  "PreviewResult": {
    "PreviewId": "29B185B1-2305-40FB-A0E2-929D61451568",
    "ExpiresIn": 180,
    "FromAddress": "0x9Bf6207f8A3f4278E0C989527015deFe10e5D7c6",
    "ToAddress": "0x326a8825472bb0f4719998e708a1eeeb4473ed1b",
    "ContractAddress": "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58",
    "NetworkId": "E3C7FDD8-B1FC-4E51-85AE-BB276E075611",
    "Symbol": "USDT",
    "Amount": 10,
    "AmountInFiat": 10,
    "NetworkName": "Optimism",
    "EstimatedTime": 600,
    "InstitutionTransferFee": {
      "Fee": 0,
      "FeeCurrency": null,
      "FeeInFiat": 0
    },
    "EstimatedNetworkGasFee": {
      "Fee": 1.1,
      "FeeCurrency": "USDT",
      "FeeInFiat": 1.1
    },
    "TotalTrasferFeeInFiat": 1.1
  }
}
  1. Call /api/v1/transfers/managed/execute with the previewId provided in the preview call and any required authentication (eg. MFA code)
    1. Note: PreviewId expire after a specific amount of time and can not be executed after the expiration time

Request

curl -X GET [https://sandbox-integration-api.getfront.com/](https://sandbox-integration-api.getfront.com/api/v1/cataloglink)[api/v1/transfers/managed/configure](https://dashboard.getfront.com/docs/api-reference#post-/api/v1/transfers/managed/configure)
-H 'Content-Type: application/json' \
-H 'X-Client-Id: CLIENT_ID' \
-H 'X-Client-Secret: CLIENT_SECRET' \

{
  "fromAuthToken": "{auth_token}",
  "fromType": "kraken",
  "previewId": "29B185B1-2305-40FB-A0E2-929D61451568",
  "mfaCode": "112457"
}

Response

{
  "Status": "Succeeded",
  "ErrorMessage": null,
  "TransferResult": {
    "TransferId": "29B185B1-2305-40FB-A0E2-929D61451568",
    "Status": "Pending",
    "StatusDetail": "Pending",
    "FromAddress": "0x9Bf6207f8A3f4278E0C989527015deFe10e5D7c6",
    "ToAddress": "0x326a8825472bb0f4719998e708a1eeeb4473ed1b",
    "Hash": "0xa9bce90d2ab4f17258729d604f88f3709eb105c58db03ca0e97ae4ea500ef98f",
    "NetworkId": "E3C7FDD8-B1FC-4E51-85AE-BB276E075611",
    "Symbol": "USDT",
    "Amount": 10,
    "AmountInFiat": 10,
    "NetworkName": "Optimism",
    "CompletedConfirmations": 7,
    "InstitutionTransferFee": {
      "Fee": 0,
      "FeeCurrency": null,
      "FeeInFiat": 0
    },
    "NetworkGasFee": {
      "Fee": 1.1,
      "FeeCurrency": "USDT",
      "FeeInFiat": 1.1
    },
    "TotalTrasferFeeFiat": 1.1
  }