Skip to main content

PIX2STABLE - OnChain Transfer

You have received your credentials, and now we’ll walk through a complete use case that expands upon the basic PIX to STABLE and then after on-chain conversions and transfers flow:

Use Case: PIX to BRLA → USDC/USDT → Subaccounts → External Wallets

This flow starts with a deposit in local currency via PIX to the BRLA stablecoin. From there, BRLA is exchanged for another stable asset such as USDC or USDT.

Once the stable assets are available, subaccounts can be created to organize and segregate balances. Funds are then transferred from the main account to the respective subaccounts as needed.

Finally, tokens held in subaccounts can be transferred to external wallets.

What Will We Cover Here?

  • Login
  • KYC
  • Subaccount creation
    • Subaccount KYC
  • About Webhooks
  • Deposit via PIX to BRLA (Funds credited to Main Account in BRLA Stablecoin)
    • Convert BRLA to USDC or USDT
  • Transfer Tokens to Subaccounts
  • Send Tokens from Subaccounts to External Wallets

Login​

Once you receive your credentials, use the following endpoint to authenticate and receive your JWT.

HTTP POST Request​

https://api.sandbox.avenia.io:10952/v2/auth/login

Sample JSON Body​

{
"email": "your.email@provider.com",
"password": "UseAStrongPassword123!"
}

cUrl Example​

curl -X POST "https://api.sandbox.avenia.io:10952/v2/auth/login" \\
-H "Content-Type: application/json" \\
-d '{
"email": "your.email@provider.com",
"password": "UseAStrongPassword123!"
}'

Upon a successful login (HTTP 200), you will receive an email with a token to validate your login.

Validate Login​

Using the token (emailToken) sent to your email, call the following endpoint to receive your authentication codes (JWT):

HTTP POST Request​

https://api.sandbox.avenia.io:10952/v2/auth/validate-login

Sample JSON Body​

{
"email": "your.email@provider.com",
"emailToken": "777777"
}

cUrl Example​

curl -X POST "https://api.sandbox.avenia.io:10952/v2/auth/validate-login" \\
-H "Content-Type: application/json" \\
-d '{
"email": "your.email@provider.com",
"emailToken": "777777"
}'

JSON Response​

{
"accessToken": "eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"refreshToken": "eyJhbdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}

KYC Main Account​

KYC (Know Your Customer) is essential to track who is moving or receiving funds.

info

We’ll soon see that, to perform KYC on a subaccount, it’s enough to include the subAccountId field as a parameter in the request.

KYC Level 1 is submitted in three calls: request upload URLs for a selfie and an identity document, upload the files, then submit the personal data with the document IDs. See KYC Level 1 for every field, the Web SDK alternative and the document status endpoints.

1. Request document upload URLs​

Call this endpoint twice: once with "documentType": "SELFIE" and once for the identity document (ID, DRIVERS-LICENSE or PASSPORT). Save the id of each response.

https://api.sandbox.avenia.io:10952/v2/documents/
{
"documentType": "PASSPORT",
"isDoubleSided": false
}
curl -X POST "https://api.sandbox.avenia.io:10952/v2/documents/" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "documentType": "PASSPORT", "isDoubleSided": false }'
{
"id": "00000000-0000-0000-0000-000000000002",
"uploadURLFront": "https://<pre-signed-upload-url>"
}

2. Upload the files​

Send each file with a PUT to the uploadURLFront (and uploadURLBack, for double-sided documents) returned above. The If-None-Match: * header is required; accepted formats are PNG, JPEG and PDF.

curl -X PUT "https://<pre-signed-upload-url>" \
-H "Content-Type: image/jpeg" \
-H "If-None-Match: *" \
--data-binary "@/path/to/passport.jpg"

3. Submit the KYC Level 1 request​

https://api.sandbox.avenia.io:10952/v2/kyc/new-level-1/api
{
"fullName": "Jane Doe",
"dateOfBirth": "1990-01-01",
"countryOfTaxId": "BRA",
"taxIdNumber": "12345678900",
"email": "jane.doe@example.com",
"country": "BRA",
"state": "SP",
"city": "SP",
"zipCode": "00000000",
"streetAddress": "123 Example Street",
"uploadedSelfieId": "00000000-0000-0000-0000-000000000001",
"uploadedDocumentId": "00000000-0000-0000-0000-000000000002"
}
info

Countries follow ISO 3166-1 alpha-3 (e.g. BRA) and states follow ISO 3166-2 subdivision codes (e.g. SP).

