Yield Use Case Build Guide

If you haven’t already, Sign Up for Sandbox Access to get your client ID and secret to work through this Build Guide!

What is the Yield use case?

With the yield use case, you or your customers can generate yield on crypto deposits. Today we support yield generation based on treasury bills. Staking based yield is coming shortly. These yield products are provided by licensed entities.

In general, the way our yield products work is that the funds are deposited into our deposit accounts. From there they are transferred into our yield accounts, where they earn yield. You can choose what type of yield product you want to participate in during onboarding. To withdraw the funds, you have to transfer them from the yield accounts into a deposit account, and withdraw from there.

path

Our Yield accounts only support USD today. Support for other assets will be coming soon. Our yield products are only available to fintechs and their corporate/ accredited customers. If you are not regulated, Layer2 and its partners can provide regulatory sponsorship and will have to conduct KYC/KYB on your customers. Regulatory sponsorship is only available in US, Canada today.

Build Guide

This guide should take no longer than 10 minutes and will allow you to setup the Yield Use Case in Sandbox.

You'll open USD deposit and yield accounts for an already onboarded customer, deposit USD, transfer USD to the yield account, earn yield, transfer the principal and earned yield back into the deposit account and then withdraw the assets to an external account.

By the end of this guide you will have:

  1. Authenticated your request
  2. Created the deposit and yield accounts for the customer
  3. Sent fiat into the deposit account
  4. Transferred fiat from the deposit account to the yield account
  5. Earned yield in the yield account
  6. Transfer fiat back to the deposit account
  7. Withdraw from deposit account

Let’s go!

1. Authenticating your request

Every request you make to a Layer2 Financial API endpoint requires an AUTH_TOKEN. We secure our endpoints using standards based OAuth2 Client Credentials Grant and scopes. This makes authenticating secure and easy.

To obtain the AUTH_TOKEN, you will need to authorize your account using your BASE_64_ENCODED_CLIENTID_AND_SECRET with the scopes you require.

Copy
Copied
curl --location --request POST 'https://auth.layer2financial.com/oauth2/ausbdqlx69rH6OjWd696/v1/token?grant_type=client_credentials&scope=customers:read+customers:write+accounts:read+accounts:write+exchanges:read+exchanges:write+withdrawals:read+withdrawals:write+deposits:read+deposits:write+transfers:read+transfers+write' \
--header 'Accept: application/json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cache-Control: no-cache' \
--header 'Authorization: Basic {BASE_64_ENCODED_CLIENTID_AND_SECRET}'

This gives you a response object containing your AUTH_TOKEN This AUTH_TOKEN is used in all API calls.

Copy
Copied
{
	"token_type":"Bearer",
	"expires_in":43200,
	"access_token": {AUTH_TOKEN},
	"scope":"customers:read customers:write accounts:write accounts:read exchanges:read exchanges:write withdrawals:read withdrawals:write deposits:read deposits:write transfers:read transfers:write" 
}

The scopes we’ll need for this tutorial are:

  • customers:read and customers:write so we can create our customer and get information about them.
  • accounts:read and accounts:write so we can create our accounts and get information about them.
  • exchanges:read and exchanges:write so we can create an exchange operation and get information about it
  • deposits:read and deposits:write so we can create a deposit operation and get information about it
  • withrawals:read and withdrawals:write so we can create a withdrawal operation and get information about it
  • transfers:read and transfers:write so we can create a transfer operation and get information about it

The full list of scopes are available here.

With that done, we can get on to setting up accounts for a corporate customer we have pre-created for you: Zarina Inc., with a customer_id of ZarinaInc001. To learn how to create a customer, check out Applications.

2. Creating the fiat deposit and yield accounts

We need two accounts, a fiat deposit account and a fiat yield account.

To create these two accounts we need:

  • The customer_id from above. For this example that is ZarinaInc001 .
  • An account_id for each account that will be the unique identifier for that specific account. Here we’ll use ZarinaInc001_USD_Deposit.001 as our fiat deposit account id and ZarinaInc001_USD_Yield.001 for our crypto account id.
  • The product_id : This is the type of account to be opened. For the deposit account, it is DEPOSIT_FORT_FIAT . For the yield account, it is YIELD_FORT_FIAT .
  • The asset_type_id : The asset type that the accounts are going to use. Our fiat accounts are in USD, so the asset_type_id in Sanxbox is FIAT_TESTNET_USD . NOTE: In Production, the asset type id will be FIAT_MAINNET_USD .

