Skip to main content

PIX2STABLE - STABLE2PIX

You have received your credentials, and now we’ll walk through a very common use case: PIX to STABLE (e.g., BRLA, USDC, USDM...) and the return flow: STABLE to PIX. An important note: while this use case is demonstrated using subaccounts, it can also be applied to the main account only.

What Will We Cover Here?

  • Login
  • KYC
  • Subaccount creation
    • Subaccount KYC
  • About Webhooks
  • PIX IN – Sending balances to your subaccounts
    • Viewing balances in your subaccounts
  • PIX OUT – Withdrawing funds from a subaccount
    • Using a brCode
    • Using a PIX key

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:

Send funds to subAccount​

We’ll simulate funding a SubAccount (your client) with US$165.00 via a PIX conversion from Brazilian Reais to a dollar stablecoin.

To do this, we first need to generate a QUOTE, which represents the exact amount to be transferred to the Main Account.

warning

The quote is only valid for 15 seconds!

Here, to operate on behalf of a SubAccount, you need to include the subAccountId parameter—this ensures that all operations are performed within the SubAccount rather than the Main Account.

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?subAccountId=YOUR-SUBACCOUNT-ID-HERE
FieldValueDescriptionRequired
inputCurrencyBRLThe currency in which the subAccount (in this case, Brazilian Reais).yes
inputPaymentMethodPIXThe payment method in this case PIX method.yes
outputAmount165The amount that the subAccount receive (e.g., 98.58 = R$98.58).yes
outputCurrencyUSDMThe currency in which the subAccount will receive funds. (in this case USDM stable)yes
outputPaymentMethodINTERNALThe method by which the subAccount 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=165&outputCurrency=USDM&outputPaymentMethod=INTERNAL&inputThirdParty=false&outputThirdParty=false&subAccountId=YOUR-SUBACCOUNT-ID-HERE" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"inputCurrency": "BRL",
"inputPaymentMethod": "PIX",
"inputAmount": "975.11",
"outputCurrency": "USDM",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "165",
"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": "8.77599",
"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": "5.855378",
"pairName": "USDMBRL"
}

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 subAccount.

Here, to operate on behalf of a SubAccount, you need to include the subAccountId parameter—this ensures that all operations are performed within the SubAccount rather than the 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 subAccount as a zero id, which makes Avenia API link this id to your subAccount, who made the requestyes

HTTP POST Request​

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

Sample JSON Body​

Remember that here we pass a zeroed uuid because we are linking your subAccount 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?subAccountId=YOUR-SUBACCOUNT-ID-HERE" \
-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.

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/tickets/YOUR-TICKET-UUID-HERE?subAccountId=YOUR-SUBACCOUNT-ID-HERE

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/tickets/b73767f7-1343-4176-9298-fffc85ea71a4?subAccountId=YOUR-SUBACCOUNT-ID-HERE" \
-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",
"externalId": "",
"workspaceId": "22222222-2222-2222-2222-222222222222",
"userId": "11111111-1111-1111-1111-111111111111",
"status": "PAID",
"reason": "",
"failureReason": "",
"createdAt": "2025-04-14T13:53:47.618039Z",
"updatedAt": "2025-04-14T13:54:10.516442Z",
"expiresAt": "2025-04-14T13:58:47.609482Z",
"quote": {
"id": "6c2f3fcf-cb64-4fb5-96c4-51597b764bfd",
"ticketId": "b73767f7-1343-4176-9298-fffc85ea71a4",
"inputCurrency": "BRL",
"inputPaymentMethod": "PIX",
"inputAmount": "975.28",
"outputCurrency": "USDM",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "165",
"markupCurrency": "",
"markupAmount": "0",
"sendMethod": "",
"inputThirdParty": false,
"outputThirdParty": false,
"basePrice": "5.856378",
"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": "8.77752",
"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": "USDMBRL",
"outputBrCode": "",
"createdAt": "2025-04-14T13:53:47Z"
},
"rebate": {
"id": "004992b7-4974-4960-8d0f-78c1ccf0be8a",
"ticketId": "b73767f7-1343-4176-9298-fffc85ea71a4",
"amount": "4.48876",
"currency": "BRLA",
"destinationWalletAddress": "0x0000000000000000000000000000000000000001"
},
"brazilianFiatSenderInfo": {
"id": "b8c67775-5395-485e-ac54-9961332eed39",
"ticketId": "b73767f7-1343-4176-9298-fffc85ea71a4",
"name": "Example Company Ltda",
"taxId": "00000000000100",
"bankCode": "00000000",
"branchCode": "0001",
"accountNumber": "0000000000000000",
"accountType": "payment",
"endToEndId": "e00000000202504141353XXXXXXXXXXX"
},
"blockchainReceiverInfo": {
"id": "b789bf87-3b38-49de-9558-c59a3a043ab7",
"ticketId": "b73767f7-1343-4176-9298-fffc85ea71a4",
"walletAddress": "0x0000000000000000000000000000000000000002",
"walletChain": "INTERNAL",
"walletMemo": "",
"txHash": "0x0000000000000000000000000000000000000000000000000000000000000005"
},
"brlPixInputInfo": {
"id": "01115639-3e21-4218-a009-256071d6502f",
"ticketId": "b73767f7-1343-4176-9298-fffc85ea71a4",
"referenceLabel": "3Uu0qFigaAnwGdmmDJp3R9Yuz",
"additionalData": "Avenia Ticket Payment",
"brCode": "00020126810014br.gov.bcb.pix01365c2c61a1-134b-4c34-958f-ea3122ac717f0219Avenia Ticket Payment5204000053039865406975.285802BR5917Avenia API Ltda6009Sao Paulo622905253Uu0qFigaAnwGdmmDJp3R9Yuz6304DE64"
}
}
}

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": "0",
"USDM": "165.00000"
}
}

