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.
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:
- Authenticated your request
- Created the deposit and yield accounts for the customer
- Sent fiat into the deposit account
- Transferred fiat from the deposit account to the yield account
- Earned yield in the yield account
- Transfer fiat back to the deposit account
- 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.
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.
{
"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
andcustomers:write
so we can create our customer and get information about them. -
accounts:read
andaccounts:write
so we can create our accounts and get information about them. -
exchanges:read
andexchanges:write
so we can create an exchange operation and get information about it -
deposits:read
anddeposits:write
so we can create a deposit operation and get information about it -
withrawals:read
andwithdrawals:write
so we can create a withdrawal operation and get information about it -
transfers:read
andtransfers: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 isZarinaInc001
. -
An
account_id
for each account that will be the unique identifier for that specific account. Here we’ll useZarinaInc001_USD_Deposit.001
as our fiat deposit account id andZarinaInc001_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 isDEPOSIT_FORT_FIAT
. For the yield account, it isYIELD_FORT_FIAT
. -
The
asset_type_id
: The asset type that the accounts are going to use. Our fiat accounts are in USD, so theasset_type_id
in Sanxbox isFIAT_TESTNET_USD
. NOTE: In Production, the asset type id will beFIAT_MAINNET_USD
.
Creating our fiat deposit account
For our fiat account, we’re going to call the /accounts/deposits
endpoint:
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.
{
"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:
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:
{
"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:
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 :
{
"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.
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.
{
"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.
Click on the 'Confirm' button and your funds will now be deposited within a few minutes into the account in sandbox.
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.
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.
{
"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
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.
{
"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.
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:
{
"data": {
"id": "d2aba5df-0bbf-4913-ad2a-bc055e5e7a1b",
"status": "ACCEPTED"
}
}
If you query the Yield account, you will see the funds in there.
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:
{
"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
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.
{
"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.
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:
{
"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.
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:
{
"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.
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.
{
"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
.
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.
{
"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
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:
{
"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.
Click Review, which will take you to the Confirmation screen, which looks something as follows.
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:
-
Authenticate
-Authenticate using the OAuth Endpoint to get the
AUTH_TOKEN
. -
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 theaccounts/deposits
endpoint . Both accounts have aFIAT_TESTNET_USD
asset type in sandbox. -
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 amemo
in the deposit instructions. You will need thismemo
to simulate a fiat deposit in Sandbox, using the Management UI . -
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 thetransfers/{TRANSFER_ID}/accept
endpoint - 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.
-
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 thetransfers/{TRANSFER_ID}/accept
endpoint . -
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 thewithdrawals/{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.