Creating our fiat deposit account

For our fiat account, we’re going to call the /accounts/deposits endpoint:

Copy
Copied
curl --location --request POST 'https://sandbox.layer2financial.com/api/v1/accounts/deposits' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--header 'Content-Type: application/json' \
--data-raw '{
	"customer_id": "ZarinaInc001",
	"account_to_open": {
        "account_id": "ZarinaInc001_USD_Deposit.001",
        "product_id": "DEPOSIT_FORT_FIAT",
        "asset_type_id": "FIAT_TESTNET_USD"
    }        
}'

The response contains the ACCOUNT_ID that you passed in.

Copy
Copied
{
	"data": {
		"id": "ZarinaInc001_USD_Deposit.001"
	}
}

You can use that ACCOUNT_ID and a GET request to the accounts/deposits/{ACCOUNT_ID} endpoint to retrieve information about this account:

Copy
Copied
curl --location --request GET 'https://sandbox.layer2financial.com/api/v1/accounts/deposits/ZarinaInc001_USD_Deposit.001' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--header 'Content-Type: application/json'

The response object will have the status of the account, product and asset type ids, and the current and available balance:

Copy
Copied
{
  "data": {
    "id": "ZarinaInc001_USD_Deposit.001",
    "status": "OPEN",
    "asset_type_id": "FIAT_TESTNET_USD",
    "product_id": "DEPOSIT_FORT_FIAT",
    "current_balance": 0,
    "available_balance": 0
  }
}

Creating our fiat yield account

For our yield account, we’re going to call the /accounts/deposits endpoint as well:

Copy
Copied
curl --location --request POST 'https://sandbox.layer2financial.com/api/v1/accounts/deposits' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--header 'Content-Type: application/json' \
--data-raw '{
	"customer_id": "ZarinaInc001",
	"account_to_open": {
        "account_id": "ZarinaInc001_USD_Yield.001",
        "product_id": "YIELD_FORT_FIAT",
        "asset_type_id": "FIAT_TESTNET_USD"
    }
}'

The response contains the account_id that you passed in :

Copy
Copied
{
	"data": {
		"id": "ZarinaInc001_USD_Yield.001"
	}
}

That’s it for creating our accounts. Now let's start transacting!

3. Depositing fiat

Next, we have to deposit fiat. you can do that by calling the deposits endpoint.

Copy
Copied
curl --location --request POST 'https://sandbox.layer2financial.com/api/v1/deposits' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "deposit_type": "PUSH",
    "deposit_destination": {
	    "destination_account_id": "ZarinaInc001_USD_Deposit.001"
    }
}'

You will get back the following response with the fiat deposit instructions that you can supply to your customers. Once the fiat funds are deposited, the customer account will be credited.

You will notice 2 memo fields under the deposit_instructions. One is under the ACH instruction_type and the other is under the FEDWIRE instruction_type. Save one of those memo fields as you will need it to siumulate the deposit in Sandbox.

Copy
Copied
{
    "data": {
        "id": "90804565-effe-4fd4-8fb7-61b40eaa88c9",
        "status": "REQUESTED",
        "created_timestamp": "2023-02-20T12:09:26.63017-05:00",
        "destination_details": {
            "destination_account_id": "ZarinaInc001_USD_Deposit.001",
            "asset_type_id": "FIAT_TESTNET_USD"
        },
        "deposit_instructions": [
            {
                "instruction_type": "ACH",
                "account_holder_name": "Joe Bloggs",
                "account_number": "9695859732",
                "account_routing_number": "715960587",
                "memo": "15218d1f-6651-4f62-812c-2e4aaa5c241c",
                "asset_type_id": "FIAT_TESTNET_USD"
            },
            {
                "instruction_type": "FEDWIRE",
                "account_holder_name": "Joe Bloggs",
                "account_number": "9695859732",
                "account_routing_number": "715960587",
                "account_holder_address": {
                    "unit_number": null,
                    "address_line1": "123 Sample St",
                    "address_line2": null,
                    "address_line3": null,
                    "city": "Boston",
                    "state": "MA",
                    "postal_code": "02135",
                    "country_code": "US"
                },
                "institution_address": {
                    "unit_number": null,
                    "address_line1": "1 Financial Place",
                    "address_line2": "Floor 34",
                    "address_line3": null,
                    "city": "Boston",
                    "state": "MA",
                    "postal_code": "02135",
                    "country_code": "US"
                },
                "memo": "ea947e78-50ba-40b0-8e6e-32345eeb2cab",
                "asset_type_id": "FIAT_TESTNET_USD"
            }
        ]
    }
}