curl -X POST "https://api.sandbox.avenia.io:10952/v2/kyc/new-level-1/api" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"fullName": "Jane Doe",
"dateOfBirth": "1990-01-01",
"countryOfTaxId": "BRA",
"taxIdNumber": "12345678900",
"email": "jane.doe@example.com",
"country": "BRA",
"state": "SP",
"city": "SP",
"zipCode": "00000000",
"streetAddress": "123 Example Street",
"uploadedSelfieId": "00000000-0000-0000-0000-000000000001",
"uploadedDocumentId": "00000000-0000-0000-0000-000000000002"
}'

The response returns the ID of the KYC attempt. Use it in the next step to track the validation.

{
"id": "00000000-0000-0000-0000-000000000003"
}

KYC - Track KYC Validation​

Before proceeding, ensure that the KYC for the main account has been successfully validated. Use the following GET endpoint with the attempt id returned by POST /v2/kyc/new-level-1/api:

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/kyc/attempts/{kyc-attempt-id}

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/kyc/attempts/{kyc-attempt-id}" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response - COMPLETED example​

{
"attempt": {
"id": "e51359cd-04b0-4bbc-bf7d-0ee515112d74",
"levelName": "level-1",
"submissionData": null,
"status": "COMPLETED",
"result": "APPROVED",
"resultMessage": "",
"retryable": false,
"createdAt": "2025-03-25T07:39:40.54713Z",
"updatedAt": "2025-03-25T07:39:40.54713Z"
}
}

JSON Response - PENDING example​

{
"attempt": {
"id": "b83802a1-afe9-46ac-96d6-ade6c5961bd3",
"levelName": "level-1",
"submissionData": null,
"status": "PENDING",
"result": "",
"resultMessage": "",
"retryable": false,
"createdAt": "2025-03-26T22:50:14.201695Z",
"updatedAt": "2025-03-26T22:50:14.201695Z"
}
}

JSON Response - REJECT example​

{
"attempt": {
"id": "5bafd6cd-ec40-4dd3-83e0-a5af117c304a",
"levelName": "level-1",
"submissionData": null,
"status": "COMPLETED",
"result": "REJECTED",
"resultMessage": "name does not match",
"retryable": false,
"createdAt": "2025-03-26T22:50:14.201695Z",
"updatedAt": "2025-03-26T22:50:14.201695Z"
}
}

Create Subaccount​

To register your client, create a subaccount. Subaccounts allow the Main Account (you) to manage your clients.

HTTP POST Request​

https://api.sandbox.avenia.io:10952/v2/account/sub-accounts
FieldTypeDescription
accountTypestringSpecify "INDIVIDUAL" for a personal subaccount.
namestringA name for the subaccount (e.g., "Jane Doe").

Sample JSON Body​

{
"accountType": "INDIVIDUAL",
"name": "Jane Doe"
}

cUrl Example​

curl -X POST "https://api.sandbox.avenia.io:10952/v2/account/sub-accounts" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json"
-d '{
"accountType": "INDIVIDUAL",
"name": "Jane Doe"
}'

JSON Response​

The response will include the ID of the created subaccount.

{
"id": "1ee0a663-922b-4389-9f84-074ccff7085d"
}

KYC for Subaccount​

KYC (Know Your Customer) is essential to track who is moving or receiving funds. For subaccounts, perform KYC using the flow below. Be sure to pass the subAccountId parameter.

Since this operation is performed for a subaccount, you must include the field as an endpoint parameter subAccountId.

KYC Level 1 is submitted in three calls: request upload URLs for a selfie and an identity document, upload the files, then submit the personal data with the document IDs. See KYC Level 1 for every field, the Web SDK alternative and the document status endpoints.

1. Request document upload URLs​

Call this endpoint twice for the subaccount: once with "documentType": "SELFIE" and once for the identity document (ID, DRIVERS-LICENSE or PASSPORT). Save the id of each response.

https://api.sandbox.avenia.io:10952/v2/documents/?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d
{
"documentType": "PASSPORT",
"isDoubleSided": false
}
curl -X POST "https://api.sandbox.avenia.io:10952/v2/documents/?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "documentType": "PASSPORT", "isDoubleSided": false }'
{
"id": "00000000-0000-0000-0000-000000000002",
"uploadURLFront": "https://<pre-signed-upload-url>"
}

2. Upload the files​

Send each file with a PUT to the uploadURLFront (and uploadURLBack, for double-sided documents) returned above. The If-None-Match: * header is required; accepted formats are PNG, JPEG and PDF.

curl -X PUT "https://<pre-signed-upload-url>" \
-H "Content-Type: image/jpeg" \
-H "If-None-Match: *" \
--data-binary "@/path/to/passport.jpg"

3. Submit the KYC Level 1 request​