Subaccount Performing a Withdrawal - BrCode​

Quote​

Let’s prepare the withdrawal through the subaccount.

Generate a quote to determine the exact amount to be transferred.

info

Since the subaccount will be the one doing the ticketing (closing the order), it must be passed on to all the endpoints in this section!

warning

The quote is only valid for 15 seconds!

info

Note: We have omitted the quoteToken for better readability, remembering that it is a JWT.

info

Notice that the outputAmount reflects the brCode value, while the inputAmount includes fees.

The fee values may vary depending on the operation.

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d
FieldValueDescription
subAccountId1ee0a663-922b-4389-9f84-074ccff7085dID of the subaccount paying the brCode.
inputCurrencyUSDMCurrency used by the subaccount for payment (Brazilian Reais).
inputPaymentMethodINTERNALPayment method (subaccount’s internal balance).
outputCurrencyBRLCurrency in which the brCode will be paid (BRL only).
outputPaymentMethodPIX-BRCODEPayment method for the payout (via PIX brCode).
inputThirdPartyfalseReserved field — send false. See Third Party Fields.
outputThirdPartyfalseReserved field — send false. It does not restrict the destination. See Third Party Fields.
blockchainSendMethodPERMITSpecifies that the transfer is automatically handled by Avenia API.
outputBrCode00020101021226580014br.gov.bcb.pix0136123e4567-e89b-12d3-a456-4266141740005204000053039865802BR5920Example Company Ltda6009SAO PAULO62070503***6304ABCDThe brCode that the user will pay.
warning

Some BrCodes do not have a specified value. In such cases, provide either the inputAmount or the outputAmount—only one amount is allowed, so do not include both.

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d&inputCurrency=USDM&inputPaymentMethod=INTERNAL&outputCurrency=BRL&outputPaymentMethod=PIX-BRCODE&inputThirdParty=false&outputThirdParty=false&blockchainSendMethod=PERMIT&outputBrCode=00020101021226580014br.gov.bcb.pix0136123e4567-e89b-12d3-a456-4266141740005204000053039865802BR5920Example%20Company%20Ltda6009SAO%20PAULO62070503***6304ABCD" \\
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"inputCurrency": "BRLA",
"inputCurrency": "USDM",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "8.687072",
"outputCurrency": "BRL",
"outputPaymentMethod": "PIX-BRCODE",
"outputAmount": "50",
"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": "USDM"
},
{
"type": "In Fee",
"description": "Fees due to input currency and input payment method.",
"amount": "0",
"currency": "USDM"
},
{
"type": "Conversion Fee",
"description": "Fees due to conversion from input currency to output currency.",
"amount": "0",
"currency": "USDM"
},
{
"type": "Out Fee",
"description": "Fees due to output currency and output payment method.",
"amount": "0.170334",
"currency": "USDM"
},
{
"type": "Gas Fee",
"description": "Fees due to blockchain transaction costs.",
"amount": "0",
"currency": "USDM"
}
],
"basePrice": "5.870793",
"pairName": "USDMBRL"
}