To simulate the deposit in sandbox, Login to the Management UI using your provided organization id and credentials. Navigate to the Customers screen and click on the 'Create manual deposit' on the right.

Enter one of the memo entries from the above response object and $1,000 as the amount you want to deposit.

path

Click on the 'Confirm' button and your funds will now be deposited within a few minutes into the account in sandbox.

path

After a few minutes, if you query the account using accounts/deposits/{ACCOUNT_ID} endpoint, you will see the current and available balance reflecing the $1,000 you just added.

Copy
Copied
curl --location --request GET 'https://sandbox.layer2financial.com/api/v1/accounts/deposits/ZarinaInc001_USD_Deposit.001' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--header 'Content-Type: application/json'

The response object will reflect the available_balance of $1,000.

Copy
Copied
{
  "data": {
    "id": "ZarinaInc001_USD_Deposit.001",
    "status": "OPEN",
    "asset_type_id": "FIAT_TESTNET_USD",
    "product_id": "DEPOSIT_FORT_FIAT",
    "current_balance": 1000,
    "available_balance": 1000
  }
}

You can also check the account balance through the Management UI, by navigating to the customer and then the account for the customer.

Now that the USD is in the fiat account, lets exchange it for some USDC!

4. Transferring to the yield account

To transfer the USD from the deposit account to the yield account, you will need to call the transfers endpoint. The source_account_id is the deposit account and the destination_account_id is the yield account. For this example, we are only transferring 900 to the yield account as we will ues the remainder to simulate yield distribution.

A Transfer is a 2 step operation: Setup and Accept. To learn more about Transfers, click here.

Setup the transfer

Copy
Copied
curl --location  --request POST 'https://sandbox.layer2financial.com/api/v1/transfers' \
--header 'Authorization: {AUTH_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
  "source_account_id": "ZarinaInc001_USD_Deposit.001",
  "destination_account_id": "ZarinaInc001_USD_Yield.001",
  "amount": 900,
  "description": "transfer from Deposit to Yield"
}
'

A 200 response will provide you with the id. You will use that as the transfer_id in the Accept operation.

Copy
Copied
{
    "data": {
        "id": "d2aba5df-0bbf-4913-ad2a-bc055e5e7a1b",
        "status": "REQUESTED",
        "created_timestamp": "2023-02-21T19:08:12.39557",
        "valid_until": "2023-02-21T19:18:12.407133",
        "source_details": {
            "source_account_id": "ZarinaInc001_USD_Deposit.001",
            "asset_type_id": "FIAT_TESTNET_USD",
            "amount_to_debit": 900.000000000000000000
        },
        "destination_details": {
            "destination_account_id": "ZarinaInc001_USD_Yield.001",
            "asset_type_id": "FIAT_TESTNET_USD",
            "amount_to_credit": 900.000000000000000000
        }
    }
}

Accept the transfer

To accept the transfer, you have to call the transfers/{TRANSFER_ID}/acccept endpoint.

Copy
Copied
curl --location --request POST 'https://sandbox.layer2financial.com/api/v1/transfers/{TRANSFER_ID}/accept' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--data ''

A 200 response will reflect the updated status of the transfer and will look something like:

Copy
Copied
{
    "data": {
        "id": "d2aba5df-0bbf-4913-ad2a-bc055e5e7a1b",
        "status": "ACCEPTED"
    }
}

If you query the Yield account, you will see the funds in there.

Copy
Copied
curl --location 'https://sandbox.layer2financial.com/api/v1/accounts/deposits/ZarinaInc001_USD_Yield.001' \
--header 'Authorization: Bearer {AUTH_TOKEN}'

You should see a response as follows, reflecting the $1,000 successfully transferred into the yield account:

Copy
Copied
{
    "data": {
        "id": "ZarinaInc001_USD_Yield.001",
        "status": "OPEN",
        "asset_type_id": "FIAT_TESTNET_USD",
        "product_id": "YIELD_FORT_FIAT",
        "current_balance": 900.000000000000000000,
        "available_balance": 900.000000000000000000
    }
}

5. Earning yield

In production, the interest will be distributed based on the type of yield product. e.g. 4 week treasury bill product will distribute interest upon maturity.

In Sandbox, to simulate interest distribution, we use a special yield distribution account TEST_USD_YIELD_DISTRIBUTION_ACC_001 we have created for you. On a nightly basis, the yield distribution engine will take all the funds in this special account and distribute it (pro-rated) into the various YIELD_FORT_FIAT accounts across all customers.

Use the same steps from step 4 above to move 50 USD from your deposit account into this special account. At 12 am ET, you will see the interest distributed into your account.

6. Withdrawing from yield account

To withdraw the funds from the yield account, you have to first transfer the assets back to the deposit account. Once that is complete, you can withdraw out to an external account.

Transfer to the deposit account

Similar to above, you have to setup and accept the transfer from the yield account to the deposit account.

Setup the transfer

Copy
Copied
curl --location  --request POST 'https://sandbox.layer2financial.com/api/v1/transfers' \
--header 'Authorization: {AUTH_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
  "source_account_id": "ZarinaInc001_USD_Yield.001",
  "destination_account_id": "ZarinaInc001_USD_Deposit.001",
  "amount": 1000,
  "description": "transfer from Yield back to Deposit"
}
'

A 200 response will provide you with the id. You will use that as the transfer_id in the Accept operation.

Copy
Copied
{
    "data": {
        "id": "fcd2ed55-894e-41f2-a1c5-c59771f8dd33",
        "status": "REQUESTED",
        "created_timestamp": "2023-02-21T19:33:44.506126",
        "valid_until": "2023-02-21T19:43:44.551085",
        "source_details": {
            "source_account_id": "ZarinaInc001_USD_Yield.001",
            "asset_type_id": "FIAT_TESTNET_USD",
            "amount_to_debit": 900.000000000000000000
        },
        "destination_details": {
            "destination_account_id": "ZarinaInc001_USD_Deposit.001",
            "asset_type_id": "FIAT_TESTNET_USD",
            "amount_to_credit": 900.000000000000000000
        }
    }
}

Execute the transfer To execute the transfer, you have to call the transfers/{TRANSFER_ID}/acccept endpoint.

Copy
Copied
curl --location --request POST 'https://sandbox.layer2financial.com/api/v1/transfers/{TRANSFER_ID}/accept' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--data ''

A 200 response will reflect the updated status of the transfer and will look something like:

Copy
Copied
{
    "data": {
        "id": "fcd2ed55-894e-41f2-a1c5-c59771f8dd33",
        "status": "ACCEPTED"
    }
}

You can query the deposit account ZarinaInc001_USD_Deposit.001 to confirm that the funds have been transferred.

Copy
Copied
curl --location 'https://sandbox.layer2financial.com/api/v1/accounts/deposits/ZarinaInc001_USD_Deposit.001' \
--header 'Authorization: Bearer {AUTH_TOKEN}'

You should see a response as follows, reflecting the $1,000 successfully transferred into the deposit account:

Copy
Copied
{
    "data": {
        "id": "ZarinaInc001_USD_Deposit.001",
        "status": "OPEN",
        "asset_type_id": "FIAT_TESTNET_USD",
        "product_id": "DEPOSIT_FORT_FIAT",
        "current_balance": 1000.000000000000000000,
        "available_balance": 1000.000000000000000000
    }
}

7. Withdraw to external account

Now that the funds are back in the deposit account, you can withdraw them to an external account, using the withdrawals endpoint.

The withdrawal operation has 3 steps: create a counterparty, setup the withdrawal, execute the withdrawal. To learn more on withdrawal, click here.

Create Counterparty To create the counterparty, call the counterparties endpoint.

Copy
Copied
curl --location 'https://sandbox.layer2financial.com/api/v1/counterparties' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "customer_id": "ZarinaInc001",
    "counterparty_type": "FIAT_US",
    "is_international": false,
    "supported_rails": [
        "ACH"
    ],
    "profile": {
        "name": "Zarina Inc."
    },
    "account_information": {
        "asset_type_id": "FIAT_TESTNET_USD",
        "account_number": "894375894",
        "type": "CHECKING",
        "routing_number": "125061207"
    }
    
}'