https://api.sandbox.avenia.io:10952/v2/kyc/new-level-1/api?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d
{
"fullName": "Jane Doe",
"dateOfBirth": "1990-01-01",
"countryOfTaxId": "BRA",
"taxIdNumber": "12345678900",
"email": "jane.doe@example.com",
"country": "BRA",
"state": "SP",
"city": "SP",
"zipCode": "00000000",
"streetAddress": "123 Example Street",
"uploadedSelfieId": "00000000-0000-0000-0000-000000000001",
"uploadedDocumentId": "00000000-0000-0000-0000-000000000002"
}
info

Countries follow ISO 3166-1 alpha-3 (e.g. BRA) and states follow ISO 3166-2 subdivision codes (e.g. SP).

curl -X POST "https://api.sandbox.avenia.io:10952/v2/kyc/new-level-1/api?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"fullName": "Jane Doe",
"dateOfBirth": "1990-01-01",
"countryOfTaxId": "BRA",
"taxIdNumber": "12345678900",
"email": "jane.doe@example.com",
"country": "BRA",
"state": "SP",
"city": "SP",
"zipCode": "00000000",
"streetAddress": "123 Example Street",
"uploadedSelfieId": "00000000-0000-0000-0000-000000000001",
"uploadedDocumentId": "00000000-0000-0000-0000-000000000002"
}'

The response returns the ID of the KYC attempt. Use it in the next step to track the validation.

{
"id": "00000000-0000-0000-0000-000000000003"
}

Track KYC Subaccount Validation​

Before proceeding, ensure that the KYC for the subaccount has been successfully validated. Use the following GET endpoint with the attempt id returned by POST /v2/kyc/new-level-1/api:

Since this operation is performed for a subaccount, you must include the field as an endpoint parameter subAccountId.

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/kyc/attempts/{kyc-attempt-id}?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/kyc/attempts/{kyc-attempt-id}?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response - COMPLETED example​

{
"attempt": {
"id": "e51359cd-04b0-4bbc-bf7d-0ee515112d74",
"levelName": "level-1",
"submissionData": null,
"status": "COMPLETED",
"result": "APPROVED",
"resultMessage": "",
"retryable": false,
"createdAt": "2025-03-25T07:39:40.54713Z",
"updatedAt": "2025-03-25T07:39:40.54713Z"
}
}

JSON Response - PENDING example​

{
"attempt": {
"id": "b83802a1-afe9-46ac-96d6-ade6c5961bd3",
"levelName": "level-1",
"submissionData": null,
"status": "PENDING",
"result": "",
"resultMessage": "",
"retryable": false,
"createdAt": "2025-03-26T22:50:14.201695Z",
"updatedAt": "2025-03-26T22:50:14.201695Z"
}
}

JSON Response - REJECT example​

{
"attempt": {
"id": "5bafd6cd-ec40-4dd3-83e0-a5af117c304a",
"levelName": "level-1",
"submissionData": null,
"status": "COMPLETED",
"result": "REJECTED",
"resultMessage": "name does not match",
"retryable": false,
"createdAt": "2025-03-26T22:50:14.201695Z",
"updatedAt": "2025-03-26T22:50:14.201695Z"
}
}

About Webhooks​

Before we begin the Operations section, we’ll share a guide for integrating webhooks—this will allow you to receive real‑time updates for every stage of a Ticket event. A Ticket event refers to any update related to a created ticket (i.e., a money movement) within your Account; it may also involve a SubAccount. Events can have multiple statuses, such as TICKET‑CREATED, DEPOSIT‑PROCESSING, and so on.

We recommend following these steps in order:

Pix to BRLA​

We will now transfer balances to the main account via PIX, and BRLA Stable will be deposited.

warning

The quote is only valid for 15 seconds!

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?inputCurrency=BRL&inputPaymentMethod=PIX&outputAmount=100&outputCurrency=BRLA&outputPaymentMethod=INTERNAL&inputThirdParty=false&outputThirdParty=false
FieldValueDescriptionRequired
inputCurrencyBRLThe currency in which the mainAccount (in this case, Brazilian Reais).yes
inputPaymentMethodPIXThe payment method in this case PIX method.yes
outputAmount100The amount that the mainAccount receive (e.g., 98.58 = R$98.58).yes
outputCurrencyBRLAThe currency in which the mainAccount will receive funds. (in this case BRLA stable)yes
outputPaymentMethodINTERNALThe method by which the mainAccount will receive funds (as an internal balance).yes
inputThirdPartyfalseReserved field — send false. See Third Party Fields.yes
outputThirdPartyfalseReserved field — send false. It does not restrict the destination. See Third Party Fields.yes

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?inputCurrency=BRL&inputPaymentMethod=PIX&outputAmount=100&outputCurrency=BRLA&outputPaymentMethod=INTERNAL&inputThirdParty=false&outputThirdParty=false" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"inputCurrency": "BRL",
"inputPaymentMethod": "PIX",
"inputAmount": "100.2",
"outputCurrency": "BRLA",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "100",
"markupAmount": "0",
"markupCurrency": "",
"inputThirdParty": false,
"outputThirdParty": false,
"appliedFees": [
{
"type": "Markup Fee",
"description": "Total markup fees represented in the input currency.",
"amount": "0",
"currency": "BRL"
},
{
"type": "In Fee",
"description": "Fees due to input currency and input payment method.",
"amount": "0.2",
"currency": "BRL"
},
{
"type": "Conversion Fee",
"description": "Fees due to conversion from input currency to output currency.",
"amount": "0",
"currency": "BRL"
},
{
"type": "Out Fee",
"description": "Fees due to output currency and output payment method.",
"amount": "0",
"currency": "BRL"
},
{
"type": "Gas Fee",
"description": "Fees due to blockchain transaction costs.",
"amount": "0",
"currency": "BRL"
}
],
"basePrice": "1",
"pairName": "BRLBRLA"
}

