Start Here
This page is the shortest path from zero to a working Avenia integration. Read it once, then follow Authentication and Your First Operation in the sandbox.
Environments
Sandbox and production are separate environments. Each one has its own account, its own API keys and its own MFA setup: a key created in sandbox does not work in production.
| Environment | API base URL | Dashboard |
|---|---|---|
| Sandbox | https://api.sandbox.avenia.io:10952 | https://app.sandbox.avenia.io/ |
| Production | https://api.avenia.io:8443 | https://app.avenia.io/ |
Every endpoint in this guide starts with /v2/, for example https://api.sandbox.avenia.io:10952/v2/account/account-info. Examples use the sandbox URL.
In sandbox no real money moves: PIX deposits up to R$1,000 are paid automatically by a simulated payer, and other rails have their own simulators (see Sandbox Usecases).
How an integration works
- Authenticate. Sign each request with an API key (recommended for servers) or send a JWT from the login flow. See Authentication.
- Set up who operates. Your main account can operate for itself or on behalf of sub-accounts, one per end customer. Each account needs the KYC (individuals) or KYB (companies) level required by the currencies it uses.
- Quote.
GET /v2/account/quote/fixed-rateprices the operation and returns aquoteToken. - Create a ticket.
POST /v2/account/tickets/with thatquoteTokenexecutes the operation and returns what to pay (a BR Code, deposit instructions, an on-chain address) or starts the payout. - Follow it to the end. Receive webhooks or read
GET /v2/account/tickets/{id}until the ticket reaches a final status.
Rules that save you a support ticket
- A quote token lives 15 seconds and creates at most one ticket. Create the ticket right after the quote. Within those 15 seconds, re-sending the same token returns
400 cannot reuse quote token, which means the first request did create a ticket. After 15 seconds the same request returnsquoteToken is invalidwhether or not a ticket was created — so after a timeout, never decide from that error: look the ticket up byexternalId. See Idempotency and Retries. externalIdis your reference, not an idempotency key. It is free text (up to 68 characters) and Avenia doesn't enforce uniqueness. Make it unique on your side and use it to find a ticket after a timeout.- Every quote sends
inputThirdPartyandoutputThirdParty. Leaving them out returns400 InvalidFieldError: InputThirdParty is invalid. Blockchain inputs also needblockchainSendMethod(PERMITorTRANSFER). - Send exactly one of
inputAmountoroutputAmount. - When you act for a sub-account, send the same
subAccountIdon the quote and on the ticket. If the quote and the ticket name different accounts — including one withsubAccountIdand one without — the ticket is refused with400 InvalidFieldError: quoteToken is invalid, the same error as an expired token. On the ticket,subAccountIdis a query parameter:POST /v2/account/tickets/?subAccountId=..., not a field in the body. TICKET-COMPLETEis sent for every final outcome, success or failure. Read the ticketstatusbefore marking anything as done. The exception isCANCELED: canceling anUNPAIDticket yourself sends no webhook.- COP, ARS and MXN only buy and pay out from USDC. See Supported Operations.
Where to go next
| You want to | Read |
|---|---|
Sign requests and fix a 401 | Authentication |
| Run a full quote → ticket in sandbox | Your First Operation |
| See every supported currency pair and its fields | Available Combinations |
Understand ticket statuses, failures and failureReason | Ticket Lifecycle and Failures |
| Handle errors and rate limits | Errors and Rate Limits |
| Operate for sub-accounts and move funds between accounts | Accounts and Sub-accounts |
| Understand fees, BRLA balances and reconciliation | Fees, Balances and Reconciliation |
| Receive status updates | Webhooks in Practice |