Full integration guide
The complete path — from API key to a settled PIX payout, covering subaccounts, KYC, wallets, on-ramp and off-ramp.
This is the golden path. Follow it top to bottom once and you'll have a working integration: create a subaccount for your user, verify them, give them a wallet, fund it, pay out to PIX, and reconcile. Each step explains what you call, why, and what comes back.
Identity model. A
subAccountIdis the single identifier for an end-user across KYC, wallets, deposits and payouts. Create one first — every other call references it.
Prerequisites
- An API key from the Hodle team. Production keys start with
hodle_live_, sandbox withhodle_test_. - A server that can receive webhooks (recommended) — or you can poll.
- Test against the sandbox first:
https://sandbox-api.hodle.com.br.
Every request carries your key:
Authorization: Bearer YOUR_API_KEYStep 1 — Create a subaccount
A subaccount is the segregated account for one of your end-users (or a business unit). It's the identity everything else hangs off.
curl -X POST https://api.hodle.com.br/api/subaccount \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "João da Silva" }'{ "success": true, "data": { "subAccountId": "5b9f...e21a" } }Store subAccountId against your user. List or fetch them any time:
curl https://api.hodle.com.br/api/subaccount -H "Authorization: Bearer $API_KEY" # list
curl https://api.hodle.com.br/api/subaccount/5b9f...e21a -H "Authorization: Bearer $API_KEY" # oneStep 2 — Run KYC
Money can't move for a subaccount until it's APPROVED. Submit the person's data plus two
uploaded image ids (selfie + document).
curl -X POST https://api.hodle.com.br/api/kyc \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subAccountId": "5b9f...e21a",
"fullName": "João da Silva",
"dateOfBirth": "1990-05-21",
"taxIdNumber": "12345678901",
"countryOfTaxId": "BRA",
"email": "joao@example.com",
"country": "BRA",
"state": "SP",
"city": "São Paulo",
"zipCode": "01310-100",
"streetAddress": "Av. Paulista, 1000",
"uploadedSelfieId": "sel_...",
"uploadedDocumentId": "doc_..."
}'{ "success": true, "data": { "attemptId": "kyc_8a2f...", "status": "PENDING" } }Then wait for approval — by webhook (preferred) or by polling:
curl https://api.hodle.com.br/api/kyc/kyc_8a2f... -H "Authorization: Bearer $API_KEY"{ "success": true, "data": { "status": "APPROVED" } }States: PENDING → APPROVED | REJECTED | EXPIRED. On APPROVED you also receive the
KYC_APPROVED webhook. A subaccount that isn't APPROVED gets 403 from
deposit and payout. Full field reference: KYC.
Step 3 — Provision a wallet
Give the subaccount a non-custodial wallet. The same address works across EVM networks (Polygon, Base) — it's an ERC-4337 smart account — plus Tron and Liquid.
curl -X POST https://api.hodle.com.br/api/wallet/create \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{ "subAccountId": "5b9f...e21a", "network": "polygon" }'{ "success": true, "data": { "address": "0x4b1f...c9a2", "network": "polygon", "balance": "0" } }Read balances any time with /api/wallet/get.
Step 4 — Fund the wallet (on-ramp)
Turn BRL into crypto credited to the wallet. Two ways:
- PIX on-ramp —
POST /api/deposit/assetreturns a PIX charge; once the payer pays, Hodle credits the wallet in the chosen asset. - External transfer — send USDT/USDC to the wallet address from Step 3; Hodle indexes the inbound transfer and credits the subaccount automatically.
curl -X POST https://api.hodle.com.br/api/deposit/asset \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subAccountId": "5b9f...e21a",
"value": 5000,
"asset": "USDT",
"network": "polygon"
}'value is in BRL cents (5000 = R$50,00). asset is one of LIGHTNING, USDT, USDC,
USDCE. You get a DEPOSIT_ASSET_SUCCESS webhook when the funds land. Full reference:
Deposit.
Step 5 — Pay out to PIX (off-ramp)
Turn the wallet's crypto into a BRL PIX payment to any key. Hodle covers gas, swaps stable → BRLA, and settles the recipient.
curl -X POST https://api.hodle.com.br/api/wallet/payout \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subAccountId": "5b9f...e21a",
"value": 5000,
"network": "polygon",
"pixKey": "recipient@example.com",
"pixKeyType": "EMAIL"
}'{ "success": true, "transactionId": "tx_7c1d...", "status": "PROCESSING", "valueInBrl": "50.00", "fee": "2.75" }Then poll until settled (or use the webhook):
curl https://api.hodle.com.br/api/wallet/payout/tx_7c1d... -H "Authorization: Bearer $API_KEY"States: PROCESSING → COMPLETED | FAILED. On COMPLETED the response carries endToEndId
(the bank's PIX reference). On FAILED the on-chain transfer is reverted and the balance
restored. Fees: R$1.50 fixed + 2.5%. Full reference: Payout.
Lightning shortcut. If you only need Lightning → PIX (no wallet or KYC), skip Steps 3–5 and issue a Lightning invoice directly — it settles to a PIX key when paid.
Step 6 — Reconcile
Pull every operation for a window and close your books. Each row carries the on-chain txHash
and the PIX endToEndId — the join keys against your bank report.
curl -X POST https://api.hodle.com.br/api/account/statement \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{ "subAccountId": "5b9f...e21a", "from": "2026-06-01", "to": "2026-06-30" }'Reference: Account statement.
Events to handle
Subscribe to webhooks instead of polling. The lifecycle emits:
| Event | When |
|---|---|
KYC_APPROVED / KYC_REJECTED | KYC resolves |
DEPOSIT_ASSET_SUCCESS | on-ramp funds land |
PAYOUT_SUCCESSFUL / PAYOUT_FAILED | payout settles or fails |
Every webhook is signed with X-Hodle-Signature (HMAC-SHA256) — verify it before trusting the body.