Ticket - Closing the Order​

With the quote in hand, we will initiate the order closing process—referred to as "Ticket"—where the quote is finalized and the requested operation is executed, which in our case is a transfer to our main account.

FieldValueDescriptionRequired
quoteTokeneyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....The quoteToken obtained from the get quote endpoint.yes
ticketBlockchainOutputbeneficiaryWalletIdContains details regarding the ticket blockchain output.yes
└ beneficiaryWalletId00000000-0000-0000-0000-000000000000Here we set the ID of your main account as a zero id, which makes Avenia API link this id to your main account, who made the requestyes

HTTP POST Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets

Sample JSON Body​

Remember that here we pass a zeroed uuid because we are linking your main account to this deposit (who will receive the funds)

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "00000000-0000-0000-0000-000000000000"
}
}

cUrl Example​

curl -X POST "https://api.sandbox.avenia.io:10952/v2/account/tickets" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "00000000-0000-0000-0000-000000000000"
}
}

JSON Response​

Here, we can see that the brCode is received, which represents the PIX payment code. The ticket will remain in a pending state until the PIX payment is completed.

info

If you’ve already registered a webhook for the TICKET event, you will start receiving webhook notifications from this point onward.

{
"brCode": "00020126810014br.gov.bcb.pix01365c2c61a1-134b-4c34-958f-ea3122ac717f0219Avenia Ticket Payment5204000053039865406975.285802BR5917Avenia API Ltda6009Sao Paulo622905253Uu0qFigaAnwGdmmDJp3R9Yuz6304DE64",
"expiration": "2025-04-14T13:58:47.609482542Z",
"id": "b73767f7-1343-4176-9298-fffc85ea71a4"
}
info

In the sandbox environment, the PIX payment is simulated within a few seconds.

Verify status from Ticket​

info

An alternative to continuously checking the ticket history to track its current stage is to use webhooks instead.

Next, verify if the ticket status is PAID by checking the tickets by id endpoint.

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets/YOUR-TICKET-UUID-HERE

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/tickets/b73767f7-1343-4176-9298-fffc85ea71a4" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

info

Note: The status can be in: UNPAID PROCESSING PAID FAILED PARTIAL-FAILED