Ticket - Closing the Order​

With the quote in hand, initiate the ticket operation to finalize the order. The subaccount will use the quote to execute the payment.

HTTP POST Request​


https://api.sandbox.avenia.io:10952/v2/account/tickets?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d

Sample JSON Body​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken...."
}

cUrl Example​

curl -X POST "https://api.sandbox.avenia.io:10952/v2/account/tickets?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d" \\
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \\
-H "Content-Type: application/json" \\
-d '{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken...."
}'

JSON Response​

{
"id": "a14d6b53-e573-4e68-b34a-2a1b717eb448"
}

Verify status from Ticket​

To verify the ticket status, use the following GET endpoint:

info

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

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets/a14d6b53-e573-4e68-b34a-2a1b717eb448?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/tickets/a14d6b53-e573-4e68-b34a-2a1b717eb448?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"ticket": {
"id": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"externalId": "",
"workspaceId": "22222222-2222-2222-2222-222222222222",
"userId": "11111111-1111-1111-1111-111111111111",
"status": "PAID",
"reason": "",
"failureReason": "",
"createdAt": "2025-04-14T17:00:32.934368Z",
"updatedAt": "2025-04-14T17:01:05.452338Z",
"expiresAt": "2025-04-14T17:05:32.93273Z",
"quote": {
"id": "cf584823-ff5f-4cb5-b050-88991873d856",
"ticketId": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"inputCurrency": "USDM",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "8.692995",
"outputCurrency": "BRL",
"outputPaymentMethod": "PIX-BRCODE",
"outputAmount": "50",
"markupCurrency": "",
"markupAmount": "0",
"sendMethod": "PERMIT",
"inputThirdParty": false,
"outputThirdParty": false,
"basePrice": "5.866793",
"appliedFees": [
{
"type": "Markup Fee",
"amount": "0",
"currency": "USDM",
"rebatable": false,
"description": "Total markup fees represented in the input currency."
},
{
"type": "In Fee",
"amount": "0",
"currency": "USDM",
"rebatable": true,
"description": "Fees due to input currency and input payment method."
},
{
"type": "Conversion Fee",
"amount": "0",
"currency": "USDM",
"rebatable": true,
"description": "Fees due to conversion from input currency to output currency."
},
{
"type": "Out Fee",
"amount": "0.17045",
"currency": "USDM",
"rebatable": true,
"description": "Fees due to output currency and output payment method."
},
{
"type": "Gas Fee",
"amount": "0",
"currency": "USDM",
"rebatable": false,
"description": "Fees due to blockchain transaction costs."
}
],
"pairName": "USDMBRL",
"outputBrCode": "00020126740014br.gov.bcb.pix0136d5f144f6-a81c-4dc4-a922-0d8a999a580c0212Avenia Deposit5204000053039865802BR5917Avenia API Ltda6009Sao Paulo62100506000003630474CD",
"createdAt": "2025-04-14T17:00:32Z"
},
"rebate": {
"id": "c5395251-6e09-42c0-9c65-20641704f961",
"ticketId": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"amount": "0.49825",
"currency": "BRLA",
"destinationWalletAddress": "0x0000000000000000000000000000000000000001"
},
"brazilianFiatReceiverInfo": {
"id": "0f222399-5999-4963-a678-bf37cb4b586d",
"ticketId": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"taxId": "00.000.000/0001-00",
"userName": "Example Company Ltda",
"bankCode": "00020126740014br.gov.bcb.pix0136d5f144f6-a81c-4dc4-a922-0d8a999a580c0212Avenia Deposit5204000053039865802BR5917Avenia API Ltda6009Sao Paulo62100506000003630474CD",
"brCode": "00020126740014br.gov.bcb.pix0136d5f144f6-a81c-4dc4-a922-0d8a999a580c0212Avenia Deposit5204000053039865802BR5917Avenia API Ltda6009Sao Paulo62100506000003630474CD",
"endToEndId": "e00000000202504141700XXXXXXXXXXX"
},
"blockchainSenderInfo": {
"id": "9ac928d2-dba1-43c9-a338-faf26989f486",
"ticketId": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"walletAddress": "0x0000000000000000000000000000000000000002",
"txHash": "0x0000000000000000000000000000000000000000000000000000000000000006"
},
"brlPixOutputInfo": {
"id": "147de45c-3547-4f7f-be5f-50055f1aa5ca",
"ticketId": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"pixMessage": "",
"senderAccountBankName": "Example Bank",
"senderAccountNumber": "0000000000000000"
},
"blockchainInputInfo": {
"id": "e492feb0-b90f-4884-9ac7-7c789ddb37a2",
"ticketId": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"r": "",
"s": "",
"v": 0,
"nonce": 0,
"deadline": 0,
"personalSignature": "",
"personalSignatureDeadline": 0
}
}
}