A successful 200 response as follows will provide you the id, which is the counterparty_id you will need to setup the withdrawal.

Copy
Copied
{
    "data": {
        "id": "b26d76e6-b29f-4e9a-8e7c-be29678ab720"
    }
}

Setup withdrawal To setup the withdrawal, call the withdrawal endpoint by passing the above id as the COUNTERPARTY_ID.

Copy
Copied
curl --location 'https://sandbox.layer2financial.com/api/v1/withdrawals' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{

    "withdrawal_rail": "ACH",
    "description": "Withdraw Fiat",
    "source_account_id": "ZarinaInc001_USD_Deposit.001",
    "amount":"3",
    "destination_counterparty_id": "{COUNTERPARTY_ID}",
    "memo": "withdrawal"
}'

A 200 response will give you the id of the withdrawal. This will be the WITHDRAWAL_ID in the subsequent Execution and Sandbox Simulation steps.

Copy
Copied
{
    "data": {
        "id": "887804df-13c2-4019-835b-08c92ed77c72",
        "status": "REQUESTED"
    }
}

Execute withdrawal To execute the withdrawal, you have to call the withdrawals/{WITHDRAWAL_ID}/accept endpoint as follows

Copy
Copied
curl --location --request POST 'https://sandbox.layer2financial.com/api/v1/withdrawals/{WITHDRAWAL_ID}/accept' \
--header 'Authorization: Bearer {AUTH_TOKEN}' \
--data ''

A 200 response will reflect the updated status of the withdrawal and will look something like:

Copy
Copied
{
    "data": {
        "id": "887804df-13c2-4019-835b-08c92ed77c72",
        "status": "ACCEPTED"
    }
}

In Production, that would be it. The fiat funds will be withdrawn to the external account. In Sandbox, however, we have to do 1 extra step.

Simulate withdrawal in Sandbox Login to the Management UI with your provided credentials. Click on Confirm Withdrawal on the middle right of the screen, passing in the WITHDRAWAL_ID. The screen looks something like this.

path

Click Review, which will take you to the Confirmation screen, which looks something as follows. path

Click on Confirm and you are done. The funds have now left the deposit account.

And thats it for this build guide.

Summary

Let’s review:

  1. Authenticate -Authenticate using the OAuth Endpoint to get the AUTH_TOKEN .
  2. Create accounts for the customer - Create a USD deposit account ( DEPOSIT_ANCH_FIAT product type) and USD yield account ( BASIC_YIELD_FIAT product type) using the accounts/deposits endpoint . Both accounts have a FIAT_TESTNET_USD asset type in sandbox.
  3. Send funds into Deposit account - Setup a deposit into the USD deposit account and get deposit instructions using the deposits endpoint . This will give you a memo in the deposit instructions. You will need this memo to simulate a fiat deposit in Sandbox, using the Management UI .
  4. Transfer to Yield account - Transfer funds to the yield account using the transfers endpoint . You have to accept the transfer after creating it, or it won't be executed. Use the transfers/{TRANSFER_ID}/accept endpoint
  5. Earn Yield - In Sandbox, to simulate interest distribution, interest will be deposited into the USD yield account on a nightly basis. In Production, it will be on a monthly basis.
  6. Transfer back to Deposit account - You can withdraw the funds from the yield account by first doing a book transfer from the yield account back into the fiat account. Transfer funds to the deposit account using the transfers endpoint . You have to accept the transfer after creating it, or it won't be executed. Use the transfers/{TRANSFER_ID}/accept endpoint .
  7. Withdraw funds from Deposit account - To withdraw funds from the deposit account into an external account, call the withdrawals endpoint . To execute the withdrawal, You have to accept it using the withdrawals/{WITHDRAWAL_ID}/accept endpoint . In Sandbox, you can simulate a withdrawal through the Management UI .

To dive deeper into what you can do on the Layer2 platform, head to our API documentation.

Contact Us - We’d love to hear your thoughts, and you can contact the team via slack, website or email support@layer2financial.com.

© 2023 Layer2 Financial Inc. All Rights Reserved.