{
"ticket": {
"id": "b73767f7-1343-4176-9298-fffc85ea71a4",
"workspaceId": "22222222-2222-2222-2222-222222222222",
"userId": "11111111-1111-1111-1111-111111111111",
"status": "PAID",
"reason": "",
"failureReason": "",
"createdAt": "2025-04-22T14:24:02.038578Z",
"updatedAt": "2025-04-22T14:24:24.389526Z",
"expiresAt": "2025-04-23T14:24:02.036433Z",
"quote": {
"id": "763fb47b-6bc4-4abc-acb3-800139ca9772",
"ticketId": "0b695784-81de-4ba4-888a-947a5efe4f55",
"inputCurrency": "BRL",
"inputPaymentMethod": "PIX",
"inputAmount": "100.2",
"outputCurrency": "BRLA",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "100",
"markupCurrency": "",
"markupAmount": "0",
"sendMethod": "",
"inputThirdParty": false,
"outputThirdParty": false,
"basePrice": "1",
"appliedFees": [
{
"type": "Markup Fee",
"amount": "0",
"currency": "BRL",
"rebatable": false,
"description": "Total markup fees represented in the input currency."
},
{
"type": "In Fee",
"amount": "0.2",
"currency": "BRL",
"rebatable": true,
"description": "Fees due to input currency and input payment method."
},
{
"type": "Conversion Fee",
"amount": "0",
"currency": "BRL",
"rebatable": true,
"description": "Fees due to conversion from input currency to output currency."
},
{
"type": "Out Fee",
"amount": "0",
"currency": "BRL",
"rebatable": true,
"description": "Fees due to output currency and output payment method."
},
{
"type": "Gas Fee",
"amount": "0",
"currency": "BRL",
"rebatable": false,
"description": "Fees due to blockchain transaction costs."
}
],
"pairName": "BRLBRLA",
"outputBrCode": "",
"createdAt": "2025-04-22T14:24:01Z"
},
"rebate": {
"id": "ce260673-1590-4a0f-84c5-e2bf3bd97cf3",
"ticketId": "0b695784-81de-4ba4-888a-947a5efe4f55",
"amount": "0.1",
"currency": "BRLA",
"destinationWalletAddress": "0x0000000000000000000000000000000000000001"
},
"brazilianFiatSenderInfo": {
"id": "36428ccf-3be4-471c-a243-2635eea3e142",
"ticketId": "0b695784-81de-4ba4-888a-947a5efe4f55",
"name": "Example Company Ltda",
"taxId": "00000000000100",
"bankCode": "00000000",
"branchCode": "0001",
"accountNumber": "0000000000000000",
"accountType": "payment",
"endToEndId": "e00000000202504221424XXXXXXXXXXX"
},
"blockchainReceiverInfo": {
"id": "2734ee95-62d5-4bd2-a909-7e9322f59404",
"ticketId": "0b695784-81de-4ba4-888a-947a5efe4f55",
"walletAddress": "0x0000000000000000000000000000000000000002",
"walletChain": "INTERNAL",
"walletMemo": "",
"txHash": "0x0000000000000000000000000000000000000000000000000000000000000003"
},
"brlPixInputInfo": {
"id": "a5bfd2bb-784a-4989-a105-52da968de113",
"ticketId": "0b695784-81de-4ba4-888a-947a5efe4f55",
"referenceLabel": "xe1thXY2aBq2naewSPfn7Xhfr",
"additionalData": "Avenia Ticket Payment",
"brCode": "00020126810014br.gov.bcb.pix01365c2c61a1-134b-4c34-958f-ea3122ac717f0219Avenia Ticket Payment5204000053039865406100.205802BR5917Avenia API Ltda6009Sao Paulo62290525xe1thXY2aBq2naewSPfn7Xhfr63041FA5"
}
}
}

Checking subAccount balance​

Here, we’ll retrieve all current balances for your or main account.

HTTP Get Request​

https://api.sandbox.avenia.io:10952/v2/account/balances

Example Json Response​

{
"balances": {
"BRLA": "165.00000",
"USDC": "0",
"USDT": "0",
"USDM": "0"
}
}

Convert BRLA to USDC or USDT​

To decide where you want to transfer your BRLA to another stablecoin, simply set the outputCurrency to your chosen one—USDT or USDC.

warning

The quote is only valid for 15 seconds!

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate
FieldValueDescriptionRequired
inputCurrencyBRLAThe currency in which the mainAccount will receive funds. (in this case BRLA stable)yes
inputPaymentMethodINTERNALThe method by which the mainAccount will receive funds (as an internal balance).yes
outputAmount100The amount that the mainAccount receive (e.g., 98.58 = R$98.58).yes
outputCurrencyUSDTThe currency in which the mainAccount will receive funds. (in this case USDT stable)yes
outputPaymentMethodINTERNALThe method by which the mainAccount will receive funds (as an internal balance).yes
inputThirdPartyfalseReserved field — send false. See Third Party Fields.yes
outputThirdPartyfalseReserved field — send false. It does not restrict the destination. See Third Party Fields.yes
blockchainSendMethodPERMITDefines the blockchain transaction type. I this case "PERMIT"yes

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?inputCurrency=BRLA&inputPaymentMethod=INTERNAL&outputAmount=100&outputCurrency=USDT&outputPaymentMethod=INTERNAL&inputThirdParty=false&outputThirdParty=false&blockchainSendMethod=PERMIT" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"inputCurrency": "BRLA",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "582.446313",
"outputCurrency": "USDT",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "100",
"markupAmount": "0",
"markupCurrency": "",
"blockchainSendMethod": "PERMIT",
"inputThirdParty": false,
"outputThirdParty": false,
"appliedFees": [
{
"type": "Markup Fee",
"description": "Total markup fees represented in the input currency.",
"amount": "0",
"currency": "BRLA"
},
{
"type": "In Fee",
"description": "Fees due to input currency and input payment method.",
"amount": "0",
"currency": "BRLA"
},
{
"type": "Conversion Fee",
"description": "Fees due to conversion from input currency to output currency.",
"amount": "3.494677",
"currency": "BRLA"
},
{
"type": "Out Fee",
"description": "Fees due to output currency and output payment method.",
"amount": "0",
"currency": "BRLA"
},
{
"type": "Gas Fee",
"description": "Fees due to blockchain transaction costs.",
"amount": "0",
"currency": "BRLA"
}
],
"basePrice": "5.7895",
"pairName": "USDTBRLA"
}