Subaccount Performing a Withdrawal - PixKey​

Let’s go through the process of withdrawing BRL from your subaccount using a PIX key (e.g., CPF, RANDOM, phone number, etc.).

Quote​

In the following steps, the operation is still performed through the subaccount, so including the subAccountId parameter is mandatory. Given this, your quote request must include the following fields:

HTTP Get Request​

https://api.sandbox.avenia.io:10952/v2/account/quote/fixed-rate?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d
FieldValueDescription
subAccountId1ee0a663-922b-4389-9f84-074ccff7085dID of the subaccount paying the brCode.
inputCurrencyUSDMCurrency used by the subaccount for payment (Brazilian Reais).
inputPaymentMethodINTERNALPayment method (subaccount’s internal balance).
outputCurrencyBRLCurrency in which the brCode will be paid (BRL only).
outputPaymentMethodPIXPayment method for the payout (via PIX brCode).
inputThirdPartyfalseReserved field — send false. See Third Party Fields.
outputThirdPartyfalseReserved field — send false. It does not restrict the destination. See Third Party Fields.
blockchainSendMethodPERMITSpecifies that the transfer is automatically handled by Avenia API.

cUrl Example​

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

JSON Response​

{
"quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.quoteToken....",
"id": "c7f1e168-2989-45c7-a0be-de8371ab0dcc",
"inputCurrency": "USDM",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "8.550804",
"outputCurrency": "BRL",
"outputPaymentMethod": "PIX",
"outputAmount": "50",
"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": "USDM"
},
{
"type": "In Fee",
"description": "Fees due to input currency and input payment method.",
"amount": "0",
"currency": "USDM"
},
{
"type": "Conversion Fee",
"description": "Fees due to conversion from input currency to output currency.",
"amount": "0",
"currency": "USDM"
},
{
"type": "Out Fee",
"description": "Fees due to output currency and output payment method.",
"amount": "0.034066",
"currency": "USDM"
},
{
"type": "Gas Fee",
"description": "Fees due to blockchain transaction costs.",
"amount": "0",
"currency": "USDM"
}
],
"basePrice": "5.870793",
"pairName": "USDMBRL"
}

Ticket​

Now moving forward to the withdrawal step directly from the subaccount, we’ll follow the same principle: the subAccountId must be included as a parameter in the request.

Here, there are two important options: you can either specify a pixKey (such as CPF, email, CNPJ, etc.) or provide the full bank account details.

Full Bank Account Details​

FieldDescription
userNameFull name of the bank account holder.
bankCodeCode identifying the bank (e.g., 260 for NuBank).
branchCodeBranch number of the bank where the account is held.
accountNumberBank account number.
accountTypeType of the bank account. Allowed values: checking, payment, savings, salary.
``taxId`Brazilian ID - CPF or CNPJ

Just PIX Key​

FieldDescription
pixKeyUnique PIX key associated with the account.
warning

Remember to provide only one of the two options: either the pixKey or all bank account fields — not both.

Making the payment using a pixKey​

HTTP Post Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets?subAccountId=55555555-5555-5555-5555-555555555555

Sample JSON Body​

{
"quoteToken": "",
"ticketBrlPixOutput": {
"pixKey": "123e4567-e89b-12d3-a456-426614174000"
}
}

JSON Response​

And as a response, you will receive the ID of the created ticket. If a webhook for this specific ticket is already registered, it will also be triggered.

{
"id": "55ea4ebf-60fb-4c47-8a97-00f7659f4762"
}

Verify status from Ticket​

To verify the ticket status, use the following GET endpoint:

info

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

HTTP GET Request​

https://api.sandbox.avenia.io:10952/v2/account/tickets/a14d6b53-e573-4e68-b34a-2a1b717eb448?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d

cUrl Example​

curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/tickets/55ea4ebf-60fb-4c47-8a97-00f7659f4762?subAccountId=1ee0a663-922b-4389-9f84-074ccff7085d" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

JSON Response​

{
"ticket": {
"id": "55ea4ebf-60fb-4c47-8a97-00f7659f4762",
"externalId": "",
"workspaceId": "22222222-2222-2222-2222-222222222222",
"userId": "55555555-5555-5555-5555-555555555555",
"status": "PAID",
"reason": "",
"failureReason": "",
"createdAt": "2025-04-14T19:01:09.173483Z",
"updatedAt": "2025-04-14T19:01:13.62169Z",
"expiresAt": "2025-04-14T19:06:09.173221Z",
"quote": {
"id": "5716deac-018d-4adb-ab3c-f845fcf886df",
"ticketId": "55ea4ebf-60fb-4c47-8a97-00f7659f4762",
"inputCurrency": "USDM",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "8.547892",
"outputCurrency": "BRL",
"outputPaymentMethod": "PIX",
"outputAmount": "50",
"markupCurrency": "",
"markupAmount": "0",
"sendMethod": "PERMIT",
"inputThirdParty": false,
"outputThirdParty": false,
"basePrice": "5.872793",
"appliedFees": [
{
"type": "Markup Fee",
"amount": "0",
"currency": "USDM",
"rebatable": false,
"description": "Total markup fees represented in the input currency."
},
{
"type": "In Fee",
"amount": "0",
"currency": "USDM",
"rebatable": true,
"description": "Fees due to input currency and input payment method."
},
{
"type": "Conversion Fee",
"amount": "0",
"currency": "USDM",
"rebatable": true,
"description": "Fees due to conversion from input currency to output currency."
},
{
"type": "Out Fee",
"amount": "0.034055",
"currency": "USDM",
"rebatable": true,
"description": "Fees due to output currency and output payment method."
},
{
"type": "Gas Fee",
"amount": "0",
"currency": "USDM",
"rebatable": false,
"description": "Fees due to blockchain transaction costs."
}
],
"pairName": "USDMBRL",
"outputBrCode": "",
"createdAt": "2025-04-14T19:01:08Z"
},
"rebate": {
"id": "830900fc-739e-42ca-a10b-156260098f97",
"ticketId": "55ea4ebf-60fb-4c47-8a97-00f7659f4762",
"amount": "0.099629",
"currency": "BRLA",
"destinationWalletAddress": "0x0000000000000000000000000000000000000001"
},
"brazilianFiatReceiverInfo": {
"id": "ccc7e955-5f27-46ba-8969-7c1e214dd097",
"ticketId": "55ea4ebf-60fb-4c47-8a97-00f7659f4762",
"pixKey": "123e4567-e89b-12d3-a456-426614174000",
"endToEndId": ""
},
"blockchainSenderInfo": {
"id": "24ed8a42-9f33-4f18-b205-d503d37ede18",
"ticketId": "55ea4ebf-60fb-4c47-8a97-00f7659f4762",
"walletAddress": "0x0000000000000000000000000000000000000004",
"txHash": ""
},
"brlPixOutputInfo": {
"id": "2bf0ef60-02ec-4760-9087-d7eb75f8ee22",
"ticketId": "55ea4ebf-60fb-4c47-8a97-00f7659f4762",
"pixMessage": "",
"senderAccountBankName": "Example Bank",
"senderAccountNumber": "0000000000000000"
},
"blockchainInputInfo": {
"id": "dc1dddff-54a0-4f24-b294-27f9674139c6",
"ticketId": "55ea4ebf-60fb-4c47-8a97-00f7659f4762",
"r": "",
"s": "",
"v": 0,
"nonce": 0,
"deadline": 0,
"personalSignature": "",
"personalSignatureDeadline": 0
}
}
}

Reversals​

Let’s take a closer look at what happens when there’s a response to a sent Pix. It’s also good to remember that to get real-time insight into what’s happening, you should register and activate your webhooks.

When a return of funds is detected, a new ticket will be created. The inputAmount of this new ticket will reflect the amount returned by the customer. Consequently, the outputAmount will be set at the moment the new ticket is generated — and that value will be credited back to your account in Avenia's, specifically to the Avenia Account that generated the refunded ticket.

A Ticket Event webhook will be triggered, just like with any new ticket. Pay attention to the reason field — it will contain a message linking both operations (indicating that it was a refund). For example:

Pay out reversed by customer. Original ticket id UUID-OF-THE-ORIGINAL-TICKET.