Ticket - Closing the Order​

With the quote in hand, we will initiate the order closing process—referred to as "Ticket"—where the quote is finalized and the requested operation is executed, which in our case is a transfer to our main account.

FieldValueDescriptionRequired
quoteTokeneyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....The quoteToken obtained from the get quote endpoint.yes
ticketBlockchainOutputbeneficiaryWalletIdContains details regarding the ticket blockchain output.yes
└ beneficiaryWalletId00000000-0000-0000-0000-000000000000Here we set the ID of your main account as a zero id, which makes Avenia API link this id to your main account, who made the requestyes

HTTP POST Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets

Sample JSON Body​

Remember that here we pass a zeroed uuid because we are linking your main account to this deposit (who will receive the funds)

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "00000000-0000-0000-0000-000000000000"
}
}

cUrl Example​

curl -X POST "https://api.sandbox.avenia.io:10952/v2/account/tickets" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "00000000-0000-0000-0000-000000000000"
}
}

JSON Response​

info

If you’ve already registered a webhook for the TICKET event, you will start receiving webhook notifications from this point onward.

{
"id": "b73767f7-1343-4176-9298-fffc85ea71a4"
}

Verify status from Ticket​

info

An alternative to continuously checking the ticket history to track its current stage is to use webhooks instead.

Next, verify if the ticket status is PAID by checking the tickets by id endpoint.

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets/YOUR-TICKET-UUID-HERE

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/tickets/b73767f7-1343-4176-9298-fffc85ea71a4" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

info

Note: The status can be in: UNPAID PROCESSING PAID FAILED PARTIAL-FAILED

{
"ticket": {
"id": "b993375e-c819-4a63-85a5-2df6e90dd976",
"workspaceId": "33333333-3333-3333-3333-333333333333",
"userId": "44444444-4444-4444-4444-444444444444",
"status": "PAID",
"reason": "",
"failureReason": "",
"createdAt": "2025-04-22T14:52:07.171269Z",
"updatedAt": "2025-04-22T14:52:17.173258Z",
"expiresAt": "2025-04-22T14:57:07.169645Z",
"quote": {
"id": "7bd064bc-51de-4afa-b2dc-9fb33f6930b0",
"ticketId": "b993375e-c819-4a63-85a5-2df6e90dd976",
"inputCurrency": "BRLA",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "582.847867",
"outputCurrency": "USDT",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "100",
"markupCurrency": "",
"markupAmount": "0",
"sendMethod": "PERMIT",
"inputThirdParty": false,
"outputThirdParty": false,
"basePrice": "5.793499",
"appliedFees": [
{
"type": "Markup Fee",
"amount": "0",
"currency": "BRLA",
"rebatable": false,
"description": "Total markup fees represented in the input currency."
},
{
"type": "In Fee",
"amount": "0",
"currency": "BRLA",
"rebatable": true,
"description": "Fees due to input currency and input payment method."
},
{
"type": "Conversion Fee",
"amount": "3.497087",
"currency": "BRLA",
"rebatable": true,
"description": "Fees due to conversion from input currency to output currency."
},
{
"type": "Out Fee",
"amount": "0",
"currency": "BRLA",
"rebatable": true,
"description": "Fees due to output currency and output payment method."
},
{
"type": "Gas Fee",
"amount": "0",
"currency": "BRLA",
"rebatable": false,
"description": "Fees due to blockchain transaction costs."
}
],
"pairName": "USDTBRLA",
"outputBrCode": "",
"createdAt": "2025-04-22T14:52:06Z"
},
"blockchainSenderInfo": {
"id": "31cea8c0-f998-41ed-ba51-4ed3412e20c0",
"ticketId": "b993375e-c819-4a63-85a5-2df6e90dd976",
"walletAddress": "0x0000000000000000000000000000000000000003",
"txHash": "0x0000000000000000000000000000000000000000000000000000000000000004"
},
"blockchainReceiverInfo": {
"id": "8fe21974-ebee-4e7c-9058-abc39b1881a9",
"ticketId": "b993375e-c819-4a63-85a5-2df6e90dd976",
"walletAddress": "0x0000000000000000000000000000000000000003",
"walletChain": "INTERNAL",
"walletMemo": "",
"txHash": "0x0000000000000000000000000000000000000000000000000000000000000004"
},
"blockchainInputInfo": {
"id": "7ae3719a-8267-4a54-a8f1-659a6e62f3ea",
"ticketId": "b993375e-c819-4a63-85a5-2df6e90dd976",
"r": "",
"s": "",
"v": 0,
"nonce": 0,
"deadline": 0,
"personalSignature": "",
"personalSignatureDeadline": 0
}
}
}

Transfer Tokens to Subaccounts​

To send funds to your SubAccount, the process is very simple—when creating the ticket, just provide your SubAccount ID as the recipient of the tokens.

warning

The quote is only valid for 15 seconds!

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate
FieldValueDescriptionRequired
inputCurrencyUSDTThe currency in which the mainAccount will receive funds. (in this case USDT stable)yes
inputPaymentMethodINTERNALThe method by which the mainAccount will receive funds (as an internal balance).yes
outputAmount100The amount that the mainAccount receive (e.g., 98.58 = R$98.58).yes
outputCurrencyUSDTThe currency in which the mainAccount will receive funds. (in this case USDT stable)yes
outputPaymentMethodINTERNALThe method by which the mainAccount will receive funds (as an internal balance).yes
inputThirdPartyfalseReserved field — send false. See Third Party Fields.yes
outputThirdPartyfalseReserved field — send false. It does not restrict the destination. See Third Party Fields.yes
blockchainSendMethodPERMITDefines the blockchain transaction type. I this case "PERMIT"yes

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?inputCurrency=USDT&inputPaymentMethod=INTERNAL&outputAmount=100&outputCurrency=USDT&outputPaymentMethod=INTERNAL&inputThirdParty=false&outputThirdParty=false&blockchainSendMethod=PERMIT" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"inputCurrency": "USDT",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "100",
"outputCurrency": "USDT",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "100",
"markupAmount": "0",
"markupCurrency": "",
"blockchainSendMethod": "PERMIT",
"inputThirdParty": false,
"outputThirdParty": false,
"appliedFees": [
{
"type": "Markup Fee",
"description": "Total markup fees represented in the input currency.",
"amount": "0",
"currency": "USDT"
},
{
"type": "In Fee",
"description": "Fees due to input currency and input payment method.",
"amount": "0",
"currency": "USDT"
},
{
"type": "Conversion Fee",
"description": "Fees due to conversion from input currency to output currency.",
"amount": "0",
"currency": "USDT"
},
{
"type": "Out Fee",
"description": "Fees due to output currency and output payment method.",
"amount": "0",
"currency": "USDT"
},
{
"type": "Gas Fee",
"description": "Fees due to blockchain transaction costs.",
"amount": "0",
"currency": "USDT"
}
],
"basePrice": "1",
"pairName": "USDTUSDT"
}

Ticket - Closing the Order​

With the quote in hand, we will initiate the order closing process—referred to as "Ticket"—where the quote is finalized and the requested operation is executed, which in our case is a transfer to our sub account.

FieldValueDescriptionRequired
quoteTokeneyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....The quoteToken obtained from the get quote endpoint.yes
ticketBlockchainOutputbeneficiaryWalletIdContains details regarding the ticket blockchain output.yes
└ beneficiaryWalletId1ee0a663-922b-4389-9f84-074ccff7085dHere we set the ID of your sub accountyes

HTTP POST Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets

Sample JSON Body​

Remember to provide the ID of the SubAccount you want to transfer the balances to.

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "1ee0a663-922b-4389-9f84-074ccff7085d"
}
}

JSON Response​

info

If you’ve already registered a webhook for the TICKET event, you will start receiving webhook notifications from this point onward.

{
"id": "b73767f7-1343-4176-9298-fffc85ea71a4"
}

Checking subAccount balance​

Here, we’ll retrieve all current balances for your or subaccount.

info

Keep in mind that the operation is still being performed by the subaccount, so it’s also necessary to include the subAccountId parameter here.

HTTP Get Request​

https://api.sandbox.avenia.io:10952/v2/account/balances?subAccountId=YOUR-SUBACCOUNT-ID-HERE

Example Json Response​

{
"balances": {
"BRLA": "0",
"USDC": "0",
"USDT": "100",
"USDM": "0"
}
}

Send tokens from Subaccounts to External Wallets​

Before starting the process of sending tokens to external wallets, we first need to identify those external wallets. That’s where the topic of Beneficiary Wallets

Create Beneficiary Wallet​

Registering a new beneficiary wallet is straightforward. Let’s look at the required fields:

Fields​

FieldTypeRequiredDescription
aliasstringYesA custom name for the wallet to help identify it.
descriptionstringNoA brief description of the wallet.
walletAddressstringYesThe blockchain wallet address.
walletChainstringYesThe blockchain network of the wallet (e.g., POLYGON, CELO, ETHEREUM, GNOSIS, MOONBEAM and TRON).
walletMemostringNoMemo for the wallet.
info

To perform this operation for a sub-account, pass the subAccountId field as a parameter to this endpoint.

HTTP Post Request​

https://api.sandbox.avenia.io:10952/v2/account/beneficiaries/wallets?subAccountId=SUB-ACCOUNT-ID-HERE

Sample JSON Body​

{
"alias": "ExampleAlias",
"description": "Example description",
"walletAddress": "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"walletChain": "POLYGON",
"walletMemo": "memooo"
}

cUrl Example​

curl -X POST "https://api.sandbox.avenia.io:10952/v2/account/beneficiaries/wallets?subAccountId=SUB-ACCOUNT-ID-HERE" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d '{
"alias": "ExampleAlias",
"description": "Example description",
"walletAddress": "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"walletChain": "POLYGON",
"walletMemo": "memooo"
}'

JSON Response​

{
"id": "76971925-a1ca-423f-badf-0b3f2b03c51c"
}

Sending Tokens to a Beneficiary Wallet​

Now that everything is ready and the beneficiary wallet has been registered, we just need to generate the quote.

info

Remember, the outputPaymentMethod must match the chain of the registered wallet.

warning

The quote is only valid for 15 seconds!

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?subAccountId=SUB-ACCOUNT-ID-HERE
FieldValueDescriptionRequired
inputCurrencyUSDTThe currency in which the mainAccount will receive funds. (in this case USDT stable)yes
inputPaymentMethodINTERNALThe method by which the mainAccount will receive funds (as an internal balance).yes
outputAmount50The amount that the mainAccount receive (e.g., 98.58 = R$98.58).yes
outputCurrencyUSDTThe currency in which the mainAccount will receive funds. (in this case USDT stable)yes
outputPaymentMethodPOLYGONThe method by which the external wallet will receive funds (must be the same as the beneficiary wallet registered chain).yes
inputThirdPartyfalseReserved field — send false. See Third Party Fields.yes
outputThirdPartyfalseReserved field — send false. It does not restrict the destination. See Third Party Fields.yes
blockchainSendMethodPERMITDefines the blockchain transaction type. I this case "PERMIT"yes
info

To perform this operation for a subAccount, pass the subAccountId field as a parameter to this endpoint.

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?inputCurrency=USDT&inputPaymentMethod=INTERNAL&outputAmount=100&outputCurrency=USDT&outputPaymentMethod=POLYGON&inputThirdParty=false&outputThirdParty=false&blockchainSendMethod=PERMIT&subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"inputCurrency": "USDT",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "100.050089",
"outputCurrency": "USDT",
"outputPaymentMethod": "POLYGON",
"outputAmount": "100",
"markupAmount": "0",
"markupCurrency": "",
"blockchainSendMethod": "PERMIT",
"inputThirdParty": false,
"outputThirdParty": false,
"appliedFees": [
{
"type": "Markup Fee",
"description": "Total markup fees represented in the input currency.",
"amount": "0",
"currency": "USDT"
},
{
"type": "In Fee",
"description": "Fees due to input currency and input payment method.",
"amount": "0",
"currency": "USDT"
},
{
"type": "Conversion Fee",
"description": "Fees due to conversion from input currency to output currency.",
"amount": "0",
"currency": "USDT"
},
{
"type": "Out Fee",
"description": "Fees due to output currency and output payment method.",
"amount": "0.050025",
"currency": "USDT"
},
{
"type": "Gas Fee",
"description": "Fees due to blockchain transaction costs.",
"amount": "0.000063",
"currency": "USDT"
}
],
"basePrice": "1",
"pairName": "USDTUSDT"
}

Ticket - Closing the Order​

With the quote in hand, we will initiate the order closing process—referred to as "Ticket"—where the quote is finalized and the requested operation is executed, which in our case is a transfer to our sub account.

FieldValueDescriptionRequired
quoteTokeneyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....The quoteToken obtained from the get quote endpoint.yes
ticketBlockchainOutputbeneficiaryWalletIdContains details regarding the ticket blockchain output.yes
└ beneficiaryWalletId1ee0a663-922b-4389-9f84-074ccff7085dHere we set the ID of your beneficiary wallet registredyes

HTTP POST Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets

Sample JSON Body​

Remember to provide the ID of the SubAccount you want to transfer the balances to.

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "76971925-a1ca-423f-badf-0b3f2b03c51c"
}
}

JSON Response​

info

If you’ve already registered a webhook for the TICKET event, you will start receiving webhook notifications from this point onward.

{
"id": "b73767f7-1343-4176-9298-fffc85ea71a4"
}