# Addresses API Source: https://docs.blockradar.co/en/about-the-api/addresses Generate and manage child addresses for your users. The Addresses API lets you generate dedicated deposit addresses for each of your users. Each address is a child of your master wallet and inherits its network and asset configuration. ## What you can do * Generate a new deposit address for a user * Retrieve address details, balances, and transaction history * Update address metadata * Whitelist or unwhitelist addresses for withdrawal ## Key concepts **One address per user.** Never reuse addresses across users. Each address should be permanently assigned to one user so deposits can be attributed correctly. **EVM compatibility.** On EVM-compatible chains, a single address works across all supported EVM networks. ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/wallets/{walletId}/addresses` | List all addresses | | `POST` | `/wallets/{walletId}/addresses` | Generate a new address | | `GET` | `/wallets/{walletId}/addresses/{addressId}` | Get address details | | `PATCH` | `/wallets/{walletId}/addresses/{addressId}` | Update address metadata | | `POST` | `/wallets/{walletId}/addresses/{addressId}/whitelist` | Whitelist an address | | `DELETE` | `/wallets/{walletId}/addresses/{addressId}/whitelist` | Unwhitelist an address | | `GET` | `/wallets/{walletId}/addresses/{addressId}/balance` | Get single asset balance | | `GET` | `/wallets/{walletId}/addresses/{addressId}/balances` | Get all asset balances | | `GET` | `/wallets/{walletId}/addresses/{addressId}/transactions` | List transactions | View all address endpoints in the API Reference tab. # AML API Source: https://docs.blockradar.co/en/about-the-api/aml Screen wallet addresses against global sanctions and blocklists. The AML API lets you screen any wallet address against OFAC, FBI, Tether, and Circle blocklists in real time. Use this to flag high-risk addresses before sending or receiving funds. ## What you can do * Look up any wallet address and get a risk assessment * Identify addresses on OFAC sanctions lists, FBI watchlists, and stablecoin issuer blocklists ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/aml/lookup?address={address}` | Screen a wallet address | View the AML endpoint in the API Reference tab. # Asset Management API Source: https://docs.blockradar.co/en/about-the-api/asset-management Configure which assets are active on your master wallet. The Asset Management API lets you control which tokens and stablecoins are enabled on a master wallet. Use this API to add, remove, or update asset configurations. ## What you can do * List all assets currently enabled on a wallet * Add a new asset to a wallet * Remove an asset from a wallet * Update asset settings such as sweep thresholds ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/wallets/{walletId}/assets` | List all assets on the wallet | | `POST` | `/wallets/{walletId}/assets` | Add an asset to the wallet | | `DELETE` | `/wallets/{walletId}/assets/{assetId}` | Remove an asset from the wallet | | `PATCH` | `/wallets/{walletId}/assets/{assetId}` | Update asset configuration | View all asset management endpoints in the API Reference tab. # Asset Recovery API Source: https://docs.blockradar.co/en/about-the-api/asset-recovery Recover tokens accidentally sent to unsupported wallet addresses. The Asset Recovery API lets you salvage tokens that were accidentally sent to a Blockradar wallet address but are not on the wallet's supported asset list. Without recovery, these tokens would be permanently inaccessible. ## What you can do * Estimate the network fee required to recover an unsupported token * Execute a recovery to move the token to a destination address ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/wallets/{walletId}/recover/network-fee` | Estimate recovery network fee | | `POST` | `/wallets/{walletId}/recover` | Execute asset recovery | View all asset recovery endpoints in the API Reference tab. # Authentication Source: https://docs.blockradar.co/en/about-the-api/authentication How to authenticate requests to the Blockradar API. The Blockradar API uses API keys to authenticate all requests. Every API key is scoped to a specific master wallet. ## Sending your API key Include your API key in the `x-api-key` header on every request: ```bash theme={null} curl https://api.blockradar.co/v1/wallets -H "x-api-key: YOUR_API_KEY" ``` Never expose your API key in client-side code, public repositories, or logs. Treat it like a password. ## Getting your API keys 1. Log in to the [Blockradar dashboard](https://dashboard.blockradar.co) 2. Navigate to your master wallet settings 3. Copy your API key from the **API Keys** section ## Key scoping Each API key is tied to a single master wallet. If you operate multiple wallets across different networks, you will have a separate key per wallet. View the authentication reference in the API Reference tab. # Auto Settlements API Source: https://docs.blockradar.co/en/about-the-api/auto-settlements Configure rules to automatically convert and route assets. The Auto Settlements API lets you define rules that automatically convert incoming assets and route them to a destination wallet. Use this to eliminate manual treasury operations and ensure funds are always held in your preferred asset. ## What you can do * Enable or disable auto-settlement on a wallet or address * Create, update, and delete settlement rules * Define conversion targets, destination wallets, and trigger thresholds per rule * Pick a settlement flow per rule: `withdraw`, `swap`, `gateway`, or `earn` * Scope a master-wallet rule to specific child addresses instead of all of them * Copy a set of rules onto other master wallets in one call ## Settlement types Every rule resolves to one of four flows. Set it explicitly with `type`; rules saved before this field existed keep their inferred behavior. | Type | What the rule does | | - | - | | `withdraw` | Transfers the source asset out as-is to `destination.address` on the same blockchain | | `swap` | Converts to a different asset and/or a different blockchain | | `gateway` | Deposits USDC into Circle's Gateway unified balance (`isGateway: true`) | | `earn` | Deposits into an Earn position with Aave or Compound (`isReward: true`, mainnet only) | ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/wallets/{walletId}/auto-settlements` | Get auto-settlement config (master wallet) | | `PATCH` | `/wallets/{walletId}/auto-settlements` | Update auto-settlement config | | `GET` | `/wallets/{walletId}/auto-settlements/rules` | List all rules | | `GET` | `/wallets/{walletId}/auto-settlements/rules/{ruleId}` | Get a single rule | | `POST` | `/wallets/{walletId}/auto-settlements/rules` | Create a rule | | `POST` | `/wallets/{walletId}/auto-settlements/rules/copy` | Copy rules onto other master wallets | | `PATCH` | `/wallets/{walletId}/auto-settlements/rules/{ruleId}` | Update a rule | | `DELETE` | `/wallets/{walletId}/auto-settlements/rules/{ruleId}` | Delete a rule | | `GET` | `/wallets/{walletId}/addresses/{addressId}/auto-settlements` | Get config (child address) | | `PATCH` | `/wallets/{walletId}/addresses/{addressId}/auto-settlements` | Update config (child address) | | `GET` | `/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules` | List rules (child address) | | `POST` | `/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules` | Create rule (child address) | | `PATCH` | `/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules/{ruleId}` | Update rule (child address) | | `DELETE` | `/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules/{ruleId}` | Delete rule (child address) | View all auto-settlement endpoints in the API Reference tab. # Checkout API Source: https://docs.blockradar.co/en/about-the-api/checkout Create and manage stablecoin payment links. The Checkout API lets you generate shareable payment links that accept stablecoin payments. Links can be pre-filled with amount, asset, and redirect URL parameters, and can be embedded in your product or shared directly with payers. ## What you can do * Create a payment link with a fixed or open amount * List and retrieve existing payment links * Update link settings * View transactions associated with a payment link ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/payment-links` | Create a payment link | | `GET` | `/payment-links` | List all payment links | | `GET` | `/payment-links/{linkId}` | Get a single payment link | | `PATCH` | `/payment-links/{linkId}` | Update a payment link | | `GET` | `/payment-links/{linkId}/transactions` | List transactions for a link | View all checkout endpoints in the API Reference tab. # Deposit Stablecoins API Source: https://docs.blockradar.co/en/about-the-api/deposit-stablecoins Accept stablecoin deposits via dedicated blockchain addresses. Accept stablecoin payments by generating a dedicated blockchain address for each of your users. Deposits are detected automatically, attributed to the right user, and streamed to your backend via webhooks. Funds can then be swept into your master wallet. ## What you can do * Generate a unique deposit address per user * Retrieve deposits, balances, and on-chain transaction history for any address * Receive real-time webhook notifications when deposits confirm * Sweep funds from child addresses into your master wallet ## How it works 1. **Create a master wallet** on the network you want to accept deposits on. 2. **Generate a child address** for each user using the [Addresses API](/en/about-the-api/addresses). 3. **Share the address** with the user as their deposit destination. 4. **Listen for webhooks** to detect incoming deposits and credit the user in your system. ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/wallets/{walletId}/addresses` | Generate a new deposit address | | `GET` | `/wallets/{walletId}/addresses/{addressId}/balances` | Check address balances | | `GET` | `/wallets/{walletId}/addresses/{addressId}/transactions` | List address transactions | View all deposit endpoints in the API Reference tab. # Errors Source: https://docs.blockradar.co/en/about-the-api/errors How Blockradar communicates errors and how to handle them. The Blockradar API uses standard HTTP status codes to indicate whether a request succeeded or failed. When a request fails, the response body contains a `message` field describing what went wrong. ## HTTP status codes | Code | Meaning | | - | - | | `200` | Success. The request completed as expected. | | `400` | Bad request. A required parameter is missing or malformed. | | `401` | Unauthorized. Your API key is missing or invalid. | | `403` | Forbidden. Your API key does not have permission for this action. | | `404` | Not found. The requested resource does not exist. | | `422` | Unprocessable entity. The request was well-formed but failed validation. | | `429` | Too many requests. You have exceeded the rate limit. | | `500` | Internal server error. Something went wrong on our end. | ## Error response format ```json theme={null} { "statusCode": 400, "message": "walletId is required" } ``` ## Handling errors Check the `statusCode` field on every response. For `4xx` errors, inspect `message` to understand what to fix. For `500` errors, retry with exponential backoff and contact support if the issue persists. View the errors reference in the API Reference tab. # Gateway API Source: https://docs.blockradar.co/en/about-the-api/gateway Move USDC natively across chains using Circle's CCTP protocol. The Gateway API enables cross-chain USDC transfers using Circle's Cross-Chain Transfer Protocol (CCTP). CCTP burns USDC on the source chain and mints it natively on the destination, eliminating bridge risk and wrapped token exposure. ## What you can do * Deposit USDC into the Gateway from any supported chain * Withdraw USDC to any supported destination chain * Check Gateway balances and transaction history * Estimate fees for cross-chain transfers ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/gateway/wallets` | List Gateway-enabled master wallets | | `GET` | `/gateway/wallets/{walletId}/transactions` | List Gateway transactions | | `GET` | `/gateway/wallets/{walletId}/balance` | Get Gateway balance | | `POST` | `/gateway/wallets/{walletId}/deposit` | Deposit to Gateway | | `POST` | `/gateway/wallets/{walletId}/deposit/network-fee` | Estimate deposit fee | | `POST` | `/gateway/wallets/{walletId}/withdraw` | Withdraw from Gateway | | `POST` | `/gateway/wallets/{walletId}/withdraw/network-fee` | Estimate withdrawal fee | | `GET` | `/gateway/wallets/{walletId}/addresses/{addressId}/transactions` | List address Gateway transactions | | `GET` | `/gateway/wallets/{walletId}/addresses/{addressId}/balance` | Get address Gateway balance | | `POST` | `/gateway/wallets/{walletId}/addresses/{addressId}/deposit` | Deposit from child address | | `POST` | `/gateway/wallets/{walletId}/addresses/{addressId}/withdraw` | Withdraw from child address | View all Gateway endpoints in the API Reference tab. # Liquidity Pool API Source: https://docs.blockradar.co/en/about-the-api/liquidity-pool Manage stablecoin liquidity rates for corridor-based settlement. The Liquidity Pool API lets you define and manage exchange rates for stablecoin pairs. This powers FX desk and corridor settlement use cases where you need to offer consistent, programmatically managed rates to counterparties. ## What you can do * Create a rate for a stablecoin pair * Retrieve current and historical rates * Update or deactivate rates * Reactivate a previously deactivated rate ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/liquidity-pool/rates` | Create a new rate | | `GET` | `/liquidity-pool/rates/{rateId}` | Get a rate | | `PATCH` | `/liquidity-pool/rates/{rateId}` | Update a rate | | `POST` | `/liquidity-pool/rates/{rateId}/deactivate` | Deactivate a rate | | `POST` | `/liquidity-pool/rates/{rateId}/reactivate` | Reactivate a rate | | `GET` | `/liquidity-pool/rates/{rateId}/history` | Get rate history | View all liquidity pool endpoints in the API Reference tab. # Master Wallet API Source: https://docs.blockradar.co/en/about-the-api/master-wallet Manage your master wallets, balances, and sweep operations. The Master Wallet API is the root of your Blockradar integration. A master wallet represents your organization's wallet on a given blockchain network. It holds funds, manages child addresses, and is the source for all outbound transactions. ## What you can do * Retrieve wallet details and current configuration * Fetch balances for all assets held in the wallet * Trigger asset sweeps to consolidate funds from child addresses * View webhook delivery logs for the wallet ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/wallets/{walletId}` | Get wallet details | | `PATCH` | `/wallets/{walletId}` | Update wallet settings | | `GET` | `/wallets/{walletId}/balance` | Get balance for a single asset | | `GET` | `/wallets/{walletId}/balances` | Get balances for all assets | | `POST` | `/wallets/{walletId}/deposit-finder` | Recover missing deposits | | `POST` | `/wallets/{walletId}/trigger-sweep` | Trigger asset sweep from child addresses | | `GET` | `/wallets/{walletId}/webhook-logs` | View webhook delivery logs | View all master wallet endpoints in the API Reference tab. # Miscellaneous API Source: https://docs.blockradar.co/en/about-the-api/miscellaneous Retrieve supported assets, blockchains, and exchange rates. The Miscellaneous API provides reference data about the Blockradar platform — the assets, networks, and exchange rates it supports. Use these endpoints to populate dropdowns, validate inputs, and keep your integration in sync with platform capabilities. ## What you can do * List all supported assets across the platform * List all supported blockchain networks * Retrieve current exchange rates between assets ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/assets` | List all supported assets | | `GET` | `/blockchains` | List all supported networks | | `GET` | `/rates` | Get current exchange rates | View all miscellaneous endpoints in the API Reference tab. # Signing API Source: https://docs.blockradar.co/en/about-the-api/signing Sign messages and typed data from any Blockradar wallet. The Signing API lets you sign arbitrary messages and EIP-712 typed data from a Blockradar wallet or child address. This is used for authentication flows, permit-style approvals, and off-chain agreement signing. ## What you can do * Sign a plain message from a master wallet or child address * Sign EIP-712 structured typed data for standards-compliant workflows ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/wallets/{walletId}/signing/message` | Sign a message (master wallet) | | `POST` | `/wallets/{walletId}/signing/typed-data` | Sign EIP-712 typed data (master wallet) | | `POST` | `/wallets/{walletId}/addresses/{addressId}/signing/message` | Sign a message (child address) | | `POST` | `/wallets/{walletId}/addresses/{addressId}/signing/typed-data` | Sign EIP-712 typed data (child address) | View all signing endpoints in the API Reference tab. # Smart Contract API Source: https://docs.blockradar.co/en/about-the-api/smart-contracts Read and write to any smart contract from a Blockradar wallet. The Smart Contract API lets you interact with any on-chain smart contract directly from a Blockradar wallet without managing ABIs, gas estimation, or RPC providers yourself. ## What you can do * Call read functions on any contract * Execute write functions that modify on-chain state * Use sign-only mode to sign contract interactions without broadcasting * Estimate network fees for contract writes ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/wallets/{walletId}/contracts/read` | Read from a contract (master wallet) | | `POST` | `/wallets/{walletId}/contracts/write` | Write to a contract (master wallet) | | `POST` | `/wallets/{walletId}/contracts/write/sign-only` | Sign-only contract write (master wallet) | | `POST` | `/wallets/{walletId}/contracts/network-fee` | Estimate fee for contract write (master wallet) | | `POST` | `/wallets/{walletId}/addresses/{addressId}/contracts/read` | Read from a contract (child address) | | `POST` | `/wallets/{walletId}/addresses/{addressId}/contracts/write` | Write to a contract (child address) | | `POST` | `/wallets/{walletId}/addresses/{addressId}/contracts/write/sign-only` | Sign-only contract write (child address) | | `POST` | `/wallets/{walletId}/addresses/{addressId}/contracts/network-fee` | Estimate fee for contract write (child address) | View all smart contract endpoints in the API Reference tab. # Swap API Source: https://docs.blockradar.co/en/about-the-api/swap Swap stablecoins across assets and chains. The Swap API lets you exchange one stablecoin for another directly from a Blockradar wallet. Swaps can be initiated from a master wallet or a child address. ## What you can do * Get a quote for a swap before committing * Quote by source amount or target amount with `amountSide` * Execute a swap between supported assets * Swap from both master wallets and child addresses * Route supported Stellar USDC destinations with the generic `recipientRouting` contract ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/v1/wallets/{walletId}/swaps/quote` | Get swap quote from master wallet | | `POST` | `/v1/wallets/{walletId}/swaps/execute` | Execute swap from master wallet | | `POST` | `/v1/wallets/{walletId}/addresses/{addressId}/swaps/quote` | Get swap quote from child address | | `POST` | `/v1/wallets/{walletId}/addresses/{addressId}/swaps/execute` | Execute swap from child address | ## Recipient parameters | Parameter | Type | Required | Description | | - | - | - | - | | `recipientAddress` | string | No | External recipient address. It remains a string, including for Stellar `G...` and `M...` addresses. | | `recipientRouting` | object | No | Stellar-only routing choice: `{ type: "none" }` or `{ type: "memo_id", value: "" }`. Do not send it to EVM, Solana, or Tron destinations. | ## Stellar recipient routing `recipientRouting` is supported only when the destination chain is Stellar. Existing EVM, Solana, and Tron swap requests are unchanged and **must not send** `recipientRouting`; requests that supply it are rejected. There is no separate recipient memo parameter. For supported Stellar USDC destinations: 1. **Muxed `M...` recipient:** omit `recipientRouting`. Its routing ID is already embedded in the address; sending routing data is rejected. 2. **Base `G...` recipient with a routing ID:** send `recipientRouting: { type: "memo_id", value: "123" }`. The value must be a non-empty numeric string from `0` through `18446744073709551615`. Blockradar normalizes the destination to an `M...` address before requesting quote or execution. 3. **Base `G...` recipient without a routing ID:** send `recipientRouting: { type: "none" }` with no `value`. A `G...` recipient without `recipientRouting` is rejected. The destination base account must already have a Stellar USDC trustline before quote and execution. 4. **Default Blockradar Stellar wallet:** callers must explicitly send `recipientRouting: { type: "none" }`. ```json Stellar base account with a routing ID theme={null} { "recipientAddress": "G...", "recipientRouting": { "type": "memo_id", "value": "123" } } ``` ```json Stellar base account without a routing ID theme={null} { "recipientAddress": "G...", "recipientRouting": { "type": "none" } } ``` ### Quote response metadata Quote responses can include `data.recipientRouting` to explain the routing result. Execute responses do not include this metadata. ```json theme={null} { "recipientRouting": { "status": "embedded", "message": "The recipient routing ID is embedded in the normalized destination address." } } ``` ### Migrating from Stellar-only fields | Previous field | Use instead | | - | - | | `recipientMemoId` | `recipientRouting: { type: "memo_id", value: "" }` | | `stellarMemoNotRequired: true` | `recipientRouting: { type: "none" }` | View all swap endpoints in the API Reference tab. # Transactions API Source: https://docs.blockradar.co/en/about-the-api/transactions Retrieve, manage, and replay transactions across your wallets. The Transactions API gives you full visibility into every transaction that has passed through your Blockradar wallets. You can also use it to cancel pending transactions, retry failed ones, and resend missed webhooks. ## What you can do * List and filter transactions across a wallet * Retrieve details for a single transaction * Resend a webhook for any transaction * Cancel a pending transaction * Retry a failed transaction * Trigger an asset sweep manually ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/wallets/{walletId}/transactions` | List all transactions | | `GET` | `/wallets/{walletId}/transactions/{transactionId}` | Get a single transaction | | `POST` | `/wallets/{walletId}/transactions/{transactionId}/resend-webhook` | Resend webhook for a transaction | | `POST` | `/wallets/{walletId}/transactions/{transactionId}/sweep` | Trigger asset sweep | | `GET` | `/wallets/{walletId}/transactions/webhook-logs` | View webhook delivery logs | | `POST` | `/wallets/{walletId}/transactions/{transactionId}/cancel` | Cancel a pending transaction | | `POST` | `/wallets/{walletId}/transactions/{transactionId}/retry` | Retry a failed transaction | View all transaction endpoints in the API Reference tab. # Virtual Accounts API Source: https://docs.blockradar.co/en/about-the-api/virtual-accounts Issue bank account numbers linked to on-chain wallets. The Virtual Accounts API lets you issue local bank account numbers to your users. When a user sends a bank transfer to their virtual account, Blockradar detects the payment and credits the linked on-chain address. ## What you can do * Create a virtual account linked to a master wallet or child address * Retrieve virtual account details and transaction history * Update or regenerate account details ## Supported markets Virtual accounts are currently available for NGN (Nigeria) via NUBAN bank account numbers, with cNGN as the on-chain settlement asset. ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/wallets/{walletId}/virtual-accounts` | Create virtual account on master wallet | | `GET` | `/wallets/{walletId}/virtual-accounts` | List virtual accounts on master wallet | | `GET` | `/wallets/{walletId}/virtual-accounts/{accountId}` | Get virtual account details | | `PATCH` | `/wallets/{walletId}/virtual-accounts/{accountId}` | Update virtual account | | `POST` | `/wallets/{walletId}/virtual-accounts/{accountId}/regenerate` | Regenerate account number | | `GET` | `/wallets/{walletId}/virtual-accounts/{accountId}/transactions` | List transactions | | `POST` | `/wallets/{walletId}/addresses/{addressId}/virtual-accounts` | Create virtual account on child address | | `GET` | `/wallets/{walletId}/addresses/{addressId}/virtual-accounts` | List virtual accounts on child address | View all virtual account endpoints in the API Reference tab. # Withdraw Stablecoins API Source: https://docs.blockradar.co/en/about-the-api/withdraw Send stablecoins from master wallets or child addresses. The Withdraw API lets you send stablecoins programmatically from either a master wallet or a child address. Both paths support standard withdrawals and sign-only variants for self-custody workflows. ## What you can do * Send a withdrawal from a master wallet or child address * Estimate network fees before sending * Use sign-only mode to sign transactions without broadcasting ## Sign-only vs standard **Standard withdrawal** — Blockradar signs and broadcasts the transaction on your behalf. **Sign-only withdrawal** — Blockradar returns a signed transaction payload that you broadcast yourself. Use this when you want to retain control of the broadcast step. ## Endpoints | Method | Endpoint | Description | | - | - | - | | `POST` | `/wallets/{walletId}/withdraw` | Withdraw from master wallet | | `POST` | `/wallets/{walletId}/withdraw/sign-only` | Sign-only withdrawal from master wallet | | `POST` | `/wallets/{walletId}/withdraw/network-fee` | Estimate fee for master wallet withdrawal | | `POST` | `/wallets/{walletId}/addresses/{addressId}/withdraw` | Withdraw from child address | | `POST` | `/wallets/{walletId}/addresses/{addressId}/withdraw/sign-only` | Sign-only withdrawal from child address | | `POST` | `/wallets/{walletId}/addresses/{addressId}/withdraw/network-fee` | Estimate fee for child address withdrawal | View all withdraw endpoints in the API Reference tab. # Withdraw Fiat API Source: https://docs.blockradar.co/en/about-the-api/withdraw-fiat Convert stablecoins to fiat and send to bank accounts. The Withdraw Fiat API lets you convert stablecoins held in a Blockradar wallet to fiat currency and disburse directly to a bank account. This powers stablecoin off-ramp flows for your users. ## What you can do * Look up supported fiat assets, institutions, and exchange rates * Verify a recipient bank account before sending * Get a quote for a fiat withdrawal * Execute a fiat withdrawal from a master wallet or child address ## Endpoints | Method | Endpoint | Description | | - | - | - | | `GET` | `/withdraw-fiat/assets` | List supported fiat assets | | `GET` | `/withdraw-fiat/institutions` | List supported financial institutions | | `GET` | `/withdraw-fiat/rates` | Get current exchange rates | | `GET` | `/withdraw-fiat/currencies` | List supported currencies | | `POST` | `/withdraw-fiat/verify` | Verify a recipient bank account | | `POST` | `/wallets/{walletId}/withdraw-fiat/quote` | Get a quote from master wallet | | `POST` | `/wallets/{walletId}/withdraw-fiat` | Execute fiat withdrawal from master wallet | | `POST` | `/wallets/{walletId}/addresses/{addressId}/withdraw-fiat/quote` | Get a quote from child address | | `POST` | `/wallets/{walletId}/addresses/{addressId}/withdraw-fiat` | Execute fiat withdrawal from child address | View all withdraw fiat endpoints in the API Reference tab. # Generate Address Source: https://docs.blockradar.co/en/api-reference/addresses/generate-address post /v1/wallets/{walletId}/addresses This endpoint allows you to create a new address for a specific wallet. ### Body Parameters | Key | **Required** | Type | Description | | --- | --- | --- | --- | | name | false | string | The name of the address. | | metadata | false | object | Additional metadata for the address, this will be part of any transaction tied to this | | disableAutoSweep | false | boolean | Disable automatic sweeping of assets sent to the address into your master wallet | | enableGaslessWithdraw | false | boolean | Enable gasless transactions from this address | # Get Address Source: https://docs.blockradar.co/en/api-reference/addresses/get-address get /v1/wallets/{walletId}/addresses/{addressId} This endpoint retrieves information about a specific address within a wallet. ### Query Parameters | Name | Type | Required | Description | |-----------------|----------|----------|--------------------------------------------------| | showPrivateKey | boolean | Optional | If `true`, the response will include the private key. If `false` or omitted, the private key is not computed. | # Get Addresses Source: https://docs.blockradar.co/en/api-reference/addresses/get-addresses get /v1/wallets/{walletId}/addresses This endpoint retrieves the addresses associated with a specific wallet. # Get Balance Source: https://docs.blockradar.co/en/api-reference/addresses/get-balance get /v1/wallets/{walletId}/addresses/{addressId}/balance This endpoint retrieves the balance of a specific address within a wallet # Get Balances Source: https://docs.blockradar.co/en/api-reference/addresses/get-balances get /v1/wallets/{walletId}/addresses/{addressId}/balances This endpoint retrieves the balances associated with a specific address in a wallet. # Get transaction Source: https://docs.blockradar.co/en/api-reference/addresses/get-transaction get /v1/wallets/{walletId}/addresses/{addressId}/transactions/{id} Get transaction # Get transactions Source: https://docs.blockradar.co/en/api-reference/addresses/get-transactions get /v1/wallets/{walletId}/addresses/{addressId}/transactions This endpoint retrieves the transactions associated with a specific address in a wallet. # Unwhitelist address Source: https://docs.blockradar.co/en/api-reference/addresses/unwhitelist-address delete /v1/wallets/{walletId}/addresses/whitelist/{addressId} The endpoint allows the deletion of a specific address from the whitelist of a wallet. # Update Address Source: https://docs.blockradar.co/en/api-reference/addresses/update-address patch /v1/wallets/{walletId}/addresses/{addressId} This endpoint allows the client to update the status of a specific address within a wallet. ### Body Parameters | Key | **Required** | Type | Description | | --- | --- | --- | --- | | isActive | false | boolean | The status state you want to set the address | | name | false | string | The name of the address. | | metadata | false | object | Additional metadata for the address. This will be part of any transaction tied to this. | | showPrivateKey | false | boolean | If you want the address private key to be part of the response. | | disableAutoSweep | false | boolean | Disable automatic sweeping of assets sent to the address into your master wallet. | | enableGaslessWithdraw | false | boolean | Enable gasless transactions from this address. | | privateKey | false | string | The private key associated with the address. Required for executing actions securely. | # Validate Address Source: https://docs.blockradar.co/en/api-reference/addresses/validate-address get /v1/addresses/validate This endpoint checks whether an address is syntactically valid for a given blockchain — for example, to validate a customer-supplied withdrawal destination at input time instead of discovering the error when the withdrawal fails. Validation happens offline against the blockchain's address format; no on-chain lookup or AML screening is performed. For EVM blockchains, a valid address is returned in its EIP-55 checksummed form. An address that fails validation still returns `200` with `isValid: false` — error status codes are reserved for malformed requests (`400`) and blockchains that are unknown or unavailable (`404`). # Whitelist address Source: https://docs.blockradar.co/en/api-reference/addresses/whitelist-address post /v1/wallets/{walletId}/addresses/whitelist This endpoint allows you to whitelist an external address to be monitored based on the wallet policies ### Body Parameters | Key | Required | Type | Description | |-------------------------|----------|---------|-----------------------------------------------------------------------------| | name | false | string | The name of the address. | | address | true | string | The wallet address. | | metadata | false | object | Additional metadata for the address. This will be part of any transaction tied to this. | | showPrivateKey | false | boolean | If you want the address private key to be part of the response. | | disableAutoSweep | false | boolean | Disable automatic sweeping of assets sent to the address into your master wallet. | | enableGaslessWithdraw | false | boolean | Enable gasless transactions from this address. | | privateKey | false | string | The private key associated with the address. Required for executing actions securely. | # Authentication Source: https://docs.blockradar.co/en/api-reference/authentication Authenticate your API calls by including your api key in the request header of every request you make. You can manage your API keys from the [dashboard](https://dashboard.blockradar.co). Generally, we provide api key for each wallet you create. The api keys, are to be kept secret. If for any reason you believe your api key has been compromised or you wish to reset them, you can do so from the dashboard. Secure your api keys
Do not commit your api keys to git, or use them in client-side code.
Request headers should be in the following format:
`x-api-key: WALLET_API_KEY ` Sample Request Header
`x-api-key: Ysz1aUX52Slt8sEXXrLBaQXjxtdT`
API requests made without authentication will fail with the status code
`401:Unauthorized` . All API requests must be made over HTTPS. Secure your requests
Do not set `VERIFY_PEER` to `FALSE`. Ensure your server verifies the SSL connection to Blockradar.
# Create Customer Onboarding Request Source: https://docs.blockradar.co/en/api-reference/customer-onboarding/create-request post /v1/customers/{customerId}/onboarding-requests Creates an API-based onboarding request for a customer and returns the Dynamic Form Schema that describes the required customer information. Complete `data.requirements.schema`, then submit the resulting object to the request's submit endpoint. The response includes `data.requirements.schema`. Complete that schema and send the resulting object as `data` to the submit operation. See [Dynamic Forms](/en/guides/dynamic-forms) for the schema-processing flow. # Get Customer Onboarding Confirmation Requirements Source: https://docs.blockradar.co/en/api-reference/customer-onboarding/get-confirmation-requirements get /v1/onboarding/cases/{caseId}/confirmation-requirements Returns a confirmation schema when the customer-onboarding case requires a confirmation step. Call this operation only when the customer-onboarding case reaches a state that requires confirmation. # Get Customer Onboarding Request Source: https://docs.blockradar.co/en/api-reference/customer-onboarding/get-request get /v1/customers/{customerId}/onboarding-requests/{caseId} Returns the current onboarding case and requirements schema. Fetch this operation again when the case changes so the integration uses the current schema and status. Use the current `data.requirements.schema` when collecting or validating customer information. The requirements may change as the onboarding request progresses. # List Customer Onboarding Requests Source: https://docs.blockradar.co/en/api-reference/customer-onboarding/list-requests get /v1/customers/{customerId}/onboarding-requests Lists onboarding requests created for a customer. # Prepare Customer Onboarding Uploads Source: https://docs.blockradar.co/en/api-reference/customer-onboarding/prepare-uploads post /v1/onboarding/cases/{caseId}/uploads/prepare Prepares upload targets for file or document fields in the current customer-onboarding requirements schema. Use the exact field paths and constraints returned by the schema. Use this operation only for file or document fields declared by the current customer-onboarding requirements schema. # Submit Customer Onboarding Requirements Source: https://docs.blockradar.co/en/api-reference/customer-onboarding/submit-request post /v1/customers/{customerId}/onboarding-requests/{caseId}/submit Submits an object completed from the request's Dynamic Form Schema. If required information is still missing, `data.initiated` is false and `data.requirements` contains the current schema. Send the completed Dynamic Forms object in the top-level `data` property. If the response contains `data.requirements`, more information is still required. # Upload Prepared Customer Document Source: https://docs.blockradar.co/en/api-reference/customer-onboarding/upload-prepared-document post /v1/onboarding/cases/{caseId}/uploads/{uploadId} Uploads the required document sides for a prepared proxy upload. This endpoint is used for a prepared proxy upload. For a direct upload, follow the method, URL, and headers returned by the prepare operation. # Create Customer Source: https://docs.blockradar.co/en/api-reference/customer/create post /v1/customers Creates a customer owned by the authenticated business. # Get Customer Source: https://docs.blockradar.co/en/api-reference/customer/get get /v1/customers/{customerId} # List Customers Source: https://docs.blockradar.co/en/api-reference/customer/list get /v1/customers Lists customers owned by the authenticated business, newest first. # Update Customer Source: https://docs.blockradar.co/en/api-reference/customer/update patch /v1/customers/{customerId} Updates the supplied customer fields. Customers are not deleted through this API. # Errors Source: https://docs.blockradar.co/en/api-reference/errors Blockradar's API is RESTful and as such, uses conventional HTTP response codes to indicate the success or failure of requests. ### HTTP Codes | Code | Description | | - | - | | 200 | Request was successful and intended action was carried out. | | 201 | A resource has successfully been created. | | 400 | A validation or client side error occurred and the request was not fulfilled. | | 401 | The request was not authorized. This can be triggered by passing an invalid api key in the x-api-key header or the lack of one. | | 404 | Request could not be fulfilled as the requested resource does not exist. | | 5xx | Request could not be fulfilled due to an error on Blockradar's end. This shouldn't happen so please report as soon as you encounter any instance of this. | Not sure where to look? Try search
Type the error or keywords into the search bar above. If you don’t find what you’re looking for, [contact us](mailto:support@blockradar.co), we’re happy to help.
# Introduction Source: https://docs.blockradar.co/en/api-reference/introduction Learn how to seamlessly integrate our APIs into your application. Before you begin!
You should create a free Blockradar account that you can test the API against. We will provide you with test keys that you can use to make API calls.
View the Postman Collection The Blockradar API gives you access to pretty much all the features you can use on our dashboard and lets you extend them for use in your product. It strives to be RESTful and is organized around the main resources you would be interacting with - with a few notable exceptions. ### Sample Requests We provide sample API calls next to each method [using cURL](https://curl.se/). All you need to do is insert your specific parameters, and you can test the calls from the command line. See this tutorial on [using cURL with APIs](https://www.baeldung.com/curl-rest). You can also [use Postman](https://www.postman.com/downloads/) if you aren't familiar with cURL. Postman is an easy to use API development and testing platform. You can explore the [Blockradar Postman Collection](https://documenter.getpostman.com/view/7709133/2s93eSYaVs) to understand how our APIs work. ### Requests and Response Both request body data and response data are formatted as JSON. Content type for responses will always be application/json. Generally, all responses will be in the following format: ```json theme={null} { "statusCode": "[number]", "message": "[string]", "data": "[object]" } ``` ### Keys | Property | Type | Description | | - | - | - | | statusCode | number | This is the request status code that lets you know if your request was succesful or not. We recommend that you use this to determine the result of an API call. | | message | string | This is a summary of the response and its status. For instance when trying to retrieve a list of customers, message might read “Transactions fetched successfully". In the event of an error, the message key will contain a description of the error as with the authorization header situation above. This is the only key that is universal across requests. | | data | object | This contain the results of your request. It can either be an object, or an array depending on the request made. For instance, a request to retrieve a single transaction will return a transaction object in the data key, while the key would be an array of transactions if a list is requested instead. | ### Meta Object The meta key is used to provide context for the contents of the data key. For instance, if a list of transactions performed by a customer is being retrieved, pagination parameters can be passed along to limit the result set. The meta key will then contain an object with the following attributes: ```json theme={null} { "meta": { "totalItems": 704, "itemCount": 100, "itemsPerPage": 100, "totalPages": 8, "currentPage": 1 } } ``` | Property | Description | | - | - | | totalItems | The total number of items available. This represents the complete count of items across all pages. | | itemCount | The number of items on the current page. This indicates how many items are being returned in the current response. | | itemsPerPage | The maximum number of items per page. This defines the pagination limit set for each page. **Default: 100** | | totalPages | The total number of pages available. This is calculated based on the total number of items and the number of items per page. | | currentPage | The current page number. This indicates which page of the pagination is being returned in the current response. **Default: 1** | # Deposit Finder Source: https://docs.blockradar.co/en/api-reference/wallet/deposit-finder post /v1/wallets/{id}/rescan/blocks This endpoint is used to initiate a rescan of blocks for a specific wallet. ### Body Parameters | Key | **Required** | Type | Description | | --- | --- | --- | --- | | transactionHash | false | string | The blockchain transaction hash | # Get Balance Source: https://docs.blockradar.co/en/api-reference/wallet/get-balance get /v1/wallets/{walletId}/balance This endpoint retrieves the balance of a specific wallet for a given asset. # Get Balances Source: https://docs.blockradar.co/en/api-reference/wallet/get-balances get /v1/wallets/{walletId}/balances This endpoint retrieves the balances of a specific wallet. # Get Wallet Source: https://docs.blockradar.co/en/api-reference/wallet/get-wallet get /v1/wallets/{walletId} This endpoint retrieves the details of a specific wallet ### Query Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | showPrivateKey | boolean | Optional | If `true`, the response will include the private key. If `false` or omitted, the private key is not computed. | # Trigger Sweep Assets Source: https://docs.blockradar.co/en/api-reference/wallet/trigger-sweep-assets post /v1/wallets/{walletId}/sweep/assets This endpoint is used to manually trigger assets sweep for all unswept assets for a specific wallet # Update wallet Source: https://docs.blockradar.co/en/api-reference/wallet/update-wallet patch /v1/wallets/{walletId} This endpoint allows you to update the details of a specific wallet ### Body Parameters | Key | **Required** | Type | Description | | --- | --- | --- | --- | | name | false | string | The updated name of the wallet. | | description | false | string | The updated description of the wallet. | # Webhooks Logs Source: https://docs.blockradar.co/en/api-reference/wallet/webhooks-logs get /v1/wallets/{walletId}/webhooks This endpoint retrieves the webhooks associated with a specific wallet # Address Activation Source: https://docs.blockradar.co/en/essentials/address-activation Understand account activation and minimum balance requirements on Stellar, Tron, and Solana In a nutshell
Some blockchains require accounts to be funded or registered on-chain before they can hold assets. Blockradar handles this automatically, but you will see small movements of native tokens (XLM, TRX, SOL) from your master wallet as a result. These are protocol requirements enforced by the blockchain itself, not Blockradar fees.
## Why This Matters On EVM chains like Ethereum or Base, a newly generated address exists implicitly: it costs nothing to create, and it can receive tokens immediately. Stellar, Tron, and Solana work differently. Each of these networks requires an account to be **activated** (Stellar, Tron) or to maintain a **minimum balance** (Solana) before it can fully participate on-chain. When Blockradar performs these steps for you, native tokens leave your master wallet, which can look alarming if you don't know what's happening. The most common example: after generating dedicated addresses on Stellar, you'll see small XLM transfers out of your master wallet. **This is not your XLM being drained.** It is the Stellar network's mandatory reserve being placed into each new address, and it remains in accounts your wallet controls. Here's a summary of what each chain requires, with details for each below: | Chain | Cost at address creation | Paid by | Where the funds go | | - | - | - | - | | Stellar | 0.5 XLM × (2 + number of Stellar assets enabled on the wallet) — for example, 2 XLM with USDC and EURC enabled | Master wallet | Locked as reserve **inside the new address** | | Tron | None — activation happens on first TRX transfer to the address (1 TRX network fee) | Sender of the first TRX transfer | Burned by the Tron network | | Solana | None — rent-exempt minimums apply when accounts are funded (\~0.00089 SOL per wallet account, \~0.00204 SOL per token account) | Fee payer (master wallet) | Locked as rent deposit in the account | ## Stellar ### How Stellar works On Stellar, an account does not exist on-chain until it is created with a funding transaction. The network enforces a minimum balance called the [base reserve](https://developers.stellar.org/docs/learn/fundamentals/lumens#base-reserves): * Every account must hold a minimum of **1 XLM** (2 × 0.5 XLM base reserves). * Each **trustline** adds **0.5 XLM** to the minimum balance. A trustline is an explicit opt-in that allows a Stellar account to hold a non-native asset. An address cannot receive USDC on Stellar until a USDC trustline has been established on it — and that trustline raises the account's required reserve by 0.5 XLM. ### What Blockradar does When you generate a dedicated address on a Stellar wallet, Blockradar automatically activates it in the background. Activation is triggered when the address is created with indexing enabled (the default). If you issue a dormant address (`enableIndexing: false`), activation is deferred until you [enable indexing](/en/essentials/addresses#enable-indexing). The activation flow: Your master wallet sends the required reserve to the new address in a `createAccount` operation. The amount is `0.5 XLM × (2 + number of trustlines)`, with one trustline for each Stellar asset enabled on the wallet. A wallet with USDC and EURC enabled funds **2 XLM per address**. Enabling USDT as well makes it **2.5 XLM per address**. In the same transaction, trustlines are established on the new address for every Stellar asset enabled on your wallet, so it can receive those assets immediately. Assets you have not enabled get no trustline and cost nothing. Blockradar supports USDC, EURC, USDT and PYUSD on Stellar mainnet, and USDC and EURC on Stellar testnet. The address is marked as activated, and the activation transaction hash is stored on the address for your records. Once activated, the address response includes the activation details under `configurations.stellar`. This example is from a mainnet wallet with USDC, EURC and USDT enabled: ```json theme={null} { "configurations": { "stellar": { "activated": true, "trustlines": [ "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", "EURC:GDHU6WRG4IEQXM5NZ4BMPKOXHW76MZM4Y2IEMFDVXBSDP6SJY4ITNPP2", "USDT0:GATISXX6BZ6NC7IKQBY37CJD4SOZL3CYZJWXEDG6JVIY4WBS6KXJHN6Q" ], "activationTxHash": "d1f4c9a4e2..." } } } ``` **Your XLM is not being drained.** The XLM sent from your master wallet during activation becomes the reserve balance of the child address — an address derived from and controlled by your own wallet. You can verify every activation on-chain using the `activationTxHash`. The reserve is required by the Stellar protocol for the account to exist and hold assets; it is not a Blockradar fee. ### Funding requirements Your Stellar master wallet must hold enough XLM to activate the addresses you plan to create. Budget **1 XLM plus 0.5 XLM for each Stellar asset enabled on the wallet** per address (2 XLM with USDC and EURC, 2.5 XLM with USDC, EURC and USDT), plus a small buffer for transaction fees. If your master wallet doesn't have enough XLM, activation doesn't fail permanently — it is queued and retried automatically (every minute for the first \~10 minutes, then every 5 minutes) until the master wallet is funded. The address's `configurations.stellar` will show `activated: false` with a `lastError` describing the reason in the meantime. ### Enabling an asset on a Stellar wallet Trustlines follow the assets enabled on each wallet. When Blockradar starts supporting a new Stellar asset, nothing changes for your wallets and no XLM moves until you enable that asset. When you enable a Stellar asset on a wallet that already has activated addresses, those accounts are brought up to date automatically. A background job adds the missing trustline to the master wallet and to every activated address on that wallet. In the same transaction, it sends **0.5 XLM** from your master wallet to each account to cover the extra reserve. The job runs every 10 minutes, so the trustlines appear within about 10 minutes of enabling the asset. `configurations.stellar.trustlines` on each address then lists the new asset. Before enabling a Stellar asset, make sure your master wallet holds at least **0.5 XLM for each activated address on the wallet, plus 0.5 XLM for the master wallet itself**. If the master wallet runs short, the missing trustlines are retried on the next run once the wallet is funded. Until then, those addresses can't receive the new asset, but everything they already hold keeps working. Do not share a Stellar address with a customer until it has been activated. Payments to a Stellar account that doesn't exist yet — or asset transfers to an account without the matching trustline — are rejected by the network. Check `configurations.stellar.activated` before displaying the address for deposits. ## Tron ### How Tron works Tron addresses are inactive until they appear on-chain for the first time. An address is activated when it receives TRX (or TRC-10 tokens) from an already-active account. The Tron network charges the **sender** a one-time [account creation fee of 1 TRX](https://developers.tron.network/docs/account), which is burned. Two things are worth knowing: * **TRC-20 deposits (e.g., USDT) do not require activation.** Token balances are tracked by the token contract, so a customer can deposit USDT to a freshly generated address with no upfront cost. * **Sending TRX to a new address costs 1 TRX extra.** The activation fee is charged to whoever sends the first TRX transfer to that address. ### What Blockradar does Generating a Tron address on Blockradar is free — there is no upfront activation. The 1 TRX fee comes into play when TRX is sent to an address that has never been active. Blockradar detects this automatically and includes the activation fee in the network fee estimate, for example when: * You process a withdrawal to a customer's brand-new Tron wallet. * Blockradar funds one of your dedicated addresses with TRX to cover sweep fees. You don't need to do anything — the fee simply appears as part of the network fee on those transactions. ## Solana ### How Solana works Solana has no activation step, but it enforces [rent exemption](https://solana.com/docs/core/accounts): every on-chain account must hold a minimum SOL balance proportional to the data it stores. As long as the balance stays above the minimum, the account persists indefinitely. * A regular wallet account requires **\~0.00089 SOL**. * Each **token account** (the account that holds a specific SPL token, such as USDC, for a wallet) requires **\~0.00204 SOL**. Unlike EVM chains, a Solana wallet needs a separate token account for every token it holds. The rent deposit is locked in the account, not burned — it is recoverable if the account is ever closed. ### What Blockradar does Generating a Solana address on Blockradar is free — no on-chain transaction happens at creation. Rent deposits come into play the first time token accounts are needed. When Blockradar sweeps a deposit or processes a withdrawal and a required token account doesn't exist yet, it creates the account automatically and the fee-paying wallet covers the \~0.00204 SOL rent deposit. This applies to both your own addresses and, on withdrawals, the recipient's token account if they've never held that token before. As with Tron, this is handled transparently and reflected in the transaction's network fee. ## FAQs No — this is Stellar activation working as designed. Each new address receives the network-mandated reserve from your master wallet: 1 XLM account minimum plus 0.5 XLM for each Stellar asset enabled on the wallet (2 XLM with USDC and EURC enabled). The XLM sits in the child address, which is derived from and controlled by your wallet. You can verify each transfer on-chain via the `activationTxHash` in the address's `configurations.stellar`. The most common cause is an underfunded master wallet. Top up your Stellar master wallet with XLM — pending activations retry automatically once funds arrive, so no manual action is needed beyond funding. Check `configurations.stellar.lastError` on the address for the specific reason. The recipient address had never been active on the Tron network, so the network charged the one-time 1 TRX account creation fee. This is burned by the network, applies only to the first TRX transfer to that address, and is included automatically in Blockradar's fee estimate. That's Solana's rent-exempt minimum: \~0.00089 SOL per wallet account and \~0.00204 SOL per token account. It's a deposit required by the network for the account to persist, not a fee — it stays in the account and is recoverable if the account is closed. Stellar reserves and Solana rent deposits remain locked while the accounts exist and hold assets. They are only released if the underlying accounts (or trustlines/token accounts) are closed. Tron's 1 TRX activation fee is burned by the network and is not recoverable. ## Learn More * [Stellar: Lumens and base reserves](https://developers.stellar.org/docs/learn/fundamentals/lumens) * [Tron: Account model and activation](https://developers.tron.network/docs/account) * [Solana: Accounts and rent](https://solana.com/docs/core/accounts) # Addresses Source: https://docs.blockradar.co/en/essentials/addresses Learn how to create dedicated addresses for your customers to deposit stablecoins In a nutshell
Dedicated addresses allow you to create unique blockchain addresses for each customer. These addresses can receive stablecoins across multiple EVM-compatible chains, with deposits automatically swept to your master wallet.
Addresses ## Prerequisites Before generating addresses, ensure you have: Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. Create at least one master wallet in the dashboard (see [Create a Master Wallet](/en/guides/create-master-wallet)). You'll need the `walletId` to generate addresses. Fund your master wallet with native tokens (ETH, BNB, MATIC, etc.) to cover gas fees for auto-sweeping operations. Set up your webhook URL on the master wallet to receive deposit notifications. See [Webhooks](/en/utilities/webhooks) for setup details. ## How It Works Dedicated Addresses is a crucial feature on Blockradar that enables you to create unique addresses for your customers. These addresses allow your customers to deposit stablecoins into your fintech app seamlessly. When you create a dedicated address for a customer, they can use that single address to deposit stablecoins across multiple EVM-compatible blockchains. For example, if you have Ethereum, Binance Smart Chain, Polygon, and Base master wallets created, each address you generate through any of these master wallets can be used to receive stablecoins on any of the [supported blockchains and assets](/en/use-cases/integrations). This ensures that you don't have to worry about your customer sending stablecoins to the wrong blockchain. Additionally, when stablecoins are deposited into a particular address, the assets are automatically moved to the chain's master wallet address. Aside from Tron and Solana, addresses generated from one wallet can be used to deposit stablecoins across other blockchains that have the blockchain parameter `isEvmCompatible: true`. **Creating addresses on Stellar, Tron, or Solana?** These networks require accounts to be activated or hold minimum balances before they can receive assets. On Stellar, each new address is automatically funded from your master wallet with 1 XLM plus 0.5 XLM for each asset enabled on the wallet — this is the network's required reserve, not a fee. See [Address Activation](/en/essentials/address-activation) for what to expect on each chain. ## Address Parameters Explained When creating or updating an address, you can use the following optional parameters to customize its behavior: | Parameter | Type | Default | Description | | - | - | - | - | | `disableAutoSweep` | Boolean (Optional) | `false` | If set to `true`, automatic sweeping of funds from this address is disabled. | | `enableGaslessWithdraw` | Boolean (Optional) | `false` | If set to `true`, allows withdrawals without requiring the user to pay gas fees directly. | | `metadata` | Object (Optional) | `null` | Custom metadata you can attach to the address for your own reference or tracking purposes. | | `name` | String (Optional) | `null` | A human-readable name for the address, useful for identification in your dashboard or logs. | | `showPrivateKey` | Boolean (Optional) | `false` | If set to `true`, the private key for this address will be returned in the API response. **Use with caution.** | The parameters `disableAutoSweep`, `enableGaslessWithdraw`, and `showPrivateKey` will override the corresponding settings in the master wallet configuration for this specific address. This allows for granular control at the address level, regardless of the wallet's default settings. **Notes:** * All these parameters are optional; you only need to include those relevant to your use case. * Enabling `showPrivateKey` can expose sensitive information. Only use this in secure, trusted environments. * Be cautious with `showPrivateKey` exposing private keys can compromise security. ## Create a Dedicated Address You can generate a dedicated address for your customer using either the [Blockradar dashboard ](https://dashboard.blockradar.co) or the API, depending on your workflow and integration needs. ### 1. Using the Dashboard The Blockradar dashboard provides a simple, user-friendly interface for generating new addresses. Generate address This screenshot demonstrates the process of generating a new address via the Blockradar dashboard. This method is ideal for manual address creation or for teams who prefer a graphical interface. ### 2. Using the API For programmatic or automated address generation, you can use the **Create Dedicated Address API**.\ This is useful for integrating address creation into your own applications or backend systems. To create a dedicated address for a customer, send a **`POST`** request to our [Create Dedicated Address API](/en/api-reference/addresses/generate-address). ```bash address.cmd theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/addresses \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "disableAutoSweep": "OPTIONAL_BOOLEAN", "enableGaslessWithdraw": "OPTIONAL_BOOLEAN", "metadata": "OPTIONAL_METADATA", "name": "OPTIONAL_ADDRESS_NAME", "showPrivateKey": "OPTIONAL_BOOLEAN" }' ``` ```js address.js theme={null} const options = { method: 'POST', headers: {'x-api-key': '', 'Content-Type': 'application/json'}, body: '{"metadata":"OPTIONAL_METADATA","name":"OPTIONAL_ADDRESS_NAME"}' }; fetch('https://api.blockradar.co/v1/wallets/{walletId}/addresses', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` ```php address.php theme={null} "https://api.blockradar.co/v1/wallets/{walletId}/addresses", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => "{\n \"metadata\": \"OPTIONAL_METADATA\",\n \"name\": \"OPTIONAL_ADDRESS_NAME\"\n}", CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "x-api-key: " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } ``` ### Response ```json theme={null} { "data": { "address": "0xe1037B45b48390285e5067424053fa35c478296b", "blockchain": { "createdAt": "2024-05-14T11:53:33.095Z", "derivationPath": "m/44'/60'/0'/0", "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf", "isActive": true, "isEvmCompatible": true, "logoUrl": "https://res.cloudinary.com/blockradar/image/upload/v1716800081/crypto-assets/ethereum-eth-logo_idraq2.png", "name": "ethereum", "slug": "ethereum", "symbol": "eth", "tokenStandard": "ERC20", "updatedAt": "2024-06-14T22:32:11.983Z" }, "configurations": { "aml": { "message": "Address is not sanctioned", "provider": "ofac", "status": "success" }, "disableAutoSweep": false, "enableGaslessWithdraw": false, "showPrivateKey": false }, "createdAt": "2024-10-23T11:13:40.446Z", "derivationPath": "m/44'/60'/0'/0/87", "id": "0a69c48a-6c6f-422c-bd6a-70de3306a3ac", "isActive": true, "metadata": { "user_id": 1 }, "name": "Customer 1", "network": "testnet", "type": "INTERNAL", "updatedAt": "2024-10-23T11:13:40.446Z" }, "message": "Address generated successfully", "statusCode": 200 } ``` ## Address Issuing and Indexing Blockradar separates two things that used to happen together when you create an address: * **Issuing** an address is cheap. It derives a new address from your master wallet and stores it, so you can hand it to a customer right away. * **Indexing** an address is the costly part. It places the address under on-chain monitoring so deposits are detected in real time, and indexing is what billing is based on. This lets you issue an address per customer up front and turn on indexing only when a customer shows intent to deposit, so you only pay for the addresses you actually monitor. ### Two independent switches Every address has two settings that control its state: | Setting | Values | Controls | | - | - | - | | `isActive` | `true` / `false` | The hard on/off switch. `false` disables the address entirely. | | `indexingStatus` | `ACTIVE` / `INACTIVE` | The monitoring and billing switch. `INACTIVE` means dormant: not watched, not billed. | An address is watched on-chain and counted for billing **only when both are on**: `isActive: true` and `indexingStatus: ACTIVE`. Existing addresses are unaffected. `indexingStatus` defaults to `ACTIVE`, so every address you already created, and every address you create without opting in, behaves exactly as before. ### Issue a dormant address When generating an address, pass `enableIndexing: false` to create a dormant address that is not watched and not billed. Omit the field or pass `true` for the default behavior (indexed immediately). A dormant address returns `"indexingStatus": "INACTIVE"` in the response. ```bash address.cmd theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/addresses \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "name": "Customer 123", "metadata": { "customerId": "123" }, "enableIndexing": false }' ``` ```js address.js theme={null} const options = { method: 'POST', headers: {'x-api-key': '', 'Content-Type': 'application/json'}, body: '{"name":"Customer 123","metadata":{"customerId":"123"},"enableIndexing":false}' }; fetch('https://api.blockradar.co/v1/wallets/{walletId}/addresses', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` ```php address.php theme={null} "https://api.blockradar.co/v1/wallets/{walletId}/addresses", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => "{\n \"name\": \"Customer 123\",\n \"metadata\": { \"customerId\": \"123\" },\n \"enableIndexing\": false\n}", CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "x-api-key: " ], ]); $response = curl_exec($curl); curl_close($curl); echo $response; ``` ### Enable indexing Enable indexing when the customer shows intent to deposit. This subscribes the address, starts real-time monitoring, and includes it in billing. The call takes no body and is idempotent (a no-op if indexing is already on). The `addressId` path parameter accepts either the address UUID or the on-chain address string. The response shows `"indexingStatus": "ACTIVE"`. It returns `400` if the address has been deactivated (`isActive: false`). ```bash indexing.cmd theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/indexing/enable \ --header 'x-api-key: ' ``` ```js indexing.js theme={null} const options = { method: 'POST', headers: {'x-api-key': ''} }; fetch('https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/indexing/enable', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` ```php indexing.php theme={null} "https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/indexing/enable", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => ["x-api-key: "], ]); $response = curl_exec($curl); curl_close($curl); echo $response; ``` ### Disable indexing Disable indexing for churned or inactive customers to stop billing for addresses you no longer watch. This stops monitoring and removes the address from billing on the next cycle. The call takes no body and is idempotent. Funds already received remain safe on-chain, and you can re-enable indexing later at no extra cost beyond normal billing. The response shows `"indexingStatus": "INACTIVE"`. ```bash indexing.cmd theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/indexing/disable \ --header 'x-api-key: ' ``` ```js indexing.js theme={null} const options = { method: 'POST', headers: {'x-api-key': ''} }; fetch('https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/indexing/disable', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` ```php indexing.php theme={null} "https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/indexing/disable", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => ["x-api-key: "], ]); $response = curl_exec($curl); curl_close($curl); echo $response; ``` ### Billing Address billing is a live count taken at each renewal, not a per-address charge. Each cycle, Blockradar counts the addresses that are active and indexed on mainnet and charges for usage above your plan limit. | Address state | Counted for billing | Watched on-chain | | - | - | - | | Dormant (`indexingStatus: INACTIVE`) | No — free | No | | Indexed (`indexingStatus: ACTIVE`) | Yes | Yes | | Disabled mid-cycle | Drops out on the next count | No | Generating dormant addresses bills nothing, and disabling indexing reclaims that slot on the next cycle. ### Best practices * Issue a dormant address when you assign it to a customer. It costs nothing. * Enable indexing when the customer shows intent to deposit (KYC passed, checkout opened, deposit screen viewed). * Always enable indexing before sharing an address for a real deposit, so the deposit is detected in real time. * Disable indexing for churned or inactive customers, then re-enable later when needed. Deposits made to a dormant address are not detected in real time. If a customer deposits to an address before indexing is enabled, the funds are safe on-chain but are not picked up automatically. Enable indexing and trigger the [Deposit Finder](/en/essentials/wallets#deposit-finder) to recover them. Always enable indexing before sharing an address to avoid this. ## Address Whitelisting This feature allows you to whitelist an external address to be monitored based on the wallet's requirements. Already have wallets issued by another provider? You can still plug them into Blockradar and monitor deposits without changing your existing setup. ### **Body Parameters** | Key | Required | Type | Description | | - | - | - | - | | `name` | false | string | The name of the address. | | `address` | true | string | The wallet address. | | `metadata` | false | object | Additional metadata for the address. This will be part of any transaction tied to this. | | `showPrivateKey` | false | boolean | If you want the address private key to be part of the response. | | `disableAutoSweep` | false | boolean | Disable automatic sweeping of assets sent to the address into your master wallet. | | `enableGaslessWithdraw` | false | boolean | Enable gasless transactions from this address. | | `privateKey` | false | string | The private key associated with the address. Required for executing actions securely. | ```bash address.cmd theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/addresses/whitelist \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "address": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6", "name": "Whitelisted Address", "metadata": {"purpose": "external_monitoring", "source": "manual"}, "showPrivateKey": false, "disableAutoSweep": false, "enableGaslessWithdraw": true, "privateKey": "0x1234567890abcdef..." }' ``` ```js address.js theme={null} const options = { method: 'POST', headers: {'x-api-key': '', 'Content-Type': 'application/json'}, body: '{"address":"ADDRESS_TO_WHITELIST","metadata":"OPTIONAL_METADATA","name":"OPTIONAL_ADDRESS_NAME"}' }; fetch('https://api.blockradar.co/v1/wallets/{walletId}/addresses/whitelist', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` ```php address.php theme={null} "https://api.blockradar.co/v1/wallets/{walletId}/addresses/whitelist", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => "{\n \"address\": \"ADDRESS_TO_WHITELIST\",\n \"metadata\": \"OPTIONAL_METADATA\",\n \"name\": \"OPTIONAL_ADDRESS_NAME\"\n}", CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "x-api-key": ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } ``` ### Response ```json theme={null} { "data": { "address": "0x3375154fa32Cb434B044E73a2582C4D2E6518AE4", "blockchain": { "createdAt": "2024-05-27T08:31:14.966Z", "derivationPath": "m/44'/60'/0'/0", "id": "74733889-4ecd-403e-9840-94e87c043f24", "isActive": true, "isEvmCompatible": true, "logoUrl": "https://res.cloudinary.com/blockradar/image/upload/v1716800080/crypto-assets/Base_Network_Logo_vqyh7r.png", "name": "base", "slug": "base", "symbol": "eth", "tokenStandard": null, "updatedAt": "2024-10-27T07:52:16.115Z" }, "configurations": { "aml": { "message": "Address is not sanctioned", "provider": "ofac", "status": "success" } }, "createdAt": "2024-11-11T16:57:19.160Z", "derivationPath": null, "id": "b87901a2-45c1-4d2d-8ee7-205ef0c4ddf1", "isActive": true, "metadata": null, "name": "External address", "network": "testnet", "type": "EXTERNAL", "updatedAt": "2024-11-11T16:57:19.160Z" }, "message": "Address whitelisted successfully", "statusCode": 200 } ``` ## Testing Addresses generated via a testnet master wallet can only receive assets on the testnet. Here is a list of places where you can get testnet assets to test with: * **Ethereum** - Get test USDC here: [Circle](https://faucet.circle.com/) * **Binance Smart Chain** - Get test USDT here: [Binance](https://www.bnbchain.org/en/testnet-faucet) * **Polygon** - Get test USDC here: [Circle](https://faucet.circle.com/) * **Base** - Get test USDC here: [Circle](https://faucet.circle.com/) * **Tron** - Get test USDT here: [Nileex](https://nileex.io/join/getJoinPage) * **Solana** - Get test USDC here: [Circle](https://faucet.circle.com) * **Optimism** - Get test USDC here: [Circle](https://faucet.circle.com) * **Arbitrum** - Get test USDC here: [Circle](https://faucet.circle.com) * **Celo** - Get test USDC here: [Circle](https://faucet.circle.com)

Happy hacking! 💚 # Signing Source: https://docs.blockradar.co/en/essentials/signing Sign messages, typed data, and raw transactions with your wallet keys In a nutshell
The Blockradar Signing API lets you cryptographically sign plain text messages, structured data (typed data), and raw transactions using your wallet's private keys. Sign messages to prove wallet ownership. Sign transactions built externally (e.g., Jupiter swaps on Solana) without exposing private keys, and optionally broadcast them on-chain.
## Prerequisites Before using the Signing API, ensure you have: Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. Create a master wallet from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Wallets** and create one for your target blockchain. You'll need the `walletId` for signing operations. Choose between **Testnet** (for development) or **Mainnet** (for production). Wallets are isolated per environment. ## How It Works The Signing API produces a cryptographic signature that proves you control a specific wallet address. The signed output can be verified by any third party without accessing your private keys. Sign plain text messages to prove wallet ownership. Works on all supported blockchains: EVM, Tron, Solana, and Stellar. Sign structured data following the EIP-712 standard. Used for gasless approvals (EIP-2612 Permit) and authorized transfers (EIP-3009). EVM-only. Sign raw transactions built externally. Build a swap on Jupiter, a contract call via ethers.js, or a TronWeb transfer, then send the unsigned tx and get it signed without exposing private keys. Sign and broadcast a raw transaction in one step. Blockradar signs the transaction and submits it on-chain via a reliable queue with automatic retries. ### Common use cases * **Third-party provider registration**: Prove you own an address when onboarding with services like Iron, Circle, or other DeFi protocols * **Gasless token approvals**: Sign EIP-2612 Permit messages to authorize token spending without an on-chain transaction * **Authorized transfers**: Sign EIP-3009 TransferWithAuthorization messages for delegated transfers, such as [agent payments over x402](/en/use-cases/make-agent-payments) * **Off-chain attestations**: Create verifiable proofs of intent or agreement tied to a wallet address * **External swap execution**: Build a Jupiter swap on Solana, sign it with Blockradar, and broadcast it on-chain * **Custom contract interactions**: Build any transaction externally and have Blockradar sign and/or submit it ## Master Wallet vs Child Address The Signing API is available at two levels: Sign using the master wallet's keys. Ideal for treasury-level operations and provider integrations. Sign using a specific child address's keys. Use when the third party requires a signature from a deposit address. ### Endpoints | Operation | Master Wallet | Child Address | | - | - | - | | Sign Message | `POST /v1/wallets/{walletId}/signing/message` | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/message` | | Sign Typed Data | `POST /v1/wallets/{walletId}/signing/typed-data` | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/typed-data` | | Sign Transaction | `POST /v1/wallets/{walletId}/signing/transaction` | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/transaction` | | Sign + Broadcast | `POST /v1/wallets/{walletId}/signing/broadcast` | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/broadcast` | *** ## Message Signing Sign a plain text message with your wallet's private key. The API signs the message, verifies the signature matches the wallet address, and returns both the signature and a transaction record. ### Supported Blockchains | Blockchain | Signing Standard | Signature Format | | - | - | - | | EVM (Ethereum, Polygon, BSC, Base, Arbitrum, Optimism, Celo) | EIP-191 (personal\_sign) | Hex-encoded with `r`, `s`, `v` components | | Tron | TronWeb signMessageV2 | Hex-encoded string | | Solana | Ed25519 | Base58-encoded string | | Stellar | SEP-53 (Ed25519 over the hashed, prefixed message) | Base64-encoded string | Stellar message signing follows [SEP-53](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0053.md), the Stellar standard for signing arbitrary messages. The signed payload is `SHA-256("Stellar Signed Message:\n" + message)`, signed with the account's Ed25519 key, and the signature is base64-encoded. To verify it, apply the same prefix and hash before checking the signature against the signer's public key. The Stellar CLI `stellar message` command and the SEP-53 helpers in the Stellar SDK do this for you. A raw Ed25519 signature over the unprefixed message will not verify. ### Request Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `message` | string | Yes | The plain text message to sign. Maximum 4,096 characters. | | `reference` | string | No | Your internal tracking ID. Use for idempotency. Duplicate references are rejected. | | `metadata` | object | No | Custom key-value pairs stored with the transaction record. | ### Message Signing Example ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/signing/message \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "message": "Please sign this message to verify your wallet ownership for Iron provider registration.", "reference": "iron-verification-001", "metadata": { "provider": "iron", "purpose": "wallet-verification" } }' ``` ```javascript JavaScript theme={null} const response = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/signing/message`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ message: 'Please sign this message to verify your wallet ownership for Iron provider registration.', reference: 'iron-verification-001', metadata: { provider: 'iron', purpose: 'wallet-verification' } }) } ).then(r => r.json()); console.log('Signature:', response.data.hash); console.log('Signed transaction:', response.data.signedTransaction); ``` ```php PHP theme={null} "https://api.blockradar.co/v1/wallets/{walletId}/signing/message", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ "message" => "Please sign this message to verify your wallet ownership for Iron provider registration.", "reference" => "iron-verification-001", "metadata" => [ "provider" => "iron", "purpose" => "wallet-verification" ] ]), CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "x-api-key: " ], ]); $response = curl_exec($curl); curl_close($curl); echo $response; ``` ### EVM Response ```json theme={null} { "message": "Message signed successfully", "statusCode": 200, "data": { "id": "770f9100-7338-4823-b1ce-3658fc67db09", "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b", "status": "SUCCESS", "type": "SIGNED", "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a", "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a", "signedTransaction": { "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133", "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3", "v": 27, "signature": "0xdb095e6cbf...b31b" }, "reference": "iron-verification-001", "metadata": { "provider": "iron", "purpose": "wallet-verification" }, "confirmed": true, "createdAt": "2025-03-02T19:00:52.000Z" } } ``` ### Tron / Solana / Stellar Response For Tron, Solana, and Stellar, the `signedTransaction` object contains only the `signature` field (no `r`, `s`, `v` components): ```json theme={null} { "message": "Message signed successfully", "statusCode": 200, "data": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "hash": "3xYkZ9...", "status": "SUCCESS", "type": "SIGNED", "senderAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y", "recipientAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y", "signedTransaction": { "signature": "3xYkZ9..." }, "reference": "tron-verification-001", "confirmed": true, "createdAt": "2025-03-02T19:00:52.000Z" } } ``` ### Response Fields | Field | Description | | - | - | | `id` | Unique transaction ID for the signing record | | `hash` | The cryptographic signature. For EVM: hex string. For Tron: hex string. For Solana: base58 string. For Stellar: base64 string. | | `status` | Always `SUCCESS` for completed signatures | | `type` | Always `SIGNED` for signing transactions | | `senderAddress` | The wallet address that produced the signature | | `signedTransaction` | Signature components. EVM includes `r`, `s`, `v`, and full `signature`. Tron, Solana, and Stellar include `signature` only. | | `reference` | Your provided reference string (if any) | | `metadata` | Your provided metadata object (if any) | *** ## Typed Data Signing (EVM Only) Sign structured data following the EIP-712 standard. This is used for gasless approvals, delegated transfers, and other on-chain authorization flows that require a structured signature. Typed data signing is only available for EVM-compatible blockchains (Ethereum, Polygon, BSC, Base, Arbitrum, Optimism, Celo). Tron, Solana, and Stellar do not support EIP-712. ### Supported Standards | Standard | Use Case | | - | - | | EIP-712 | Generic structured data signing | | EIP-2612 (Permit) | Gasless token approvals. Approve spending without an on-chain transaction | | EIP-3009 (TransferWithAuthorization) | Delegated transfers. Authorize a transfer that a third party submits | EIP-3009 is how AI agents pay for APIs over the x402 protocol. See [Make Agent Payments](/en/use-cases/make-agent-payments) for the full flow, from the `402` response to settlement. ### Request Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `domain` | object | Yes | EIP-712 domain separator. Includes `name`, `version`, `chainId`, and `verifyingContract`. | | `types` | object | Yes | Type definitions for the structured data. | | `message` | object | Yes | The data to sign, conforming to the type definitions. | ### EIP-2612 Permit Example ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/signing/typed-data \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "domain": { "name": "USD Coin", "version": "2", "chainId": 11155111, "verifyingContract": "0xa0b86a33e6441b8c4c8c0c077bcdd28571685701" }, "types": { "Permit": [ { "name": "owner", "type": "address" }, { "name": "spender", "type": "address" }, { "name": "value", "type": "uint256" }, { "name": "nonce", "type": "uint256" }, { "name": "deadline", "type": "uint256" } ] }, "message": { "owner": "0x742d35cc6634c0532925a3b8d4c9db96c4b4d8b6", "spender": "0x8ba1f109551bd432803012645aac136c4c8c8c0c", "value": "1000000000", "nonce": "0", "deadline": "1641081600" } }' ``` ```javascript JavaScript theme={null} const response = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/signing/typed-data`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ domain: { name: 'USD Coin', version: '2', chainId: 11155111, verifyingContract: '0xa0b86a33e6441b8c4c8c0c077bcdd28571685701' }, types: { Permit: [ { name: 'owner', type: 'address' }, { name: 'spender', type: 'address' }, { name: 'value', type: 'uint256' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' } ] }, message: { owner: '0x742d35cc6634c0532925a3b8d4c9db96c4b4d8b6', spender: '0x8ba1f109551bd432803012645aac136c4c8c8c0c', value: '1000000000', nonce: '0', deadline: '1641081600' } }) } ).then(r => r.json()); console.log('Signature:', response.data.hash); console.log('r:', response.data.signedTransaction.r); console.log('s:', response.data.signedTransaction.s); console.log('v:', response.data.signedTransaction.v); ``` ### Typed Data Response ```json theme={null} { "message": "Typed data signed successfully", "statusCode": 200, "data": { "id": "770f9100-7338-4823-b1ce-3658fc67db09", "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b", "status": "SUCCESS", "type": "SIGNED", "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a", "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a", "signedTransaction": { "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133", "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3", "v": 27, "signature": "0xdb095e6cbf...b31b" }, "confirmed": true, "createdAt": "2025-03-02T19:00:52.000Z" } } ``` ### Domain Object Fields | Field | Type | Required | Description | | - | - | - | - | | `name` | string | Yes | The name of the signing domain (e.g., the token name or dApp name) | | `version` | string | Yes | The version of the domain | | `chainId` | number | Yes | The chain ID. Must match the wallet's blockchain network. | | `verifyingContract` | string | Yes | The contract address that will verify the signature | | `salt` | string | No | Optional domain salt for EIP-712 v4 | Chain ID validation
The `chainId` in your domain object must match the chain ID of the wallet's blockchain network. If they don't match, the API returns a `400 Chain ID mismatch` error.
*** ## Child Address Signing Sign messages, typed data, transactions, or broadcast using a specific child address instead of the master wallet. All four signing operations are available for child addresses: ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/signing/message \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "message": "Verify ownership of deposit address for provider onboarding.", "reference": "address-verify-001" }' ``` ```javascript JavaScript theme={null} const response = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/addresses/${addressId}/signing/message`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ message: 'Verify ownership of deposit address for provider onboarding.', reference: 'address-verify-001' }) } ).then(r => r.json()); console.log('Signature:', response.data.hash); ``` Child address signing follows the same request and response format as master wallet signing. The only difference is the endpoint URL, which includes the `addressId`. *** ## Webhook Events Signing operations trigger a webhook with the transaction record: | Event | Description | | - | - | | `signed.success` | Signing completed successfully. For message/typed data/transaction sign, this fires immediately. For broadcast, this fires after on chain confirmation. | | `signed.failed` | Transaction broadcast failed after all retries were exhausted. Only applies to the `/broadcast` endpoint. | ### Webhook Payload (Message or Typed Data Signing) ```json theme={null} { "event": "signed.success", "data": { "id": "770f9100-7338-4823-b1ce-3658fc67db09", "reference": "iron-verification-001", "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a", "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a", "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b", "confirmed": true, "status": "SUCCESS", "type": "SIGNED", "createdChannel": "api", "reason": "Message signed", "network": "testnet", "chainId": 11155111, "metadata": { "provider": "iron", "purpose": "wallet-verification" }, "signedTransaction": { "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133", "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3", "v": 27, "signature": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b" }, "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2025-03-02T19:00:52.000Z", "updatedAt": "2025-03-02T19:00:52.000Z", "wallet": { "id": "d236a191-c1d4-423c-a439-54ce6542ca41", "name": "Ethereum Master Wallet", "address": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf", "name": "ethereum", "symbol": "eth", "slug": "ethereum", "isEvmCompatible": true, "tokenStandard": "ERC20" }, "beneficiary": null } } ``` ### Webhook Payload (Transaction Signing) For transaction signing, the `signedTransaction` field is a string (not an object). The format depends on the chain. ```json theme={null} { "event": "signed.success", "data": { "id": "782942da-48b0-416b-924b-8f657ae637a7", "reference": "52TQawmiqYpNiWD2Ks0P", "senderAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446", "recipientAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446", "hash": "0xac4c73ca084608ac6b981e54db948dc80c15b4ea3ffd0c9f5781f3af7ad6fe51", "confirmed": true, "status": "SUCCESS", "type": "SIGNED", "createdChannel": "api", "reason": "Transaction signed", "network": "testnet", "chainId": 11155111, "metadata": null, "signedTransaction": "0x02f87383aa36a763843b9aca008459682f0082520894000000000000000000000000000000000000dead865af3107a400080c080a0b760...", "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2026-03-19T13:34:24.937Z", "updatedAt": "2026-03-19T13:34:24.937Z", "wallet": { "id": "3f9aca5c-38ee-4e1d-ab67-c084a2e37bb2", "name": "Ethereum Wallet", "address": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf", "name": "ethereum", "symbol": "eth", "slug": "ethereum", "isEvmCompatible": true, "tokenStandard": "ERC20" }, "beneficiary": null } } ``` ### Webhook Payload (Broadcast Success) After the broadcast queue confirms the transaction on chain, you receive this webhook. The `hash` field is updated to the on chain transaction hash and `confirmed` changes to `true`. ```json theme={null} { "event": "signed.success", "data": { "id": "f3efdbaa-a1f8-4365-b3b4-768413c9a92b", "reference": "docs-test-broadcast", "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "hash": "5bKNw9RX8aXkrK1VEHg5aPa1xtckpShPyenSRET4mUBXh5uCkWLFV5MhGRi4cMACDJvFn6VfkoKb75Pk4KYw6xtw", "confirmed": true, "status": "SUCCESS", "type": "SIGNED", "createdChannel": "api", "reason": "Transaction signed and broadcast", "network": "testnet", "chainId": 103, "metadata": null, "signedTransaction": "AeWpW65y80rSu+TU0CSrcvFNovyDiybKRjSskCpfffAFLM0GIYzx...", "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2026-03-19T13:35:09.921Z", "updatedAt": "2026-03-19T13:35:09.921Z", "wallet": { "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311", "name": "Solana Testnet Wallet", "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "196badf5-380f-4480-ab4a-d0e4304e91f0", "name": "solana", "symbol": "sol", "slug": "solana", "isEvmCompatible": false, "tokenStandard": null }, "beneficiary": null } } ``` ### Webhook Payload (Broadcast Failed) If the broadcast fails permanently after all retry attempts, you receive this webhook. The `status` is `FAILED` and `confirmed` remains `false`. ```json theme={null} { "event": "signed.failed", "data": { "id": "f3efdbaa-a1f8-4365-b3b4-768413c9a92b", "reference": "docs-test-broadcast", "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "hash": "5bKNw9RX8aXkrK1VEHg5aPa1xtckpShPyenSRET4mUBXh5uCkWLFV5MhGRi4cMACDJvFn6VfkoKb75Pk4KYw6xtw", "confirmed": false, "status": "FAILED", "type": "SIGNED", "createdChannel": "api", "reason": "Transaction broadcast failed", "network": "testnet", "chainId": 103, "metadata": null, "signedTransaction": "AeWpW65y80rSu+TU0CSrcvFNovyDiybKRjSskCpfffAFLM0GIYzx...", "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2026-03-19T13:35:09.921Z", "updatedAt": "2026-03-19T13:35:09.921Z", "wallet": { "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311", "name": "Solana Testnet Wallet", "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "196badf5-380f-4480-ab4a-d0e4304e91f0", "name": "solana", "symbol": "sol", "slug": "solana", "isEvmCompatible": false, "tokenStandard": null }, "beneficiary": null } } ``` *** ## Transaction Signing Sign a raw, unsigned transaction built externally. You build the transaction using any SDK (ethers.js, TronWeb, Solana web3.js, Jupiter API), then send the serialized unsigned transaction to Blockradar for signing and/or broadcasting, without needing to build or manage your own infrastructure or blockchain nodes. ### Supported Blockchains and Formats | Blockchain | `transaction` field format | How to build | | - | - | - | | Solana | Base64 of `VersionedTransaction.serialize()` | Jupiter API `/swap` response, or `@solana/web3.js` TransactionMessage | | EVM | JSON string of `{to, value, data, nonce, chainId, gasLimit, maxFeePerGas, ...}` | `ethers.js` populateTransaction() | | Tron | JSON string of TronWeb transaction object `{txID, raw_data, raw_data_hex}` | `tronWeb.transactionBuilder.triggerSmartContract()` | | Stellar | Base64 of the transaction envelope XDR (`transaction.toXDR()`) | `@stellar/stellar-sdk` `TransactionBuilder`, then `.toXDR()`. Soroban transactions must be simulated and assembled first — see [Stellar Soroban Transactions](#stellar-soroban-transactions) | ### Request Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `transaction` | string | Yes | The serialized unsigned transaction. Format depends on the blockchain. | | `reference` | string | No | Your internal tracking ID. | | `metadata` | object | No | Custom key-value pairs stored with the transaction record. | ### Transaction Signing Example (Solana + Jupiter) ```javascript JavaScript theme={null} import { Connection, PublicKey, VersionedTransaction } from '@solana/web3.js'; // Step 1: Build the swap transaction via Jupiter API const quoteResponse = await fetch( 'https://quote-api.jup.ag/v6/quote?inputMint=SOL&outputMint=USDC&amount=1000000&slippageBps=50' ).then(r => r.json()); const swapResponse = await fetch('https://quote-api.jup.ag/v6/swap', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ quoteResponse, userPublicKey: walletAddress, // Your Blockradar wallet's Solana address wrapAndUnwrapSol: true, }) }).then(r => r.json()); // Step 2: Send the unsigned transaction to Blockradar for signing const signResponse = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/signing/transaction`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ transaction: swapResponse.swapTransaction, // Base64 VersionedTransaction reference: 'jupiter-swap-001' }) } ).then(r => r.json()); console.log('Signed tx:', signResponse.data.signedTransaction); console.log('Hash:', signResponse.data.hash); ``` ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/signing/transaction \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "transaction": "", "reference": "jupiter-swap-001" }' ``` ### Transaction Signing Example (EVM) ```javascript JavaScript theme={null} import { ethers } from 'ethers'; // Step 1: Build the unsigned transaction const provider = new ethers.providers.JsonRpcProvider('https://rpc.sepolia.org'); const nonce = await provider.getTransactionCount(walletAddress); const feeData = await provider.getFeeData(); const unsignedTx = JSON.stringify({ to: '0xRecipientAddress', value: ethers.utils.parseEther('0.01').toHexString(), nonce, chainId: 11155111, // Sepolia gasLimit: ethers.utils.hexlify(21000), maxFeePerGas: feeData.maxFeePerGas.toHexString(), maxPriorityFeePerGas: feeData.maxPriorityFeePerGas.toHexString(), type: 2, }); // Step 2: Send to Blockradar for signing const signResponse = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/signing/transaction`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ transaction: unsignedTx, reference: 'eth-transfer-001' }) } ).then(r => r.json()); // The signed transaction can be broadcast via any RPC // await provider.sendTransaction(signResponse.data.signedTransaction); ``` ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/signing/transaction \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "transaction": "{\"to\":\"0xRecipient\",\"value\":\"0x2386F26FC10000\",\"nonce\":0,\"chainId\":11155111,\"gasLimit\":\"0x5208\",\"maxFeePerGas\":\"0x59682F00\",\"maxPriorityFeePerGas\":\"0x3B9ACA00\",\"type\":2}", "reference": "eth-transfer-001" }' ``` ### Sign-Only Response (EVM) ```json theme={null} { "statusCode": 200, "message": "Transaction signed successfully", "data": { "id": "782942da-48b0-416b-924b-8f657ae637a7", "reference": "52TQawmiqYpNiWD2Ks0P", "senderAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446", "recipientAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446", "hash": "0xac4c73ca084608ac6b981e54db948dc80c15b4ea3ffd0c9f5781f3af7ad6fe51", "confirmed": true, "status": "SUCCESS", "type": "SIGNED", "createdChannel": "api", "reason": "Transaction signed", "network": "testnet", "chainId": 11155111, "metadata": null, "signedTransaction": "0x02f87383aa36a763843b9aca008459682f0082520894000000000000000000000000000000000000dead865af3107a400080c080a0b760...", "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2026-03-19T13:34:24.937Z", "updatedAt": "2026-03-19T13:34:24.937Z", "wallet": { "id": "3f9aca5c-38ee-4e1d-ab67-c084a2e37bb2", "name": "Ethereum Wallet", "address": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf", "name": "ethereum", "symbol": "eth", "slug": "ethereum", "isEvmCompatible": true, "tokenStandard": "ERC20" }, "beneficiary": null } } ``` ### Sign-Only Response (Solana) ```json theme={null} { "statusCode": 200, "message": "Transaction signed successfully", "data": { "id": "02f404a5-d13e-4bcf-8ad5-c5f51c04fa49", "reference": "qZmQqDiIp9owMzQJcDbv", "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "hash": "TjphHHAzjhRBn8t1qhhTRWpUxvkATBnzeRBB8fonWkYpR1gDh4t99rmgah3hrwoCbD3L9Ex1a7SYjjX2TePio3s", "confirmed": true, "status": "SUCCESS", "type": "SIGNED", "createdChannel": "api", "reason": "Transaction signed", "network": "testnet", "chainId": 103, "metadata": null, "signedTransaction": "ARcO4DT2IYg/wemCZy4iYXVRzlGruYHUTGqIcbWI/uWeWet6MNZKVVvUF4yT5GQjRqrb1QD1TaAoflyXXatxzAaAAQABA...", "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2026-03-19T13:38:45.326Z", "updatedAt": "2026-03-19T13:38:45.326Z", "wallet": { "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311", "name": "Solana Testnet Wallet", "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "196badf5-380f-4480-ab4a-d0e4304e91f0", "name": "solana", "symbol": "sol", "slug": "solana", "isEvmCompatible": false, "tokenStandard": null }, "beneficiary": null } } ``` ### Sign-Only Response (Tron) ```json theme={null} { "statusCode": 200, "message": "Transaction signed successfully", "data": { "id": "af44218f-d38b-472b-9834-49f461a20fd4", "reference": "J6RugzxXI6cdpeMXrhh", "senderAddress": "TMUZSkS3aF1pZxnTokWikUQH7SYt3bNb6G", "recipientAddress": "TMUZSkS3aF1pZxnTokWikUQH7SYt3bNb6G", "hash": "3180f971f692a78f62050278149d746abd946fbd1797a414f5ad0d5ed45c902b", "confirmed": true, "status": "SUCCESS", "type": "SIGNED", "createdChannel": "api", "reason": "Transaction signed", "network": "testnet", "chainId": 3448148188, "metadata": null, "signedTransaction": "{\"visible\":false,\"txID\":\"3180f971f692a78f...\",\"raw_data\":{\"contract\":[{\"parameter\":{\"value\":{\"to_address\":\"418840e6c55b9ada...\",\"owner_address\":\"417e3682ec8f5b98...\",\"amount\":1000000},\"type_url\":\"type.googleapis.com/protocol.TransferContract\"},\"type\":\"TransferContract\"}],\"ref_block_bytes\":\"513f\",\"ref_block_hash\":\"08c7d5da0ddd12fb\",\"expiration\":1773927585000,\"timestamp\":1773927525000},\"signature\":[\"d5adac23f23414083ef4f93b995a4a18...\"]}", "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2026-03-19T13:38:47.096Z", "updatedAt": "2026-03-19T13:38:47.096Z", "wallet": { "id": "c4bbebea-6cec-4021-b842-ffead75fd0f1", "name": "Tron Wallet", "address": "TMUZSkS3aF1pZxnTokWikUQH7SYt3bNb6G", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "fa91a922-3838-45f6-8a88-a4c771e1443a", "name": "tron", "symbol": "trx", "slug": "tron", "isEvmCompatible": false, "tokenStandard": "TRC20" }, "beneficiary": null } } ``` For transaction signing, `signedTransaction` is a **string**, not an object. This is different from message signing where it returns an object with signature components like `r`, `s`, `v`. ### `signedTransaction` Format by Chain | Chain | Type | Format | What to do with it | | - | - | - | - | | Solana | string | Base64 encoded bytes of the signed VersionedTransaction | Decode to bytes and pass to `connection.sendRawTransaction()` | | EVM | string | Hex string starting with `0x` containing the RLP encoded signed transaction | Pass directly to `eth_sendRawTransaction` or `provider.sendTransaction()` | | Tron | string | JSON string of the signed transaction object containing a `signature` array | Parse with `JSON.parse()` and pass to `tronWeb.trx.sendRawTransaction()` | | Stellar | string | Base64 of the signed transaction envelope XDR | Classic transactions: submit via Horizon `server.submitTransaction(TransactionBuilder.fromXDR(...))`. Soroban transactions: submit via Soroban RPC `server.sendTransaction(...)` — Horizon will reject them. Or use the `/broadcast` endpoint for either | ### `hash` Field by Chain | Chain | Format | How it is derived | | - | - | - | | Solana | Base58 string | First signature from the signed transaction | | EVM | Hex string starting with `0x` | Keccak256 hash of the signed transaction bytes | | Tron | Hex string | The `txID` field from the transaction object, computed during transaction building | | Stellar | Hex string | SHA-256 transaction hash (`transaction.hash()`) over the signed envelope | *** ## Transaction Broadcast Sign **and** broadcast a raw transaction in one step. Blockradar signs the transaction, then submits it on-chain via a reliable queue with automatic retries. The API returns immediately with `PENDING` status. You'll receive a `signed.success` or `signed.failed` webhook when the on-chain result is confirmed. Broadcast requires testnet/mainnet funds in the wallet to pay gas fees. The transaction must be valid and not expired (Solana blockhashes expire in \~90 seconds). ### Stellar Soroban Transactions The signing endpoints accept Stellar Soroban transactions — a [Stellar Asset Contract](https://developers.stellar.org/docs/tokens/stellar-asset-contract) transfer or a custom contract invocation — in addition to classic transactions. Pass the same base64 transaction envelope XDR format; Blockradar detects Soroban transactions automatically and submits them via Soroban RPC instead of Horizon. Two Stellar rules to follow: 1. **Simulate and assemble before signing.** A Soroban transaction must be simulated against Soroban RPC and assembled with the simulation results (resource footprint and fees) before it is signed. Submitting an unassembled transaction fails on-chain. 2. **Rebuild on stale sequence.** If the wallet's sequence number has moved by submission time, the API returns an error stating the transaction is stale (`tx_bad_seq`) and must be rebuilt and re-signed. Build a fresh transaction with the current sequence number and try again. ```javascript JavaScript theme={null} import { rpc, TransactionBuilder, Networks, Contract, Address, nativeToScVal } from '@stellar/stellar-sdk'; const server = new rpc.Server('https://soroban-testnet.stellar.org'); const account = await server.getAccount(walletAddress); // your Blockradar wallet address // Build a Stellar Asset Contract transfer (USDC) const contract = new Contract(usdcContractId); const tx = new TransactionBuilder(account, { fee: '1000000', networkPassphrase: Networks.TESTNET }) .addOperation( contract.call( 'transfer', Address.fromString(walletAddress).toScVal(), Address.fromString(recipientAddress).toScVal(), // G..., M..., or C... nativeToScVal('1000000', { type: 'i128' }) // 0.1 USDC (7 decimals) ) ) .setTimeout(300) .build(); // Simulate and assemble — required for Soroban transactions const simulation = await server.simulateTransaction(tx); const assembled = rpc.assembleTransaction(tx, simulation).build(); // Blockradar signs and submits via Soroban RPC const response = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/signing/broadcast`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ transaction: assembled.toXDR(), reference: 'soroban-usdc-transfer-001' }) } ).then(r => r.json()); ``` If a Soroban transaction is submitted on-chain but confirmation polling times out, the response includes the transaction hash with the message `Soroban transaction submitted but not yet confirmed`. Reconcile the outcome by looking up that hash — do not rebuild and resubmit, as the original transaction may still confirm and cause a double spend. ### Request Same parameters as transaction signing: | Parameter | Type | Required | Description | | - | - | - | - | | `transaction` | string | Yes | The serialized unsigned transaction. | | `reference` | string | No | Your internal tracking ID. | | `metadata` | object | No | Custom key-value pairs. | ### Broadcast Example ```javascript JavaScript theme={null} // Build the unsigned tx (same as sign-only examples above) const unsignedTx = swapResponse.swapTransaction; // Jupiter base64 tx // Sign + broadcast in one call const broadcastResponse = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/signing/broadcast`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ transaction: unsignedTx, reference: 'jupiter-swap-broadcast-001' }) } ).then(r => r.json()); console.log('Status:', broadcastResponse.data.status); // "PENDING" console.log('Transaction ID:', broadcastResponse.data.id); // Wait for webhook: signed.success or signed.failed ``` ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/signing/broadcast \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "transaction": "", "reference": "jupiter-swap-broadcast-001" }' ``` ### Broadcast Response (Solana Example, immediate) ```json theme={null} { "statusCode": 200, "message": "Transaction signed and broadcast initiated", "data": { "id": "f3efdbaa-a1f8-4365-b3b4-768413c9a92b", "reference": "docs-test-broadcast", "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "hash": "5bKNw9RX8aXkrK1VEHg5aPa1xtckpShPyenSRET4mUBXh5uCkWLFV5MhGRi4cMACDJvFn6VfkoKb75Pk4KYw6xtw", "confirmed": false, "status": "PENDING", "type": "SIGNED", "createdChannel": "api", "reason": "Transaction signed and broadcast", "network": "testnet", "chainId": 103, "metadata": null, "signedTransaction": "AeWpW65y80rSu+TU0CSrcvFNovyDiybKRjSskCpfffAFLM0GIYzx...", "amount": null, "amountUSD": "0.00", "fee": null, "feeUSD": null, "currency": "USD", "createdAt": "2026-03-19T13:35:09.921Z", "updatedAt": "2026-03-19T13:35:09.921Z", "wallet": { "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311", "name": "Solana Testnet Wallet", "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw", "isActive": true, "status": "ACTIVE", "network": "testnet" }, "asset": null, "blockchain": { "id": "196badf5-380f-4480-ab4a-d0e4304e91f0", "name": "solana", "symbol": "sol", "slug": "solana", "isEvmCompatible": false, "tokenStandard": null }, "beneficiary": null } } ``` ### Broadcast Lifecycle The transaction goes through these states: | Status | Meaning | | - | - | | `PENDING` | Transaction signed, broadcast queued. You receive this in the HTTP response. | | `SUCCESS` | Transaction confirmed on-chain. Webhook `signed.success` is sent. | | `FAILED` | Broadcast failed after all retries exhausted. Webhook `signed.failed` is sent. | The broadcast queue retries up to 10 times with 5-minute intervals. For Solana, if the blockhash expires, retries will not help. You'll need to rebuild the transaction with a fresh blockhash. For Stellar, a stale sequence number (`tx_bad_seq`) similarly requires rebuilding and re-signing the transaction. *** ## Complete Flow Example Here's a full implementation for signing a message and submitting the signature to a third-party provider: ```javascript theme={null} async function signAndVerifyWithProvider(walletId, providerMessage) { const apiKey = process.env.BLOCKRADAR_API_KEY; const baseUrl = 'https://api.blockradar.co/v1'; // Step 1: Sign the message const signResponse = await fetch( `${baseUrl}/wallets/${walletId}/signing/message`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ message: providerMessage, reference: `provider-verify-${Date.now()}` }) } ).then(r => r.json()); if (signResponse.statusCode !== 200) { throw new Error(`Signing failed: ${signResponse.message}`); } const { hash, senderAddress } = signResponse.data; // Step 2: Submit the signature to the third-party provider // The provider can verify the signature matches the wallet address // without accessing your private keys return { address: senderAddress, signature: hash, message: providerMessage }; } // Usage signAndVerifyWithProvider( 'wallet-uuid', 'I authorize Iron to manage assets on my behalf.' ); ``` *** ## Error Responses ```json theme={null} { "message": "Wallet not found", "statusCode": 404 } ``` The `walletId` does not exist or does not belong to your business. ```json theme={null} { "message": "Address not found", "statusCode": 404 } ``` The `addressId` does not exist or is not associated with the specified wallet. ```json theme={null} { "message": "Typed data signing is only supported for EVM blockchains", "statusCode": 400 } ``` Typed data signing (EIP-712) is only available on EVM-compatible chains. Use message signing for Tron, Solana, and Stellar. ```json theme={null} { "message": "Chain ID mismatch", "statusCode": 400 } ``` The `chainId` in your typed data domain object does not match the wallet's blockchain network. ```json theme={null} { "message": "Signature verification failed", "statusCode": 400 } ``` Internal round-trip verification failed. This indicates a system error. Please contact support. ```json theme={null} { "message": "Invalid transaction format: expected a base64-encoded Solana VersionedTransaction", "statusCode": 400 } ``` The `transaction` field is not valid base64, or the decoded bytes are not a valid Solana VersionedTransaction. ```json theme={null} { "message": "Invalid transaction format: expected a JSON string", "statusCode": 400 } ``` The `transaction` field is not valid JSON. EVM and Tron transactions must be JSON-stringified objects. ```json theme={null} { "message": "Invalid transaction format: expected a base64-encoded Stellar transaction envelope XDR", "statusCode": 400 } ``` The `transaction` field is not a valid base64-encoded Stellar transaction envelope XDR. Build the transaction with `@stellar/stellar-sdk` and pass `transaction.toXDR()`. *** ## Best Practices ### Security * **Use references**: Track signing operations with unique reference IDs for audit trails and idempotency * **Verify the message**: Before signing, confirm the message content matches what the third-party service expects * **Limit message length**: Messages are capped at 4,096 characters. Keep messages concise and specific ### Integration * **No gas fees**: Signing operations are off-chain and do not require native token balance * **Immediate response**: Signatures are generated synchronously. No polling or webhook waiting required for the signature itself * **Listen for webhooks**: Use webhooks to maintain an audit trail of all signing events ### Typed Data * **Match chain IDs**: The `chainId` in your domain must match the wallet's network. Use sandbox (testnet) chain IDs for testing and production (mainnet) chain IDs for live operations * **Check the contract**: The `verifyingContract` must be the contract that will verify the signature on-chain ### Transaction Signing * **Build the transaction with the correct sender**: The unsigned transaction must use the wallet or child address public key as the fee payer (Solana) or sender (EVM/Tron). If the key does not match, signing will fail. * **Solana blockhashes expire quickly**: Solana blockhashes are valid for about 60 to 90 seconds. Build the transaction and call the signing endpoint promptly. If using broadcast, the queue retries will not help once the blockhash expires. * **EVM nonce management**: Set the nonce correctly. If the nonce is already used, the broadcast will fail. Query the nonce from the chain immediately before building the transaction. * **Tron expiration**: Tron transactions have a 24 hour expiration window set during building. This gives plenty of time for signing and broadcast. * **Stellar sequence and time bounds**: Build the transaction with the wallet's current account sequence number and valid time bounds. A stale sequence (`tx_bad_seq`) or expired time bounds cause submission to fail. Build and sign promptly, and set time bounds generously if you plan to broadcast later. * **Stellar Soroban transactions**: Simulate and assemble the transaction before submitting it for signing — an unassembled Soroban transaction fails on-chain. If a stale sequence error is returned, rebuild with a fresh sequence and re-submit. If a broadcast times out awaiting confirmation, reconcile using the returned transaction hash instead of rebuilding, to avoid a double spend. * **Sign only vs broadcast**: Use `/signing/transaction` when you want to broadcast the transaction yourself or through another service. Use `/signing/broadcast` when you want Blockradar to handle submission with automatic retries. *** ## API Reference ### Master Wallet Endpoints | Endpoint | Description | | - | - | | [Sign Message](/en/api-reference/signing/master-wallet-sign-message) | Sign a plain text message | | [Sign Typed Data](/en/api-reference/signing/master-wallet-typed-data) | Sign EIP-712 structured data | | [Sign Transaction](/en/api-reference/signing/master-wallet-sign-transaction) | Sign a raw transaction | | [Broadcast Transaction](/en/api-reference/signing/master-wallet-broadcast-transaction) | Sign and broadcast a raw transaction | ### Child Address Endpoints | Endpoint | Description | | - | - | | [Sign Message](/en/api-reference/signing/child-address-sign-message) | Sign a plain text message from a child address | | [Sign Typed Data](/en/api-reference/signing/child-address-typed-data) | Sign EIP-712 structured data from a child address | | [Sign Transaction](/en/api-reference/signing/child-address-sign-transaction) | Sign a raw transaction from a child address | | [Broadcast Transaction](/en/api-reference/signing/child-address-broadcast-transaction) | Sign and broadcast a raw transaction from a child address | # Wallets Source: https://docs.blockradar.co/en/essentials/wallets Learn how to manage your master wallets In a nutshell
Master wallets are the backbone of Blockradar's infrastructure. They enable you to manage stablecoin deposits across multiple blockchains, generate dedicated addresses for customers, auto-sweep funds, and initiate withdrawals—all from a single wallet per chain.
Wallets Home ## Prerequisites Before creating and managing wallets, ensure you have: Sign up at [dashboard.blockradar.co](https://dashboard.blockradar.co) and complete your account setup. Generate an API key from **Dashboard → Developers** in the dashboard. You'll need this for all API operations. Choose between **Testnet** (for development) or **Mainnet** (for production). Wallets are isolated per environment. Decide which blockchain(s) you need. View [supported blockchains and assets](/en/use-cases/integrations) to see available options. ## How It Works Master wallets let you manage stablecoin deposits across multiple blockchains supported by Blockradar. When you create a master wallet for a specific blockchain, it allows you to manage everything related to that blockchain with the master wallet: 1. Generating dedicated addresses for your customers to use for depositing stablecoins on multiple blockchains. 2. Whitelisting externally managed addresses for stablecoin deposit monitoring. 3. Auto-sweeping: when enabled, every stablecoin deposited to any of the dedicated addresses is automatically swept into the master wallet. 4. Withdrawals: you can easily initiate stablecoin withdrawals from the master wallet address to an external address. ### Creating a Wallet The creation of a master wallet requires four steps: 1. Select the blockchain you want to create the wallet for. 2. Add the stablecoins that you need this master wallet to support. 3. Configure your wallet webhook URL. This will be used for notifications and data synchronization when stablecoins are deposited into any of the dedicated addresses generated through this wallet. 4. Fund the master wallet. If you want to enable auto-sweeping of stablecoins from the dedicated addresses to the master wallet and withdrawal to external addresses, you will need to maintain a balance of the native asset on the blockchain in this master wallet. One dedicated address generated via any of these master wallets can be used to receive deposits on all other blockchain master wallets, provided the blockchains have `isEvmCompatible: true`. This means you can issue your customers a single unique address that can be used to deposit stablecoins on multiple blockchains, without worrying about them sending stablecoins to the wrong blockchain. #### Create a Master Wallet To create a master wallet, go to the dashboard, navigate to the wallets section, and create a wallet to start building a seamless experience for your customers. The Blockradar dashboard provides a simple, user-friendly interface for generating master wallet. Create Wallet This screenshot demonstrates the process of generating a new master wallet via the Blockradar dashboard. This method is ideal for manual address creation or for teams who prefer a graphical interface. Environment
Wallets created in the live environment are isolated to that environment. The same applies to wallets created in the test environment, including the dedicated addresses created for your customers.
**One Master Wallet per blockchain.** Blockradar allows only one Master Wallet per blockchain network per account. To support an additional blockchain, you must create a separate Master Wallet for it. Within a single Master Wallet, you can create as many child addresses as needed to segment funds by user, application, or purpose. Creating multiple Master Wallets for the same blockchain is not supported. ## Wallet Configurations Blockradar master wallets support two key configuration options to help you manage funds and user experience: **Auto Sweeping** and **Gasless Transactions**. ### Auto Sweeping **Enable**\ When enabled, funds deposited to addresses under this wallet will be automatically swept (transferred) to the master wallet. This helps consolidate balances, improves security, and simplifies fund management. **Threshold**\ Set the minimum balance required for each child address to trigger auto-sweeping. If left empty, any amount received will trigger an auto-sweeping. This allows you to control how frequently sweeping occurs and optimize for gas fees. * **Default Setting:** By default auto sweeping is set to true and threshold is 0 * **Address Override:** When generating or updating an address, you can override both the auto sweeping enable/disable and threshold settings for that specific address. The `auto-sweeping` and `threshold` settings on the [addresses](/en/essentials/addresses) level will override the master wallet's configuration for that address. This allows for granular control over auto-sweeping behavior per address. **Best Practice:**\ Enable auto sweeping and set an appropriate threshold to balance between timely fund consolidation and minimizing transaction fees. Auto Sweeping ### Gasless Transactions Configure when the master wallet should cover gas fees for withdrawals from child addresses. **Enable Gasless Withdrawals**\ When enabled, gas fees for qualifying withdrawals will be paid by the master wallet, providing a seamless experience for your users. **Threshold Settings**\ Set the amount threshold for gasless withdrawals. Only transactions that meet this threshold will have their gas fees covered by the master wallet.\ You can specify the threshold logic using arithmetic operators: | Operator | Description | Example (Threshold = 100) | | - | - | - | | `gt` | Greater than | Only withdrawals > 100 | | `gte` | Greater than or equal to | Only withdrawals ≥ 100 | | `lt` | Less than | Only withdrawals \< 100 | | `lte` | Less than or equal to | Only withdrawals ≤ 100 | | `eq` | Equal to | Only withdrawals = 100 | * **Default Setting:** Gasless Transaction is set to `false` by default and threshold settings are set to 0. * **Address Override:** When generating or updating an address, you can override both the enable/disable and threshold settings for gasless transactions for that specific address. The enable `gasless transaction` and `threshold` settings on the [addresses](/en/essentials/addresses) level will override the master wallet's configuration for that address. This allows for granular control over gasless withdrawal behavior per address. **Best Practice:**\ Enable gasless withdrawals and set appropriate threshold logic to balance user experience and operational costs. * Set wallet-level configurations according to your business needs and security requirements. * Use address-level overrides only when you need different behavior for specific addresses. Gasless Transaction ### Funding Funding a master wallet is essential for paying the gas fees on the blockchain when `auto-sweeping` stablecoins from the dedicated addresses to the master wallet and for withdrawals to external wallets. #### Test Environment * **Ethereum**: Get test ETH here: [Alchemy](https://www.alchemy.com/faucets/ethereum-sepolia) or [Infura](https://www.infura.io/faucet/sepolia) * **Binance Smart Chain**: Get test BNB here: [Faucet](https://www.bnbchain.org/en/testnet-faucet) * **Polygon**: Get test MATIC here: [Polygon PoS (Amoy)](https://faucet.polygon.technology/) * **Base**: Get test ETH here: [Alchemy](https://www.alchemy.com/faucets/base-sepolia) * **Optimism**: Get test ETH here: [Alchemy](https://www.alchemy.com/faucets/optimism-sepolia) * **Arbitrum**: Get test ETH here: [Alchemy](https://www.alchemy.com/faucets/arbitrum-sepolia) * **Tron**: Get test TRX here: [Faucet](https://nileex.io/join/getJoinPage) * **Solana**: Get test SOL here: [Faucet](https://faucet.solana.com/) * **Celo**: Get test CELO here: [Faucet](https://faucet.celo.org/alfajores) #### Live Environment For the live environment, you can send assets from any wallet or exchange that supports the native assets on each of the blockchains. Sweeping
Always ensure you have enough balance in your master wallet to avoid delays in auto-sweeping or withdrawals. We will notify you when your master wallet balance is low.
### Gas Fees: Test vs Live Environment Understanding the differences in gas fees between test and live environments is crucial for efficient development and deployment. #### Test Gas Fees In the test environment, gas fees are minimal. Testnets are designed to simulate the mainnet environment without the associated real-world costs. As a result, small amounts of native gas in a testnet can be used for an extended period. This allows developers to test and iterate their integration without incurring significant expenses. #### Live Gas Fees In a test environment, gas fees represent real-world expenses. These costs can vary significantly based on the blockchain and network congestion. Properly estimating and managing gas fees is essential to ensure the smooth operation of your applications and to avoid excessive costs. By leveraging testnets for development and testing, you can minimize expenses and ensure your solutions are robust before deploying to the mainnet. ## Deposit Finder In rare cases, you might not receive a webhook from our system after a customer sends stablecoins to any of the addresses issued to them. We have a deposit finder mechanism built internally, but you also have the ability to trigger a rescan of the blockchain for a missing transaction using the [Deposit Finder API](/en/api-reference/wallet/deposit-finder) by providing the `transactionHash` ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{id}/rescan/blocks \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "transactionHash": "string" }' ``` ```js JavaScript theme={null} const options = { method: 'POST', headers: {'x-api-key': '', 'Content-Type': 'application/json'}, body: '{"blockNumber":"number","transactionHash":"string"}' }; fetch('https://api.blockradar.co/v1/wallets/{id}/rescan/blocks', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` ```php PHP theme={null} "https://api.blockradar.co/v1/wallets/{id}/rescan/blocks", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => "{\n \"blockNumber\": \"number\",\n \"transactionHash\": \"string\"\n}", CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "x-api-key": '' ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } ``` *Body parameters*
The required parameter is `transactionHash`, which can be obtained from either the original transaction record or by looking up the transaction on the blockchain explorer.


Happy hacking! 💚 # Create an Account Source: https://docs.blockradar.co/en/guides/create-account Sign up, complete business info, and get your workspace ready in minutes. Before you can create wallets or make API calls, you need a Blockradar account. This guide walks you through signup, business verification, and getting your workspace ready. ## Step 1: Sign up Go to [dashboard.blockradar.co/signup](https://dashboard.blockradar.co/signup) and enter your email address. You'll receive a verification email — click the link to continue. Blockradar signup screen ## Step 2: Add business information Enter your company name, business sector, country, and website. We will send you a 6-digit code to your email to verify it. Set up two-factor authentication (2FA). This is required before you can access API keys or perform withdrawals. Blockradar signup screen ## Next steps Set up your first wallet and pick a network. Follow a complete end-to-end integration walkthrough. # Create Addresses Source: https://docs.blockradar.co/en/guides/create-addresses Generate dedicated deposit addresses for your users and track balances in real time. In a nutshell
Dedicated addresses allow you to create unique blockchain addresses for each customer. These addresses can receive stablecoins across multiple EVM-compatible chains, with deposits automatically swept to your master wallet.
Addresses ## Prerequisites Before generating addresses, ensure you have: Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. Create at least one master wallet in the dashboard (see [Create a Master Wallet](/en/guides/create-master-wallet)). You'll need the `walletId` to generate addresses. Fund your master wallet with native tokens (ETH, BNB, MATIC, etc.) to cover gas fees for auto-sweeping operations. Set up your webhook URL on the master wallet to receive deposit notifications. See [Webhooks](/en/utilities/webhooks) for setup details. ## How It Works Dedicated Addresses is a crucial feature on Blockradar that enables you to create unique addresses for your customers. These addresses allow your customers to deposit stablecoins into your fintech app seamlessly. When you create a dedicated address for a customer, they can use that single address to deposit stablecoins across multiple EVM-compatible blockchains. For example, if you have Ethereum, Binance Smart Chain, Polygon, and Base master wallets created, each address you generate through any of these master wallets can be used to receive stablecoins on any of the [supported blockchains and assets](/en/use-cases/integrations). This ensures that you don't have to worry about your customer sending stablecoins to the wrong blockchain. Additionally, when stablecoins are deposited into a particular address, the assets are automatically moved to the chain's master wallet address. Aside from Tron and Solana, addresses generated from one wallet can be used to deposit stablecoins across other blockchains that have the blockchain parameter `isEvmCompatible: true`. ## Create a Dedicated Address You can generate a dedicated address for your customer using either the [Blockradar dashboard ](https://dashboard.blockradar.co) or the API, depending on your workflow and integration needs. ### 1. Using the Dashboard The Blockradar dashboard provides a simple, user-friendly interface for generating new addresses. Generate address This screenshot demonstrates the process of generating a new address via the Blockradar dashboard. This method is ideal for manual address creation or for teams who prefer a graphical interface. ### 2. Using the API For programmatic or automated address generation, you can use the **Create Dedicated Address API**.\ This is useful for integrating address creation into your own applications or backend systems. To create a dedicated address for a customer, send a **`POST`** request to our [Create Dedicated Address API](/en/api-reference/addresses/generate-address). ```bash address.cmd theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/addresses \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "disableAutoSweep": "OPTIONAL_BOOLEAN", "enableGaslessWithdraw": "OPTIONAL_BOOLEAN", "metadata": "OPTIONAL_METADATA", "name": "OPTIONAL_ADDRESS_NAME", "showPrivateKey": "OPTIONAL_BOOLEAN" }' ``` ```js address.js theme={null} const options = { method: 'POST', headers: {'x-api-key': '', 'Content-Type': 'application/json'}, body: '{"metadata":"OPTIONAL_METADATA","name":"OPTIONAL_ADDRESS_NAME"}' }; fetch('https://api.blockradar.co/v1/wallets/{walletId}/addresses', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` ```php address.php theme={null} "https://api.blockradar.co/v1/wallets/{walletId}/addresses", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => "{\n \"metadata\": \"OPTIONAL_METADATA\",\n \"name\": \"OPTIONAL_ADDRESS_NAME\"\n}", CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "x-api-key: " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } ``` ### Response ```json theme={null} { "data": { "address": "0xe1037B45b48390285e5067424053fa35c478296b", "blockchain": { "createdAt": "2024-05-14T11:53:33.095Z", "derivationPath": "m/44'/60'/0'/0", "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf", "isActive": true, "isEvmCompatible": true, "logoUrl": "https://res.cloudinary.com/blockradar/image/upload/v1716800081/crypto-assets/ethereum-eth-logo_idraq2.png", "name": "ethereum", "slug": "ethereum", "symbol": "eth", "tokenStandard": "ERC20", "updatedAt": "2024-06-14T22:32:11.983Z" }, "configurations": { "aml": { "message": "Address is not sanctioned", "provider": "ofac", "status": "success" }, "disableAutoSweep": false, "enableGaslessWithdraw": false, "showPrivateKey": false }, "createdAt": "2024-10-23T11:13:40.446Z", "derivationPath": "m/44'/60'/0'/0/87", "id": "0a69c48a-6c6f-422c-bd6a-70de3306a3ac", "isActive": true, "metadata": { "user_id": 1 }, "name": "Customer 1", "network": "testnet", "type": "INTERNAL", "updatedAt": "2024-10-23T11:13:40.446Z" }, "message": "Address generated successfully", "statusCode": 200 } ``` ## Testing Addresses generated via a testnet master wallet can only receive assets on the testnet. Here is a list of places where you can get testnet assets to test with: * **Ethereum** - Get test USDC here: [Circle](https://faucet.circle.com/) * **Binance Smart Chain** - Get test USDT here: [Binance](https://www.bnbchain.org/en/testnet-faucet) * **Polygon** - Get test USDC here: [Circle](https://faucet.circle.com/) * **Base** - Get test USDC here: [Circle](https://faucet.circle.com/) * **Tron** - Get test USDT here: [Nileex](https://nileex.io/join/getJoinPage) * **Solana** - Get test USDC here: [Circle](https://faucet.circle.com) * **Optimism** - Get test USDC here: [Circle](https://faucet.circle.com) * **Arbitrum** - Get test USDC here: [Circle](https://faucet.circle.com) * **Celo** - Get test USDC here: [Circle](https://faucet.circle.com)

Happy hacking! 💚 # Create a Master Wallet Source: https://docs.blockradar.co/en/guides/create-master-wallet Set up a master wallet, pick your network, and start receiving deposits. In a nutshell
Master wallets are the backbone of Blockradar's infrastructure. They enable you to manage stablecoin deposits across multiple blockchains, generate dedicated addresses for customers, auto-sweep funds, and initiate withdrawals, all from a single wallet per chain.
Wallets Home ## Prerequisites Before creating and managing wallets, ensure you have: Sign up at [dashboard.blockradar.co](https://dashboard.blockradar.co) and complete your account setup. Generate an API key from **Dashboard → Developers** in the dashboard. You'll need this for all API operations. Choose between **Testnet** (for development) or **Mainnet** (for production). Wallets are isolated per environment. Decide which blockchain(s) you need. View [supported blockchains and assets](/en/use-cases/integrations) to see available options. ## How It Works Master wallets let you manage stablecoin deposits across multiple blockchains supported by Blockradar. When you create a master wallet for a specific blockchain, it allows you to manage everything related to that blockchain with the master wallet: 1. Generating dedicated addresses for your customers to use for depositing stablecoins on multiple blockchains. 2. Whitelisting externally managed addresses for stablecoin deposit monitoring. 3. Auto-sweeping: when enabled, every stablecoin deposited to any of the dedicated addresses is automatically swept into the master wallet. 4. Withdrawals: you can easily initiate stablecoin withdrawals from the master wallet address to an external address. ### Creating a Wallet The creation of a master wallet requires four steps: 1. Select the blockchain you want to create the wallet for. 2. Add the stablecoins that you need this master wallet to support. 3. Configure your wallet webhook URL. This will be used for notifications and data synchronization when stablecoins are deposited into any of the dedicated addresses generated through this wallet. 4. Fund the master wallet. If you want to enable auto-sweeping of stablecoins from the dedicated addresses to the master wallet and withdrawal to external addresses, you will need to maintain a balance of the native asset on the blockchain in this master wallet. One dedicated address generated via any of these master wallets can be used to receive deposits on all other blockchain master wallets, provided the blockchains have `isEvmCompatible: true`. This means you can issue your customers a single unique address that can be used to deposit stablecoins on multiple blockchains, without worrying about them sending stablecoins to the wrong blockchain. #### Create a Master Wallet To create a master wallet, go to the dashboard, navigate to the wallets section, and create a wallet to start building a seamless experience for your customers. The Blockradar dashboard provides a simple, user-friendly interface for generating master wallet. Create Wallet This screenshot demonstrates the process of generating a new master wallet via the Blockradar dashboard. This method is ideal for manual address creation or for teams who prefer a graphical interface. Environment
Wallets created in the live environment are isolated to that environment. The same applies to wallets created in the test environment, including the dedicated addresses created for your customers.
# Dynamic Forms Source: https://docs.blockradar.co/en/guides/dynamic-forms Interpret, complete, validate, and submit schemas returned by Blockradar API flows. ## In a nutshell Some Blockradar API flows return a Dynamic Form Schema when an operation needs more information. The schema describes the object that your integration must produce. ```text theme={null} Input: The schema returned by a requirements or discovery request Values: Data collected for the schema's properties Output: A JSON object that validates against the schema Destination: The request property documented by the API operation ``` Your integration: 1. receives the JSON Schema; 2. determines which fields apply to the current values; 3. obtains values from a user or automated workflow; 4. loads choices and resolves fields when their dependencies are ready; 5. builds and validates the completed object; and 6. submits that object as documented by the API guide for the operation. Do not submit the completed object back to a requirements or discovery endpoint. Submit it in the request property documented by the next API operation, such as `paymentMethodData` or `additionalData`. ## How Dynamic Forms work A Dynamic Form Schema is a JSON object that describes the fields to collect. It uses standard JSON Schema keywords and documented `x-*` properties for choices, files, and fields whose values come from another API call. Do not hard-code fields from an earlier response. Use the schema returned for the current operation. Some fields apply only when another value selects a particular `oneOf` or `if`/`then`/`else` branch. Collect, validate, and submit only the fields in the selected branch. When a value selects a different branch, remove values that no longer apply. Repeat these steps as values change: ```text theme={null} Receive schema ↓ Find the fields that apply ↓ Collect or generate available values ↓ Load choices and resolve fields when their required inputs are valid ↓ Check again which fields apply ↺ Repeat until all required values are available ↓ Validate the completed object ↓ Submit it as documented by the API guide ``` ## Recipes ### Collect a basic object For a schema with no conditions or API-driven fields: 1. Read the field names from `properties`. 2. Read required field names from `required`. 3. Collect values using the declared types and validation rules. 4. Validate the completed object against the schema. 5. Submit the object in the request property documented by the API guide. For example, this schema: ```json theme={null} { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, "properties": { "accountNumber": { "type": "string", "pattern": "^[0-9]{10}$" }, "bankCode": { "type": "string" } }, "required": ["accountNumber", "bankCode"] } ``` produces an object with the same property names and types: ```json theme={null} { "accountNumber": "0123456789", "bankCode": "999" } ``` ### Switch between conditional fields An object-level `oneOf` can describe different sets of fields. Each branch uses a required `type.const` value as its selector: ```json theme={null} { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "oneOf": [ { "title": "Bank account", "type": "object", "additionalProperties": false, "properties": { "type": { "type": "string", "const": "bank" }, "accountNumber": { "type": "string" } }, "required": ["type", "accountNumber"] }, { "title": "Mobile money", "type": "object", "additionalProperties": false, "properties": { "type": { "type": "string", "const": "mobile_money" }, "phoneNumber": { "type": "string" } }, "required": ["type", "phoneNumber"] } ] } ``` When `type` is `"mobile_money"`, collect and submit only that branch: ```json theme={null} { "type": "mobile_money", "phoneNumber": "+2348012345678" } ``` If `type` changes to `"bank"`, remove `phoneNumber` and collect `accountNumber`. ### Complete Withdraw Fiat requirements 1. [Get the payment-method requirements](/en/api-reference/withdraw-fiat/payment-method-requirements-v2) from `GET /v2/wallets/{id}/withdraw/fiat/payment-method-requirements`. 2. Collect the fields in `data.schema`. 3. When a field contains `x-resolution`, call it after its dependencies are valid, as described below. 4. Validate the completed object. 5. Send it as `paymentMethodData` when you [get a quote](/en/api-reference/withdraw-fiat/master-wallet-get-quote-v2) or [execute the withdrawal](/en/api-reference/withdraw-fiat/master-wallet-execute-v2). ```json theme={null} { "assetId": "ae455f23-3824-4125-baab-d158315cbcbd", "amount": "100.00", "currency": "NGN", "paymentMethod": "bank_transfer", "paymentMethodData": { "institutionIdentifier": "999", "accountIdentifier": "0123456789", "accountName": "Ada Okafor" } } ``` `accountName` is included because the resolution returned it. The field is optional in this example because it is not listed in the schema's `required` array. ### Complete Virtual Account requirements 1. [Get the Virtual Account requirements](/en/api-reference/virtual-accounts/requirements-v2) from `GET /v2/wallets/{id}/virtual-accounts/requirements`. 2. If `data.additionalDataRequired` is `true`, collect the fields in `data.additionalDataSchema`. 3. Validate the completed object. 4. Send it as `additionalData` when you [create the Virtual Account](/en/api-reference/virtual-accounts/master-wallet-create-v2). Use the `provider` returned by the requirements request. ```json theme={null} { "currency": "NGN", "assetId": "ae455f23-3824-4125-baab-d158315cbcbd", "provider": "example-provider", "additionalData": { "bvn": "12345678901", "dateOfBirth": "1992-04-18" } } ``` ### Complete Deposit Fiat payment-order requirements 1. [Get a Deposit Fiat quote](/en/api-reference/deposit-fiat/master-wallet-get-quote) from `POST /v1/wallets/{id}/deposit/fiat/quote`. Include `customerId` when the order belongs to an existing customer and the provider uses corridor-specific inline KYC. The provider adapter infers the corridor from the selected fiat currency. 2. Read the schema from `data.additionalDataRequirements.schema`. 3. Initialize the form with `data.additionalDataRequirements.data` when it is not `null`. These are previously saved values for the resolved customer, provider, and corridor. 4. Collect any missing fields and resolve `x-resolution` fields using the instructions in the schema. See [Resolve Payment Order Requirements](/en/api-reference/deposit-fiat/resolve-payment-order-requirements). 5. Validate the completed object against the current schema. 6. Send it as `additionalData` when [creating the payment order](/en/api-reference/deposit-fiat/master-wallet-create-payment-order) with `POST /v1/wallets/{id}/deposit/fiat/orders`. The quote may return `null` for the schema. In that case, the selected route does not require `additionalData`. For providers such as Paycrest, the schema can include inline customer KYC. When the order is created, Blockradar saves the submitted KYC for the business customer, provider, and corridor. Future quotes for the same combination can return it in `additionalDataRequirements.data`; treat it as editable form data and revalidate it before submission. ### Complete customer onboarding requirements 1. [Create an onboarding request](/en/api-reference/customer-onboarding/create-request) for the customer. 2. Read `data.requirements.schema` from the response. You can also [retrieve the request](/en/api-reference/customer-onboarding/get-request) to obtain its current schema and status. 3. Collect and validate the customer information described by the schema. For file and document fields, first [prepare the upload](/en/api-reference/customer-onboarding/prepare-uploads), then follow the returned direct-upload instructions or [send the prepared document](/en/api-reference/customer-onboarding/upload-prepared-document). 4. [Submit the completed object](/en/api-reference/customer-onboarding/submit-request) in the request body as `data`. 5. If the response includes `data.requirements`, repeat the process using that current schema. If it does not, follow the returned case status and hosted session information. If the case requires confirmation, fetch its [confirmation requirements](/en/api-reference/customer-onboarding/get-confirmation-requirements), complete that schema, and [submit the confirmation](/en/api-reference/customer-onboarding/submit-confirmation). ```json theme={null} { "data": { "firstName": "Ada", "lastName": "Okafor", "dateOfBirth": "1992-04-18" } } ``` The property names above are illustrative. Always use the properties returned by the current onboarding request. ### Complete a schema from existing data For an automated integration: 1. Copy existing values only when their property paths and JSON types match the fields that currently apply. 2. Report required fields that have no value. Do not invent placeholders. 3. Accept only identifiers declared by `enum` or `const`. 4. Load documented choices and resolve fields only after their dependencies are valid. 5. If required information is still missing, stop and return the missing and invalid property paths to the calling workflow. 6. Return a completed object only after full validation succeeds. ## Schema structure and supported keywords Dynamic Form Schemas use JSON Schema [Draft 07](https://json-schema.org/draft-07) and declare: ```json theme={null} { "$schema": "http://json-schema.org/draft-07/schema#" } ``` Accept `http://json-schema.org/draft-07/schema#`. Accept another value only when the API operation explicitly documents that dialect. Otherwise, stop and report that the schema dialect is unsupported. Implement only the features present in the schemas your integration receives: | When the schema contains | Your integration needs to handle | | - | - | | `properties`, `required`, and validation keywords | Basic collection and validation | | `allOf`, `oneOf`, or `if`/`then`/`else` | Conditional fields | | `enum` or `oneOf` branches with `const` | Choices | | `x-resolution` | API-resolved values | | `x-options` | Self-describing remote choices | | `x-data-source` | Legacy named remote-choice source | | File extensions | The documented upload flow | ### Validation keywords | Keyword | Meaning | | - | - | | `type` | Value type, including `string`, `number`, `integer`, `boolean`, `object`, and `array` | | `properties` | Exact property names and their schemas | | `required` | Required property names in the containing object | | `additionalProperties` | Whether undeclared properties are accepted | | `enum` | Allowed string, number, boolean, or `null` values | | `const` | One fixed value, including a branch selector | | `pattern` | Regular expression for a string | | `format` | String format, including `email` and `date` (`YYYY-MM-DD`) | | `minLength`, `maxLength` | String-length limits | | `minimum`, `maximum` | Inclusive numeric limits | | `items`, `minItems`, `maxItems` | Array item schema and length limits | | `allOf` | Apply every listed schema | | `oneOf` | Exactly one listed schema must match | | `if`, `then`, `else` | Apply conditional constraints from current values | Requiredness belongs to the containing object's `required` array. A field-level `required: true` is not Draft 07. ### Presentation annotations | Annotation | Meaning | | - | - | | `title` | Field, section, or choice label | | `description` | Explanatory text | | `readOnly` | Presentation hint that the value is not entered directly; it does not resolve the value | ### Blockradar extensions | Extension | Meaning | | - | - | | `x-field-kind` | Identifies a resolved, file, files, or document field | | `x-resolution` | Request and response mapping for a resolved field | | `x-options` | Endpoint, response mapping, and dependencies for remote choices | | `x-value-format` | Semantic format of the submitted value | | `x-data-source` | Legacy named remote-choice source | | `x-data-source-depends-on` | Legacy field paths required before loading choices | | `x-accept` | Accepted file MIME types | | `x-max-file-size-bytes` | Maximum file size | | `x-document-type` | Fixed document type | | `x-document-types` | Allowed document types, labels, and required sides | Nested objects define their own `properties`, `required`, and `additionalProperties`. Arrays retain the structure declared by `items`. Do not flatten nested paths when validating or submitting values. For a selectable object-level `oneOf`, each branch has a non-empty `title` and a required `type` property with a unique string `const`. Dynamic Forms does not use an OpenAPI `discriminator`. ### Language-neutral data model `?` means optional, `[]` means a list, and `map` means an object whose property names map to values of type `T`. ```text theme={null} JSON primitive = string | number | boolean | null JSON value = JSON primitive | JSON value[] | map Dynamic Form Schema $schema?: string type: "string" | "number" | "integer" | "boolean" | "object" | "array" title?: string description?: string readOnly?: boolean enum?: JSON primitive[] const?: JSON primitive allOf?: Dynamic Form Schema[] oneOf?: Dynamic Form Schema[] if?: Dynamic Form Schema then?: Dynamic Form Schema else?: Dynamic Form Schema When type is "string" pattern?: string format?: string minLength?: number maxLength?: number When type is "number" or "integer" minimum?: number maximum?: number When type is "array" items: Dynamic Form Schema minItems?: number maxItems?: number When type is "object" properties?: map required?: string[] additionalProperties?: boolean | Dynamic Form Schema Blockradar extensions x-field-kind?: "resolved" | "file" | "files" | "document" | string x-resolution?: Resolution Definition x-options?: Option Source x-value-format?: string x-data-source?: string x-data-source-depends-on?: string[] x-accept?: string[] x-max-file-size-bytes?: number x-document-type?: string x-document-types?: Document Type[] Resolution Definition method: "POST" | "PATCH" url: string body?: map inputPath?: string dependsOn: string[] responsePath: string Option Source endpoint: string responsePath: string valueField: string labelField: string parameters?: map allowCustomValue?: boolean Option Parameter from: string scope: "parent" | "root" Document Type = string | { value: string, label: string, sides?: ("front" | "back")[] } ``` ## Finding the fields that apply Start at the root schema and follow nested objects and arrays. Apply conditional keywords before collecting their properties: ```text theme={null} visit(schema, path, values): apply every allOf schema evaluate if and apply then or else select the oneOf branch that matches current values if object: visit each property that applies if array: visit items for each current array item otherwise: record the field at path ``` At each object, read `required` from that object. At each array, retain numeric indexes in error paths, such as `owners[0].address.country`. When a value selects a different object-level branch, remove fields that exist only in the previous branch. Reload choices and resolved values that depended on the changed value. Use a Draft 07 validator to evaluate `allOf`, `oneOf`, and conditional schemas. Do not implement branch selection by field titles or property order. ## Supplying field values Store every value at the exact property path from the selected branch and keep its declared JSON type. Do not assume that every schema contains a field such as `accountName`, `country`, or `document`. Validate supplied values before using them. Accept only declared `enum` or `const` identifiers, obtain resolved values through `x-resolution`, and obtain file references through the upload flow documented by the API operation. ## Choices, dependencies, and resolved fields ### Static choices For `enum`, submit the selected value. For a `oneOf` choice whose branches contain `const`, show each branch's `title` and submit its `const`: ```json theme={null} { "type": "string", "title": "Institution", "oneOf": [ { "const": "999", "title": "Example Bank" } ] } ``` The completed value is `"999"`, not `"Example Bank"`. ### Remote choices `x-options` is the canonical remote-choice contract. It describes where to load choices, how to map the response, and how to resolve dependent endpoint parameters: | Property | Required | Meaning | | - | - | - | | `endpoint` | Yes | API-relative `GET` path. It can contain named placeholders such as `{countryCode}` | | `responsePath` | Yes | Dot-separated path to the choices in the complete response object | | `valueField` | Yes | Property from each choice to submit | | `labelField` | Yes | Property from each choice to display | | `parameters` | When the endpoint has placeholders | Map from placeholder names to parameter definitions | | `allowCustomValue` | No | Whether a user can submit a value not returned by the endpoint | Resolve every endpoint placeholder before making the request. URL-encode each substituted value. Do not call an endpoint while a required parameter is missing or invalid. Each parameter declares `from` and `scope`: * `scope: "parent"` resolves `from` against the object containing the current field. This works for nested objects and ensures each item in an array uses its own sibling value. * `scope: "root"` resolves a dot-separated `from` path against the complete form value object. Read the choices from `responsePath`. For each item, display `labelField` and submit `valueField`. Cache choices by the fully resolved endpoint. If a dependency changes, discard choices and selected values that are no longer valid, and prevent an older request from replacing the new response. When `allowCustomValue` is `true`, allow a string that is not in the returned choices. Keep manual input available when the endpoint returns an empty list or the request fails, subject to the property's normal JSON Schema validation. `x-value-format` describes the semantics of the submitted value. Unknown formats are informational and must not prevent a client from rendering the field. The country and subdivision formats currently used are: | Format | Submitted value | | - | - | | `ISO-3166-1-alpha-2-uppercase` | Exactly two uppercase letters, such as `NG` or `US` | | `country-subdivision-code` | The country-scoped subdivision code, such as `LA`, `NY`, or `CA`; do not prepend the country code | #### Load country options A country property uses the lean country-options endpoint: ```json theme={null} { "type": "string", "title": "Country", "minLength": 2, "maxLength": 2, "pattern": "^[A-Z]{2}$", "x-value-format": "ISO-3166-1-alpha-2-uppercase", "x-options": { "endpoint": "/countries/options", "responsePath": "data", "valueField": "code", "labelField": "name" } } ``` `GET /countries/options` returns: ```json theme={null} { "statusCode": 200, "message": "Country options fetched successfully", "data": [ { "code": "NG", "name": "Nigeria" }, { "code": "US", "name": "United States" } ] } ``` Display `name` and submit `code`. The completed value is `"NG"`, not `"Nigeria"`. #### Load a dependent subdivision A state, province, region, county, or equivalent property uses the selected country to resolve its endpoint: ```json theme={null} { "type": "object", "properties": { "Country": { "type": "string", "pattern": "^[A-Z]{2}$", "minLength": 2, "maxLength": 2, "x-value-format": "ISO-3166-1-alpha-2-uppercase", "x-options": { "endpoint": "/countries/options", "responsePath": "data", "valueField": "code", "labelField": "name" } }, "State": { "type": "string", "title": "State / province", "x-value-format": "country-subdivision-code", "x-options": { "endpoint": "/countries/{countryCode}/subdivisions", "responsePath": "data", "parameters": { "countryCode": { "from": "Country", "scope": "parent" } }, "valueField": "code", "labelField": "name", "allowCustomValue": true } } }, "required": ["Country", "State"] } ``` For `{ "Country": "NG" }`, resolve the endpoint to `GET /countries/NG/subdivisions`. The response is: ```json theme={null} { "statusCode": 200, "message": "Country subdivisions fetched successfully", "data": [ { "code": "LA", "name": "Lagos" } ] } ``` Display `Lagos` and submit `LA`. Do not transform it to `NG-LA`. For lowercase schemas, the parameter can use `{ "from": "country", "scope": "parent" }`. In an array of addresses, resolve that path against the current address item, not the root object or a different item. #### Legacy data sources `x-data-source` and `x-data-source-depends-on` are legacy compatibility hints. When `x-options` is present, use it and do not infer another endpoint from `x-data-source`. If only a legacy source is present, follow the API guide that documents it. Do not guess an endpoint from an unexplained source name. ### Resolved fields A field with `x-resolution` gets its value from the API request described by `x-resolution`: | Property | Required | Meaning | | - | - | - | | `method` | Yes | `POST` or `PATCH` | | `url` | Yes | API-relative path beginning `/v/` | | `body` | No | JSON values to copy into the request body | | `inputPath` | No | Request-body path for the current form object | | `dependsOn` | Yes | Property paths required before the call | | `responsePath` | Yes | Path to read inside the response's top-level `data` value | `x-field-kind: "resolved"` does not make a field required. A resolved field is required only when its property name appears in the containing object's `required` array. Resolve an optional field when the API flow needs its value or when you want to show the verified result. #### Resolve an account name This recipe uses the `x-resolution` returned by the [Withdraw Fiat requirements request](/en/api-reference/withdraw-fiat/payment-method-requirements-v2): Fiat withdrawal requirements also return a top-level `resolution` contract for submitting the completed form. Its body contains the backend-issued `sessionId` and selected `paymentMethod`; place the current form object at its `inputPath`. The field-level `x-resolution` below still controls when and how a derived field such as `accountName` is populated. ```json theme={null} { "type": "object", "additionalProperties": false, "properties": { "institutionIdentifier": { "type": "string" }, "accountIdentifier": { "type": "string", "pattern": "^[0-9]{10}$" }, "accountName": { "type": "string", "readOnly": true, "x-field-kind": "resolved", "x-resolution": { "method": "POST", "url": "/v2/wallets/4465468a-3c36-4536-918a-91d689e18a74/withdraw/fiat/payment-method/resolve", "body": { "sessionId": "13a36c1c-f4a6-4e49-a582-2ecded2559bc", "paymentMethod": "bank_transfer" }, "inputPath": "paymentMethodData", "dependsOn": ["institutionIdentifier", "accountIdentifier"], "responsePath": "data.accountName" } } }, "required": [ "institutionIdentifier", "accountIdentifier" ] } ``` Given these current values: ```json theme={null} { "institutionIdentifier": "999", "accountIdentifier": "0123456789" } ``` the request body is: ```json theme={null} { "provider": "example-provider", "assetId": "ae455f23-3824-4125-baab-d158315cbcbd", "currency": "NGN", "amount": "100.00", "paymentMethod": "bank_transfer", "paymentMethodData": { "institutionIdentifier": "999", "accountIdentifier": "0123456789" } } ``` Send this body to `x-resolution.url`. For this recipe, see [Resolve Payment Method](/en/api-reference/withdraw-fiat/resolve-payment-method-v2). The API returns: ```json theme={null} { "statusCode": 200, "message": "Payment method resolved successfully", "data": { "paymentMethod": "bank_transfer", "data": { "accountNumber": "0123456789", "accountName": "Ada Okafor", "bankCode": "999" } } } ``` Follow `responsePath` from the response's top-level `data` value: ```text theme={null} Start: response.data Path: data.accountName Result: "Ada Okafor" ``` Store the result at `accountName`: ```json theme={null} { "institutionIdentifier": "999", "accountIdentifier": "0123456789", "accountName": "Ada Okafor" } ``` Copy `body` into a new request body. When `inputPath` is present, add the current form values at that path. If a dependency changes, clear the previous result and call the resolution again with the new values. Do not call the resolution while a path in `dependsOn` is missing or invalid. If the request fails, leave the field unresolved and surface the API error to the calling workflow. ## File and document fields File fields add upload constraints to a schema property: ```json theme={null} { "type": "object", "title": "Identity document", "x-field-kind": "file", "x-accept": ["application/pdf", "image/jpeg", "image/png"], "x-max-file-size-bytes": 5000000, "x-document-types": ["passport", "national_id"] } ``` `x-field-kind: "files"` uses an array whose `items` are objects. `x-document-types` can contain strings or objects with `value`, `label`, and optional `sides` containing `front` or `back`. The API guide defines how to upload the file and which value to place in the completed object. The schema itself does not provide an upload endpoint, multipart field name, response format, or file-reference format. Do not place a platform-specific file object or raw bytes in the JSON object. If the API operation does not document the upload flow or file-reference format, stop and tell the caller that the file field cannot be submitted. Enforce `x-accept`, `x-max-file-size-bytes`, array limits, document types, and required sides before submission. ## Partial and complete validation Partial validation answers: **Are the values supplied so far valid?** It does not mean the object is ready to submit. For partial validation, validate the current object against the branch that applies. Continue to enforce: * supplied value types and constraints; * `enum` and `const`; * `additionalProperties`; * array constraints; and * `allOf`, `oneOf`, and any `if`/`then`/`else` branch that can already be determined. Ignore only `required` failures for properties that have not been supplied yet. Do not validate each property in isolation because rules on the containing object may also apply. Complete validation answers: **Is the object ready to submit?** Validate the completed object against the full, unmodified schema and report every failure. Preserve strings when the schema declares `type: "string"`, including account numbers and decimal amounts. Submit JSON numbers for fields declared as `number` or `integer`. ## Constructing and submitting the final object Build a new object from the properties that currently apply: * copy accepted values at exact property paths; * retain nested objects and arrays; * copy identifiers rather than labels; * include values returned by resolution calls; * include documented uploaded-file references; * omit properties from unselected branches and any UI-only state; * reject unknown properties where `additionalProperties: false`; and * omit absent optional properties. Validate this new object against the complete schema. Then place it in the request property documented by the API guide. ## Error handling Dynamic Forms uses the [standard Blockradar API error response](/en/about-the-api/errors). A validation failure includes the HTTP status and a message that identifies the missing or invalid field: ```json theme={null} { "statusCode": 400, "message": "Invalid payment method data for accountIdentifier: accountIdentifier does not match the expected format" } ``` `requestId` is included when request context is available. Some errors can also include `details`. Do not depend on undocumented error codes. Use the HTTP status and `message`, and retain `requestId` when contacting support. ## Security boundaries The integration must: * keep API credentials out of untrusted application code; * use the schema returned by Blockradar instead of a modified client copy; * read the schema as data; never execute content from it as code; * accept only `GET` for `x-options`, the documented `POST` or `PATCH` methods for `x-resolution`, and API-relative paths on the configured Blockradar origin; * validate the completed object before submission; and * avoid logging credentials or sensitive field values. ## Testing and production checklist Before production, verify that your integration can: * retrieve schemas dynamically; * identify required and conditional fields at nested paths; * handle static choices, `x-options`, legacy documented data sources, and resolved fields; * resolve parent-scoped choices independently for nested objects and array items; * preserve submitted country and subdivision codes rather than their labels; * preserve exact names, types, paths, objects, and arrays; * remove values from branches that no longer apply; * build and validate the completed object; and * submit it in the request property documented by the API guide. # From 0 to Integration Source: https://docs.blockradar.co/en/guides/getting-started Go from zero to a live stablecoin integration in under 2 hours. This guide walks you through everything you need to accept stablecoin deposits using Blockradar, from account setup to handling your first webhook event. You can integrate and go live with one developer in under 2 hours. Follow along and build as you read. By the end you'll have a working stablecoin payment flow. ## What you'll build By the end of this guide you will have: * A Blockradar account and a master wallet on testnet * Child addresses generated and tied to your users * A webhook handler receiving real-time deposit events * A pattern for updating user balances after a deposit *** ## Step 1: Create your account Visit [dashboard.blockradar.co/signup](https://dashboard.blockradar.co/signup) and complete the onboarding process. It takes under 60 seconds. In the top-right corner of the dashboard you'll see a **Live Mode** toggle. It's off by default, this means every action runs on **testnet**, a safe sandbox where no real funds are involved. Leave it off while following this guide. *** ## Step 2: Create a master wallet ### What is a master wallet? The master wallet is the foundation of your stablecoin infrastructure. Think of it as your treasury, it holds control over all the child addresses you create for your users. Each master wallet is tied to a specific blockchain, so if you want to support deposits on Ethereum, Base, and BNB Chain, you'll create a separate master wallet for each. ### Create your first wallet From the dashboard, click **Create Master Wallet**. Choose **Base Sepolia (Testnet)** to follow this guide. You can create wallets on other chains later. Give it a name like `base-testnet` and click **Create**. You now have a master wallet. This is where all child addresses for your users will be generated. *** ## Step 3: Generate addresses for your users ### What are child addresses? When a user onboards to your app and needs to receive stablecoins, they need a wallet address, like a bank account number, but on the blockchain. In Blockradar, these are called **child addresses**. They are generated under your master wallet and inherit its network configuration. Addresses generated on any EVM-compatible chain (Base, Ethereum, BNB Chain, etc.) work across all EVM chains. One address covers all your EVM networks. ### Generate an address via API Call this endpoint when a user signs up on your platform: ```bash theme={null} curl -X POST https://api.blockradar.co/v1/wallets/{walletId}/addresses \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Customer Wallet", "disableAutoSweep": false, "enableGaslessWithdraw": true, "metadata": { "user_id": 1234, "email": "user@example.com" } }' ``` ```javascript theme={null} const options = { method: "POST", headers: { "x-api-key": "", "Content-Type": "application/json", }, body: JSON.stringify({ name: "Customer Wallet", disableAutoSweep: false, enableGaslessWithdraw: true, metadata: { user_id: 1234, email: "user@example.com" }, }), }; fetch("https://api.blockradar.co/v1/wallets/{walletId}/addresses", options) .then((res) => res.json()) .then(console.log); ``` ### Where to find your walletId and API key 1. Go to your master wallet in the dashboard 2. Scroll down to the **API Config** section 3. Click the reveal icon (you'll need to pass 2FA) 4. Copy both your **API Key** and **Wallet ID** ### The metadata field The `metadata` object is one of the most important parts of this request. Anything you attach here will be included in every webhook Blockradar sends for that address, deposits, withdrawals, sweeps. This is how your backend identifies which user a transaction belongs to. ```json theme={null} { "user_id": 1234, "email": "user@example.com" } ``` **Best practice:** Always include a `user_id` in metadata so you can map every deposit directly to a user in your database without any additional lookups. *** ## Step 4: Configure auto sweep and gasless transactions ### Auto sweep When auto sweep is enabled (`disableAutoSweep: false`), funds deposited to a child address are automatically consolidated into your master wallet. This keeps treasury management simple, all funds sit in one place, and you track user balances in your own database. For auto sweep to work, your master wallet must hold native tokens to cover gas fees. Find the master wallet deposit address on the wallet overview page and send testnet tokens there. **Testnet faucets for gas tokens:** | Network | Token | Faucet | | - | - | - | | Base Sepolia | ETH | [alchemy.com/faucets/base-sepolia](https://www.alchemy.com/faucets/base-sepolia) | | Ethereum Sepolia | ETH | [alchemy.com/faucets/ethereum-sepolia](https://www.alchemy.com/faucets/ethereum-sepolia) | | BNB Testnet | BNB | [bnbchain.org/en/testnet-faucet](https://www.bnbchain.org/en/testnet-faucet) | | Polygon Testnet | MATIC | [faucet.polygon.technology](https://faucet.polygon.technology/) | | Tron Testnet | TRX | [nileex.io](https://nileex.io/join/getJoinPage) | | Solana Devnet | SOL | [faucet.solana.com](https://faucet.solana.com/) | | Celo Alfajores | CELO | [faucet.celo.org/alfajores](https://faucet.celo.org/alfajores) | | Avalanche Fuji | AVAX | [core.app/tools/testnet-faucet](https://core.app/tools/testnet-faucet/) | **Testnet stablecoin faucets:** | Network | Token | Faucet | | - | - | - | | Base / Ethereum / Polygon / Solana | USDC | [faucet.circle.com](https://faucet.circle.com/) | | BNB Testnet | USDT | [bnbchain.org/en/testnet-faucet](https://www.bnbchain.org/en/testnet-faucet) | ### Gasless transactions When `enableGaslessWithdraw: true`, your users can send stablecoins from their address without holding any native tokens. Your master wallet covers the gas on their behalf. This removes the biggest UX friction in crypto onboarding. ### Set defaults globally Instead of configuring each address individually, you can set defaults for the entire master wallet: 1. Go to your master wallet 2. Click **Configurations** 3. Set `disableAutoSweep` and `enableGaslessWithdraw` Configuration set at the address level overrides the master wallet config. Use address-level config only when you need exceptions. *** ## Step 5: Set up webhooks Blockradar uses webhooks to notify your backend when blockchain events happen, deposits, withdrawals, sweeps, and more. Set this up before testing transactions. ### Register your webhook endpoint 1. Go to your master wallet in the dashboard 2. Click **Developer → Webhook** 3. Enter your backend endpoint URL (must be a `POST` endpoint) ### Handle webhooks in your backend ```javascript theme={null} app.post("/webhook-handler", (req, res) => { const event = req.body; console.log("Webhook received:", event); // Handle event based on event type res.sendStatus(200); }); ``` ### Common webhook events | Event | Description | | - | - | | `deposit.success` | A deposit was received at a child address | | `deposit.swept.success` | Funds were swept from a child address to the master wallet | | `withdraw.success` | A withdrawal was sent successfully | | `swap.success` | A swap was executed successfully | See all event types, payload schemas, retry logic, and HMAC verification. *** ## Step 6: Handle a deposit event When a user sends USDC to their address, Blockradar fires a `deposit.success` event to your webhook endpoint. ### Sample payload ```json theme={null} { "event": "deposit.success", "data": { "amountPaid": "10.0", "currency": "USD", "senderAddress": "0xabc...", "recipientAddress": "0xdef...", "metadata": { "user_id": 1234 } } } ``` ### How to process it Extract `metadata.user_id` from the payload. This maps the deposit to a user in your database. Use `data.amountPaid` to determine how much was deposited. Apply any deposit fee by subtracting from this value before saving. Credit the user's balance in your database. If auto sweep is enabled, the funds are already in your master wallet. *** ## What you've built You now have a complete stablecoin payment flow: * A master wallet on testnet * Child addresses tied to users via metadata * Auto sweep consolidating funds into your treasury * Gasless transactions removing friction for your users * A webhook handler updating balances in real time ## Where to go next Send stablecoins to your users or partners programmatically. Screen addresses before sending or receiving funds. Let users swap between stablecoins with a single API call. Enable Live Mode in the dashboard and start accepting real funds. # Guides Overview Source: https://docs.blockradar.co/en/guides/overview Step-by-step guides to help you integrate Blockradar quickly. Everything you need to go from zero to a live integration. Follow the guides in order or jump to what you need. Go from zero to a live stablecoin integration in under 2 hours. Sign up, complete business info, and get your workspace ready in minutes. Set up a master wallet, pick your network, and start receiving deposits. Generate dedicated deposit addresses for your users and track balances in real time. Receive payments, send funds, and monitor transactions from the dashboard, no code required. Step-by-step guide to recovering native and custom tokens sent to the wrong chain. Use Blockradar's Smart Contract API to read from and write to any onchain contract. Interpret, complete, and validate schemas returned by Blockradar API flows. # Recover Tokens Sent to the Wrong Blockchain Source: https://docs.blockradar.co/en/guides/recover-tokens Step-by-step guide to recovering native and custom tokens sent to the wrong chain using Blockradar Asset Recovery. If you've ever sent tokens to the correct address but on the wrong blockchain, you know that gut-drop moment when it feels like your funds have vanished. With Blockradar Asset Recovery, getting your tokens back is possible and simpler than you might think. With Blockradar Asset Recovery, you can: * Recover native tokens on all supported blockchains * Recover custom tokens (ERC-20 and other compatible assets) on supported networks * Recover tokens on unsupported or custom networks by providing your own RPC endpoint * Recover tokens on Layer 2 networks (Arbitrum, Optimism, Base, and other EVM-compatible rollups) *** ## Prerequisites Before starting a recovery, have the following information ready: | Field | Description | | - | - | | **Recovery Blockchain** | The blockchain where the lost tokens currently reside (e.g. Ethereum, BNB Chain, Polygon) | | **Token Contract Address** | Required only for custom (non-native) tokens | | **Recover From Address** | The Blockradar address that accidentally received the tokens | | **Recover To Address** | The address where recovered assets should be sent | *** ## Recovering via the Dashboard ### Step 1: Retrieve Transaction Information If you're missing any recovery details, look up your **transaction hash** on the relevant blockchain explorer and note: * The blockchain network used * The receiving address (your Blockradar address) * The token contract address (for custom tokens) * The amount transferred OpBNB custom token on BNB chain Bitcoin custom token on BNB chain ### Step 2: Fill in Recovery Details On your Blockradar dashboard, navigate to **Asset Recovery** and fill in the required fields. **For native tokens:** Native token recovery form **For custom tokens:** Custom token recovery form Ensure your wallet has enough native token balance to cover gas fees for the recovery transaction. ### Step 3: Submit Recovery 1. Click **Recover Assets** 2. Enter the OTP from your authenticator app 3. Confirm the action Once completed, verify the recovery by checking the destination address in your dashboard or searching the transaction hash on the block explorer for the selected chain. *** ## Recovering via a Custom RPC or Layer 2 Chain If your lost assets exist on a blockchain not officially supported by Blockradar, you can recover them using a custom RPC URL. **Additional prerequisites:** | Field | Description | | - | - | | **RPC Endpoint** | A valid HTTPS RPC URL for the blockchain you're recovering from. Free RPC endpoints are available from [PublicNode](https://publicnode.com). | | **Layer 2 Network** | Enable this toggle if the RPC URL points to an L2 chain (Arbitrum, Optimism, Base, etc.) | **Steps:** 1. Enable **Use Custom RPC** 2. Select the Master Wallet associated with your recovery address 3. Paste your RPC URL 4. Toggle **Layer 2 Network** if applicable 5. Fill in all other fields as described above 6. Click **Recover Assets**, verify OTP, and confirm Custom RPC recovery form *** ## Recovering via the API You can also recover assets programmatically using the Asset Recovery API — ideal for building custom flows or integrating recovery into backend systems. ### Required Parameters | Parameter | Description | | - | - | | `walletId` | Your Blockradar master wallet ID | | `blockchainId` | The unique ID of the blockchain the transaction was performed on | | `senderAddress` | The Blockradar address holding the lost token | | `recipientAddress` | The address to send the recovered token to | | `amount` | Amount of the token to recover | | `tokenAddress` | Smart contract address of the token (custom tokens only) | | `rpcUrl` | RPC endpoint for unsupported networks (optional) | | `isL2` | Whether the RPC points to a Layer 2 chain (optional) | ### Step 1: Estimate the Network Fee Before initiating recovery, estimate the gas cost: ```bash theme={null} curl --request POST \ --url "https://api.blockradar.co/v1/wallets/{walletId}/salvage/network-fee" \ --header "Content-Type: application/json" \ --header "x-api-key: " \ --data '{ "amount": "2.5", "blockchainId": "", "senderAddress": "0xYourBlockradarAddress", "recipientAddress": "0xRecipientAddress", "tokenAddress": null }' ``` **Response:** ```json theme={null} { "data": { "balance": "0.1", "fee": "0.000021" }, "message": "Salvage network fee fetched successfully", "statusCode": 200 } ``` For custom tokens, include `"tokenAddress": "0xTokenContractAddress"` in the request body. ### Step 2: Execute the Recovery After confirming the fee and available balance, initiate the recovery: ```bash theme={null} curl --request POST \ --url "https://api.blockradar.co/v1/wallets/{walletId}/salvage" \ --header "Content-Type: application/json" \ --header "x-api-key: " \ --data '{ "amount": "2.5", "blockchainId": "", "senderAddress": "0xYourBlockradarAddress", "recipientAddress": "0xRecipientAddress", "tokenAddress": null }' ``` ### Step 3: Monitor Recovery Status Listen for these webhook events to confirm the outcome: | Event | Description | | - | - | | `salvage.success` | Recovery completed successfully | | `salvage.failed` | Recovery failed | *** ## Troubleshooting If you run into issues, check the following: * **Wrong wallet ID** — make sure you're using the master wallet ID, not a child address ID * **Missing token contract address** — required for all custom (non-native) tokens * **Insufficient gas** — ensure your master wallet has enough native token to cover the recovery fee * **Custom RPC issues** — verify the RPC URL is a valid HTTPS endpoint and that the L2 toggle matches the chain type *** ## Security Notes * Blockradar is non-custodial — you control keys and policies * Every recovery is an on-chain transaction that requires gas on the source chain * OTP is required for all recovery actions on the dashboard ## API Reference | Endpoint | Description | | - | - | | [Estimate Network Fee](/en/api-reference/asset-recovery/salvage-network-fee) | Calculate the gas cost before recovery | | [Execute Recovery](/en/api-reference/asset-recovery/salvage) | Initiate the asset recovery | # Interact with Any Smart Contract Source: https://docs.blockradar.co/en/guides/smart-contract-interaction Use Blockradar's Smart Contract API to read from and write to any onchain contract — DeFi protocols, custom tokens, RWAs, and more. Blockradar's core APIs cover the most common fintech flows: stablecoin deposits, payouts, swaps, and settlements. But what if you need to go beyond what's natively supported? What if you need to interact with a DeFi protocol, your own token contract, or an onchain service unique to your business? That's where the **Smart Contract API** comes in. It lets you interact with any smart contract directly from your Blockradar wallet without managing RPC endpoints, signing flows, or node infrastructure yourself. With it, you can: * Connect to **DeFi protocols** for yield or liquidity management * Automate **stablecoin lending, staking, or treasury operations** * Integrate **tokenized real-world assets (RWAs)** into your product flows * Power **programmable settlements, payouts, or compliance checks** using onchain logic * Extend your platform with **custom tokens, reward systems, or fee rules** The Smart Contract API gives you three capabilities: read contract state, write to contracts, and estimate gas before execution. *** ## Prerequisites Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. You'll need a `walletId` for all smart contract operations. You need the ABI (Application Binary Interface) for the contract function you want to call. This is publicly available for verified contracts on block explorers like Etherscan. The onchain address of the smart contract you want to interact with. *** ## How It Works In this guide, we'll walk through a real example: swapping an unsupported token into USDT using Uniswap V2. The same pattern applies to any smart contract interaction. The flow: 1. **Read** the token balance from the contract 2. **Approve** Uniswap to spend the token 3. **Estimate** the network fee for the swap 4. **Execute** the swap 5. **Confirm** via webhook *** ## Step 1: Understand the Contract We'll use Uniswap V2 Router's `swapExactTokensForTokens` method. **Method signature:** ```solidity theme={null} function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); ``` | Parameter | Description | | - | - | | `amountIn` | Amount of the token you want to sell | | `amountOutMin` | Minimum amount of output token you'll accept (slippage protection) | | `path` | Token addresses for the swap route | | `to` | Your Blockradar wallet address (receives the output token) | | `deadline` | Unix timestamp after which the transaction expires | *** ## Step 2: Read the Token Balance Before swapping, check how much of the token your wallet holds using `contracts/read`. ```javascript theme={null} const res = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/contracts/read', { method: 'POST', headers: { 'x-api-key': '', 'Content-Type': 'application/json' }, body: JSON.stringify({ abi: [{ "constant": true, "inputs": [{ "name": "_owner", "type": "address" }], "name": "balanceOf", "outputs": [{ "name": "balance", "type": "uint256" }], "stateMutability": "view", "type": "function" }], address: "0xUnsupportedTokenAddress", method: "balanceOf", parameters: ["0xYourWalletAddress"] }) } ).then(r => r.json()); // Response: // { "data": "1000000000000000000", "message": "Contract read successfully" } ``` | Parameter | Description | | - | - | | `abi` | The ABI of the contract function you're calling | | `address` | The token's smart contract address | | `method` | The function name to call | | `parameters` | Arguments for the function | Use the balance returned here as the `amountIn` value for your swap call. *** ## Step 3: Approve the Contract to Spend Your Token Before Uniswap can move your token, you need to grant it permission using the token contract's `approve` function. ```javascript theme={null} await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/contracts/write', { method: 'POST', headers: { 'x-api-key': '', 'Content-Type': 'application/json' }, body: JSON.stringify({ abi: [{ "inputs": [ { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "approve", "outputs": [], "stateMutability": "nonpayable", "type": "function" }], address: "0xUnsupportedTokenAddress", method: "approve", parameters: ["0xUniswapRouterAddress", "1000000000000000000"] }) } ); ``` Do not proceed to the swap immediately after submitting the approval. Wait for the `custom-smart-contract.success` webhook confirming the approval transaction was mined before moving to the next step. **Approval webhook payload:** ```json theme={null} { "event": "custom-smart-contract.success", "data": { "status": "SUCCESS", "type": "CUSTOM_SMART_CONTRACT", "hash": "0xfedcba098765...", "tokenAddress": "0xUnsupportedTokenAddress" } } ``` *** ## Step 4: Estimate the Network Fee Before executing the swap, estimate the gas cost to ensure your wallet has enough native token to cover it. ```javascript theme={null} const fee = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/contracts/network-fee', { method: 'POST', headers: { 'x-api-key': '', 'Content-Type': 'application/json' }, body: JSON.stringify({ abi: [ /* ABI of swapExactTokensForTokens */ ], address: "0xUniswapRouterAddress", method: "swapExactTokensForTokens", parameters: [ "1000000000000000000", "990000", ["0xUnsupportedTokenAddress", "0xUSDTAddress"], "0xYourWalletAddress", Math.floor(Date.now() / 1000) + 60 * 20 ] }) } ).then(r => r.json()); // Response: // { "data": { "balance": "1.0123", "fee": "0.00422" } } ``` *** ## Step 5: Execute the Swap Once the approval is confirmed and you've reviewed the fee, execute the swap. ```javascript theme={null} const swap = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/contracts/write', { method: 'POST', headers: { 'x-api-key': '', 'Content-Type': 'application/json' }, body: JSON.stringify({ abi: [ /* ABI of swapExactTokensForTokens */ ], address: "0xUniswapRouterAddress", method: "swapExactTokensForTokens", parameters: [ "1000000000000000000", "990000", ["0xUnsupportedTokenAddress", "0xUSDTAddress"], "0xYourWalletAddress", Math.floor(Date.now() / 1000) + 60 * 20 ] }) } ).then(r => r.json()); // Response: // { "message": "Contract write initiated successfully", "data": { "status": "PENDING" } } ``` Listen for the webhook to confirm completion: ```json theme={null} { "event": "custom-smart-contract.success", "data": { "status": "SUCCESS", "type": "CUSTOM_SMART_CONTRACT", "hash": "0xfedcba098765...", "tokenAddress": "0xUniswapRouterAddress" } } ``` *** ## Webhook Events | Event | Description | | - | - | | `custom-smart-contract.success` | Contract write confirmed on-chain | | `custom-smart-contract.failed` | Contract write failed | *** ## Other Endpoints | Endpoint | Description | | - | - | | `POST /v1/wallets/{walletId}/contracts/read` | Read state from any contract | | `POST /v1/wallets/{walletId}/contracts/write` | Execute any contract function | | `POST /v1/wallets/{walletId}/contracts/network-fee` | Estimate gas before execution | | `POST /v1/wallets/{walletId}/contracts/write/sign` | Sign a transaction without broadcasting | *** ## Security Notes * All transactions are signed and broadcast through Blockradar's infrastructure — no need to manage private keys or RPC nodes * Native AML and compliance checks apply where possible * Every contract interaction is a real on-chain transaction and requires gas in the native token of the chain *** ## API Reference | Endpoint | Description | | - | - | | [Master Wallet Read](/en/api-reference/smart-contract/master-wallet-read) | Read contract state from master wallet | | [Master Wallet Write](/en/api-reference/smart-contract/master-wallet-write) | Execute contract function from master wallet | | [Master Wallet Network Fee](/en/api-reference/smart-contract/master-wallet-network-fee) | Estimate gas from master wallet | | [Child Address Read](/en/api-reference/smart-contract/child-address-read) | Read contract state from child address | | [Child Address Write](/en/api-reference/smart-contract/child-address-write) | Execute contract function from child address | | [Child Address Network Fee](/en/api-reference/smart-contract/child-address-network-fee) | Estimate gas from child address | # Use Without Code Source: https://docs.blockradar.co/en/guides/use-without-code Receive payments, send funds, and monitor transactions from the dashboard, no code required. Blockradar Dashboard You don't need to write a single line of code to start using Blockradar. The dashboard gives you full access to wallets, payments, and transaction monitoring through a visual interface. This guide is for operators, finance teams, and anyone who wants to use Blockradar without a technical integration. ## What you can do without code * Create and manage master wallets * Generate payment links and share them with customers * Send manual withdrawals to any address * Monitor all inbound and outbound transactions * View and replay webhook delivery logs * Screen addresses with AML before sending * Export transaction history ## Create a payment link Payment links let you accept stablecoin payments without any integration. You share a link, your customer pays, and you see the funds arrive in your dashboard. In the left sidebar, click **My Wallets → Payment Links**. Click **Create Link**. Set the amount, token, and expiry date. Leave the amount blank to let the payer enter any amount. Copy the generated URL and share it with your customer via email, WhatsApp, or any other channel. When payment is received, you'll see it in the **Transactions** tab of the payment link. You'll also receive a dashboard notification. ## Send a manual withdrawal Go to **Wallets** and select the wallet you want to send from. Click the **Withdraw** button on the wallet overview page. Paste the destination address, select the asset and amount, then confirm. Enter your 2FA code to authorize the transaction. Withdrawals are irreversible once broadcast to the blockchain. Double-check the destination address before confirming. ## Monitor transactions The **Transactions** tab on any wallet shows every deposit and withdrawal in real time. You can: * Filter by status, asset, date range, or address * Click any transaction to see the full on-chain details * Export to CSV for accounting or reconciliation * Replay a webhook if your backend missed a notification ## Screen an address before sending Before sending funds to a new counterparty, you can run an AML check directly from the dashboard: In the sidebar, click **My Wallets → AML Lookup**. Paste the wallet address you want to screen. Blockradar checks against OFAC, FBI, Tether, and Circle blocklists and returns a risk assessment instantly. This feature is only available in Live Mode (mainnet). ## Next steps When you're ready to automate and scale, move to the API: Build a full stablecoin payment flow with the API. Explore all available endpoints. # API Tour Source: https://docs.blockradar.co/en/introduction/api-tour A quick overview of how the Blockradar API is structured. The Blockradar API is RESTful and gives you programmatic access to every feature available on the dashboard. It is organized around the core resources you interact with: wallets, addresses, transactions, and the products built on top of them. Before you begin, [create a free Blockradar account](https://dashboard.blockradar.co/signup) to get your API keys. You can test against our sandbox environment before going live. ## Base URL All API requests are made to: ``` https://api.blockradar.co/v1 ``` ## Request and response format All request bodies and responses are formatted as JSON. Every response follows this structure: ```json theme={null} { "statusCode": 200, "message": "Request successful", "data": {} } ``` | Property | Type | Description | | - | - | - | | `statusCode` | number | HTTP status code indicating success or failure. Use this to determine the result of every call. | | `message` | string | A human-readable summary of the response. On errors, this describes what went wrong. | | `data` | object or array | The result of your request. A single resource returns an object; a list returns an array. | ## Pagination List endpoints return a `meta` object alongside `data`: ```json theme={null} { "meta": { "totalItems": 704, "itemCount": 100, "itemsPerPage": 100, "totalPages": 8, "currentPage": 1 } } ``` | Property | Description | | - | - | | `totalItems` | Total number of items across all pages. | | `itemCount` | Number of items on the current page. | | `itemsPerPage` | Pagination limit per page. Default: `100`. | | `totalPages` | Total number of pages available. | | `currentPage` | The current page being returned. Default: `1`. | ## Postman collection Prefer exploring APIs visually? Use the [Blockradar Postman Collection](https://documenter.getpostman.com/view/7709133/2s93eSYaVs) to browse and test every endpoint interactively. Learn how to authenticate your API requests. Understand error codes and how to handle them. *** ## Wallets Manage your master wallets, balances, and sweep operations. Generate and manage child addresses for your users. Receive real-time notifications for deposits, withdrawals, and on-chain events. Sign messages and typed data from any Blockradar wallet. Retrieve, manage, and replay transactions across your wallets. Configure which assets are active on your master wallet. ## Receive Payments Accept stablecoin deposits via dedicated blockchain addresses. Create and manage stablecoin payment links. Issue bank account numbers linked to on-chain wallets for fiat deposits. ## Send Payments Send stablecoins from master wallets or child addresses. Convert stablecoins to fiat and send to bank accounts. ## Convert & Manage Move USDC natively across chains using Circle's CCTP protocol. Swap stablecoins across assets and chains. Configure rules to automatically convert and route assets. Manage stablecoin liquidity rates for corridor-based settlement. ## Compliance & Recovery Screen wallet addresses against global sanctions and blocklists. Recover tokens accidentally sent to unsupported wallet addresses. ## Integrations Read and write to any smart contract from a Blockradar wallet. Retrieve supported assets, blockchains, and exchange rates. # Build with AI Source: https://docs.blockradar.co/en/introduction/build-with-ai Connect Claude, Cursor, and other AI tools to the Blockradar docs so they answer from current documentation. Give your AI assistant or coding agent direct access to the Blockradar docs, so it answers from current documentation instead of what it remembers from training. There are three ways to do it: | Method | Best for | | - | - | | [MCP server](#connect-the-mcp-server) | Coding agents and IDEs that look up the docs while they work | | [Page menu](#chat-about-a-page) | Asking an AI chat about a single page | | [Markdown and llms.txt](#fetch-the-docs-as-markdown) | Scripts, custom agents, and RAG pipelines | ## Connect the MCP server The Blockradar docs MCP server is hosted at: ```text theme={null} https://docs.blockradar.co/mcp ``` It uses the Streamable HTTP transport and needs no API key. Once connected, your AI tool can: * **Search the docs** for guides, code examples, and API reference pages. * **Read pages and the OpenAPI spec** to look up exact endpoints, parameters, and response fields. * **Report a docs problem** to the Blockradar team when a page is wrong or out of date. The MCP server reads public documentation only. It can't access your Blockradar account, wallets, or transactions, and it doesn't call the Blockradar API. Using Cursor or VS Code? Open the menu next to **Copy page** and choose **Connect to Cursor** or **Connect to VS Code** to install the server in one click. Run this command in your terminal: ```bash theme={null} claude mcp add --transport http blockradar-docs https://docs.blockradar.co/mcp ``` This adds the server to the current project. To use it in every project, run the same command with `--scope user`. Add the server to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` to use it in every project: ```json theme={null} { "mcpServers": { "blockradar-docs": { "url": "https://docs.blockradar.co/mcp" } } } ``` Add the server to `.vscode/mcp.json` in your workspace: ```json theme={null} { "servers": { "blockradar-docs": { "type": "http", "url": "https://docs.blockradar.co/mcp" } } } ``` Add the server as a custom connector in Claude Desktop or on claude.ai: 1. Go to **Customize > Connectors**. 2. Click **+**, then **Add custom connector**. 3. Enter `https://docs.blockradar.co/mcp` as the server URL, then click **Add**. On Team and Enterprise plans, an Owner first adds the connector in **Organization settings > Connectors**. Members then connect to it from **Customize > Connectors**. Add the server to `~/.codeium/windsurf/mcp_config.json`: ```json theme={null} { "mcpServers": { "blockradar-docs": { "serverUrl": "https://docs.blockradar.co/mcp" } } } ``` ### What to ask it Once connected, your assistant answers from the docs instead of guessing at endpoints. Try one of these — if the server is connected, it searches the Blockradar docs before it answers: * "Create a child address on Base and verify the `x-blockradar-signature` header when a USDC deposit webhook arrives." * "Estimate the network fee for a USDT withdrawal on Tron before I execute it." * "Move USDC from Base to Arbitrum with Gateway, and tell me how long finality takes on each chain." * "Validate a customer-supplied Solana address before I queue a withdrawal, and show me what an invalid address returns." ## Chat about a page Every docs page has a **Copy page** button in the top-right corner. Open the menu next to it for more options: The page menu on a Blockradar docs page, open and showing Copy page, View as Markdown, Open in ChatGPT, Open in Claude, Open in Perplexity, Copy MCP Server, Connect to Cursor, and Connect to VS Code | Option | What it does | | - | - | | **Copy page** | Copies the page as Markdown to paste into any AI chat | | **View as Markdown** | Opens the page as plain Markdown | | **Open in ChatGPT** | Starts a ChatGPT conversation with the page as context | | **Open in Claude** | Starts a Claude conversation with the page as context | | **Open in Perplexity** | Starts a Perplexity conversation with the page as context | | **Copy MCP Server** | Copies the MCP server URL | | **Connect to Cursor** | Installs the MCP server in Cursor | | **Connect to VS Code** | Installs the MCP server in VS Code | Use it to ask questions about one page, generate code from an API reference page, or debug an integration with the right page loaded. ## Fetch the docs as Markdown For scripts, custom agents, and RAG pipelines, load the docs as plain text: | Resource | URL | Use it for | | - | - | - | | Any page | Add `.md` to the page URL, for example [`/en/introduction/build-with-ai.md`](https://docs.blockradar.co/en/introduction/build-with-ai.md) | Loading a single page | | `llms.txt` | [docs.blockradar.co/llms.txt](https://docs.blockradar.co/llms.txt) | An index of the docs pages with their titles and descriptions | | `llms-full.txt` | [docs.blockradar.co/llms-full.txt](https://docs.blockradar.co/llms-full.txt) | The full documentation in a single file | # FAQ Source: https://docs.blockradar.co/en/introduction/faq Answers to the most common questions about Blockradar. ## Deposits & Webhooks This is usually a temporary indexing delay. Use the Deposit Finder to manually trigger indexing: * **Dashboard:** Go to your Master Wallet → Overview → Click "Deposit Finder" * **API:** `POST /v1/wallets/{walletId}/rescan/blocks` with the `transactionHash` [Deposit Finder Documentation →](/en/essentials/wallets) Webhook delays can occur due to blockchain network congestion, temporary node indexing delays, or your webhook endpoint returning errors. To check webhook logs: * **Dashboard:** Master Wallet → Developers → Webhook Logs * **API:** `GET /v1/wallets/{walletId}/webhooks` To have a webhook delivered again, use [Resend Webhook](/en/api-reference/transactions/resend-webhook). Blockradar only indexes stablecoins by design. Native token deposits (ETH, TRX, SOL, etc.) won't appear in the dashboard transaction history. However, the funds are still in your wallet and can be viewed on the blockchain explorer or withdrawn via API or dashboard. ## Auto-Sweep By default, `disableAutoSweep` is set to `false`, meaning auto-sweep is enabled. When a deposit arrives at a child address, it automatically sweeps to your master wallet. To keep funds in child addresses: * Set `disableAutoSweep: true` when creating the address via API * Or toggle **Disable Auto Sweep** in the address settings on the dashboard Check both configuration levels: * **Master wallet level** — sets the default for all addresses * **Address level** — overrides the master wallet setting The address-level setting always takes priority. Verify the specific address has `disableAutoSweep: true`. Yes. You can configure sweep thresholds so funds only auto-sweep once a certain balance is reached. [Wallet Configuration →](/en/essentials/wallets) ## Gas Fees & Network Costs Gas fees are paid directly to the blockchain in the chain's native token — for example ETH on Ethereum, Base, Arbitrum and Optimism, BNB on BNB Chain, POL (formerly MATIC) on Polygon, TRX on Tron, SOL on Solana, and XLM on Stellar. Blockradar does not mark up network gas: you pay only what the blockchain charges. Other products can carry their own charges — see Fees & Pricing below. Tron network fees are typically \$1–6 per transaction due to how Tron handles bandwidth and energy. This is a blockchain-level cost, not a Blockradar charge. Lower-cost alternatives: * **Solana:** \~\$0.01–0.30 per transaction * **Base:** \~\$0.01–0.10 per transaction * **Polygon:** \~\$0.01–0.10 per transaction The `/withdraw/network-fee` endpoint returns a conservative estimate to ensure transactions succeed even during high network congestion. You are only charged the actual network fee, which is typically lower than the estimate. No, blockchain gas fees must be paid in the chain's native token. However, you can enable gasless withdrawals so your master wallet sponsors gas for child address transactions. ## Address Activation (Stellar, Tron, Solana) Some blockchains require an address to be activated or funded before it can hold tokens. This is a network rule, not a Blockradar charge, and your wallet is not being drained: | Chain | Cost | Paid by | Where the funds go | | - | - | - | - | | Stellar | 1 XLM account minimum + 0.5 XLM for each Stellar asset enabled on the wallet (2 XLM with USDC and EURC) | Master wallet, at address creation | Locked as reserve **inside the new address** | | Tron | 1 TRX, once, on the first TRX transfer to the address | Sender of that first transfer | Burned by the Tron network | | Solana | \~0.00089 SOL per wallet account, \~0.00204 SOL per token account | Fee payer (master wallet) | Locked as rent deposit in the account | [Address Activation →](/en/essentials/address-activation) Issue the address as dormant with `enableIndexing: false`. Activation is deferred until you [enable indexing](/en/essentials/addresses#enable-indexing) on it, so you only fund the reserve for addresses your customers actually use. The most common cause is an underfunded master wallet. Top up your Stellar master wallet with XLM — pending activations retry automatically once funds arrive. Check `configurations.stellar.lastError` on the address for the specific reason. ## Gasless Transactions When gasless is enabled, the master wallet pays gas fees on behalf of child address withdrawals. To enable: * **Master wallet level:** Dashboard → Master Wallet Settings → Enable Gasless Transactions * **Address level:** Set `enableGaslessWithdraw: true` when creating or updating an address You can also set thresholds so only withdrawals above or below certain amounts are covered. [Gasless Transactions →](/en/use-cases/withdraw-stablecoins) · [Address Parameters →](/en/essentials/addresses) It depends on the `enableGaslessWithdraw` setting: * **Enabled (`true`):** Master wallet pays gas * **Disabled (`false`, default):** Child address needs its own gas ## Swaps & Bridges Blockradar supports stablecoin-to-stablecoin swaps (for example USDT ↔ USDC) and swaps between stablecoins and native tokens (for example SOL → USDC or USDC → TRX), both on the same chain and across chains. Liquidity varies by pair, chain and amount, so request a quote to confirm a specific route before offering it to users. [Swap Documentation →](/en/use-cases/swap) Common causes: * No route or liquidity is currently available for that pair on that chain * The amount is too small or too large for available liquidity * The asset is not enabled on your wallet Try a different amount, or check that both assets are enabled on the wallets involved. This error usually means you're using the wrong asset ID. You need to use the **wallet-specific asset ID**, not a general asset ID. To find the correct ID: * **Dashboard:** Go to your wallet → Assets → Copy the asset ID from there * **API:** Use the asset IDs returned from your wallet details endpoint Yes. You can swap and bridge assets across different blockchains via the dashboard or API. For cross-chain swaps via API, pass the destination master wallet's asset ID as the `toAssetId`. [Swap Documentation →](/en/use-cases/swap) ## Wallet Setup & Configuration Yes. Each blockchain network needs its own Master Wallet, and that includes each EVM chain — a Base wallet does not cover Ethereum, Polygon or Arbitrum. Create one Master Wallet per chain you want to support. [Create a Master Wallet →](/en/guides/create-master-wallet) Blockradar allows only one Master Wallet per blockchain network per account. To support an additional blockchain, you must create a separate Master Wallet for it. Within a single Master Wallet, you can create as many child addresses as needed to segment funds by user, application, or purpose. Creating multiple Master Wallets for the same blockchain is not supported. No, addresses cannot be deleted due to blockchain limitations. You can only deactivate them in the dashboard. Deactivated addresses won't receive new deposits or be monitored. Yes. Address whitelisting lets you add an external address to your wallet so Blockradar monitors its deposits, without changing your existing setup. [Address Whitelisting →](/en/essentials/addresses#address-whitelisting) Use the `showPrivateKey: true` parameter when fetching wallet or address details via API. Only use this in secure, trusted environments. ## Withdrawals & Transfers Use the withdrawal API endpoint: `POST /v1/wallets/{walletId}/addresses/{addressId}/withdraw` [Withdrawal Documentation →](/en/use-cases/withdraw-stablecoins) Common causes: * Insufficient gas in the master wallet (if using gasless) or child address * Queue processing — transactions process sequentially due to blockchain nonces * Node issues — temporary delays If stuck for more than 30 minutes, contact support with the transaction ID. Yes: * **Retry a failed transaction:** [Retry Transaction](/en/api-reference/transactions/retry-transaction) * **Cancel a transaction that hasn't been processed:** [Cancel Transaction](/en/api-reference/transactions/cancel-transaction) * **Deliver the webhook again:** [Resend Webhook](/en/api-reference/transactions/resend-webhook) Yes. Sign-only mode signs the transaction and returns it without submitting it to the blockchain — useful for offline signing, multi-signature workflows, or inspecting a transaction before broadcasting. * **Master wallet:** `POST /v1/wallets/{walletId}/withdraw/sign` * **Child address:** `POST /v1/wallets/{walletId}/addresses/{addressId}/withdraw/sign` [Sign-Only Mode →](/en/use-cases/withdraw-stablecoins#sign-only-mode) All on-chain fund movements use the withdrawal endpoint. There is no separate "transfer" endpoint. * **Master to child:** `POST /v1/wallets/{walletId}/withdraw` with child address as destination * **Child to master:** `POST /v1/wallets/{walletId}/addresses/{addressId}/withdraw` with master wallet address as destination * **Child to external:** Same endpoint, external address as destination [Withdrawal Documentation →](/en/use-cases/withdraw-stablecoins) Use the transactions endpoint with the address query parameter: ``` GET /v1/wallets/{walletId}/transactions?address={addressId} ``` [Transactions Documentation →](/en/api-reference/transactions/get-transactions) ## Asset Recovery Use Asset Recovery in the dashboard. [Asset Recovery →](/en/use-cases/asset-recovery) ## Test Mode vs. Live Mode No, your funds are not lost. Mainnet and testnet are separate networks, but addresses are cryptographically linked. You can recover funds using Asset Recovery. [Asset Recovery →](/en/use-cases/asset-recovery) Always check the environment indicator in the dashboard (shows "Test Mode" or "Live Mode") before transacting. 1. Use the environment toggle in your dashboard (usually top-right or in wallet settings) 2. Switch from **Test Mode** to **Live Mode** 3. Create a new master wallet for mainnet 4. Update your API keys — Test Mode keys won't work in Live Mode Testnet addresses cannot receive mainnet funds and vice versa. Native tokens for gas: | Chain | Token | Faucet | | - | - | - | | Ethereum | ETH | [Alchemy Faucet](https://www.alchemy.com/faucets/ethereum-sepolia) • [Infura Faucet](https://www.infura.io/faucet/sepolia) | | BNB Smart Chain | BNB | [BNB Chain Faucet](https://www.bnbchain.org/en/testnet-faucet) | | Polygon | MATIC | [Polygon PoS (Amoy Faucet)](https://faucet.polygon.technology/) | | Base | ETH | [Alchemy Faucet](https://www.alchemy.com/faucets/base-sepolia) | | Optimism | ETH | [Alchemy Faucet](https://www.alchemy.com/faucets/optimism-sepolia) | | Arbitrum | ETH | [Alchemy Faucet](https://www.alchemy.com/faucets/arbitrum-sepolia) | | Tron | TRX | [Nileex](https://nileex.io/join/getJoinPage) | | Solana | SOL | [Solana Faucet](https://faucet.solana.com/) | | Stellar | XLM | [Stellar Friendbot](https://friendbot.stellar.org) | | Celo | CELO | [Celo Faucet](https://faucet.celo.org/alfajores) | | Lisk | ETH | [Lisk Faucet](https://console.optimism.io/faucet) | | Avalanche | AVAX | [Avalanche Faucet](https://core.app/tools/testnet-faucet/) | | Asset Chain | RWA | [Asset Chain Faucet](https://faucet.assetchain.org/) | | Arc | USDC | [Arc Faucet](https://faucet.circle.com/) | | Plasma | XPL | [Plasma Faucet](https://plasma.to/docs/plasma-chain/tools/faucets) | | Tempo | Alpha USD | [Tempo Faucet](https://docs.tempo.xyz/quickstart/faucet) | For testnet USDC and EURC on most chains, use the [Circle Faucet](https://faucet.circle.com). Stablecoin faucets for every chain are listed on [Supported Assets](/en/use-cases/supported-assets). ## API Errors & Troubleshooting Common causes: * Wrong wallet ID * Wrong API key (doesn't match the wallet) * Using a general asset ID instead of a wallet-specific asset ID Usually a temporary issue. If it persists, contact support with the endpoint you're calling, the blockchain/network, and the full error response. Your API key is invalid or doesn't match the wallet you're trying to access. Check that: * The API key is correct (no extra spaces) * The API key belongs to this wallet * You're not using a Test Mode key in Live Mode (or vice versa) * The API key hasn't been rotated or regenerated The resource (wallet, address, or asset) doesn't exist or you're using the wrong ID. Common causes include a wrong wallet ID or address ID, using a general asset ID instead of a wallet-specific one, or a typo in the endpoint URL. You have exceeded the API rate limit. Slow down and retry after a short wait, ideally with exponential backoff. Avoid polling in tight loops — use webhooks for transaction updates, and cache responses from discovery endpoints (supported assets, currencies, blockchains) instead of calling them on every request. [Errors →](/en/about-the-api/errors) ## Fees & Pricing Not on gas — Blockradar passes network fees through without a markup. Some products carry their own charges: * **Swaps and fiat conversions** can include a markup on the exchange rate * **Fiat deposits and payouts** can carry a processing fee * **Virtual account creation** can carry a fixed fee * **Earn** takes its fee from earnings when you withdraw, never from your deposit Rates depend on your plan and commercial terms. Quote endpoints show the rate and fees for a specific transaction before you execute it. For your account's pricing, contact [info@blockradar.co](mailto:info@blockradar.co). ## Virtual Accounts & Fiat Deposits * **Compliance approval:** Complete the due diligence process under **My Wallets → Settings → Compliance** in the dashboard * **Feature activation:** After compliance approval, request virtual account activation from [support@blockradar.co](mailto:support@blockradar.co) or via live chat on the dashboard * **A paid plan with stablecoin access:** Depositing fiat and converting it to stablecoins is a paid feature. Upgrade from **Dashboard → Settings → Subscription** * **The right environment:** Test Mode requests use only testnet routes and wallets; Live Mode requests use only mainnet routes and wallets [Virtual Accounts Documentation →](/en/use-cases/virtual-accounts) Virtual Accounts only appear once your compliance has been approved, the feature has been activated for your account, and your plan includes stablecoin access. * **Reusable [Virtual Accounts](/en/use-cases/virtual-accounts)** are long-lived bank accounts tied to a master wallet or child address. Every deposit to them converts to stablecoins — good for recurring customer deposits. * **[Deposit Fiat payment orders](/en/use-cases/payment-orders)** create a one-time virtual account for a single expected payment. The account is valid for that one payment only. Deposits are currently live in ARS, BRL, COP, EUR, KES, MXN and USD. NGN virtual accounts are temporarily paused. NGN payouts through Withdraw Fiat are not affected. Availability varies by corridor and wallet, so check what your wallet supports before presenting an option: use the [Virtual Accounts discovery endpoint](/en/api-reference/virtual-accounts/discovery-v2) for reusable accounts, or [Get Supported Currencies](/en/api-reference/deposit-fiat/get-supported-currencies) for Deposit Fiat. No. AUD, CAD, GHS, THB, TRY, TZS, UGX, XOF and ZAR are payout-only: you can pay out to them with [Withdraw Fiat](/en/use-cases/withdraw-fiat), but users cannot deposit them. cNGN is a Nigerian Naira-pegged stablecoin. Blockradar supports cNGN transactions and swaps with other stablecoins. ## Fiat Payouts (Withdraw Fiat) Use [Withdraw Fiat](/en/use-cases/withdraw-fiat). It converts supported stablecoins to fiat and pays out to bank accounts, mobile money and other local rails, from a master wallet or a child address. The flow discovers the payment methods for a corridor, tells you exactly which beneficiary details each one needs, then quotes and executes the payout. Payouts are currently live in ARS, AUD, BRL, CAD, COP, EUR, GHS, KES, MXN, NGN, THB, TRY, TZS, UGX, USD, XOF and ZAR. Availability varies by corridor and wallet, so fetch the live list with [Get Supported Currencies](/en/api-reference/withdraw-fiat/get-supported-currencies-v2) rather than hard-coding it. ## Earn Earn lets you put idle stablecoins to work in interest-bearing DeFi protocols (Aave and Compound). It is non-custodial: funds move from your own wallet, Blockradar never pools or holds them, and there is no lock-up period. [Earn →](/en/use-cases/earn) Aave is available on Ethereum, Base, Arbitrum, Optimism, Polygon and BNB Smart Chain. Compound is available on Ethereum, Base and Arbitrum. The dashboard only shows networks where Earn is available for your wallet. Depositing is free. When you withdraw, you receive exactly the amount you ask for — the fee is drawn from your earnings, never your principal. You can withdraw part or all of a position at any time. Rates are variable, and DeFi carries smart-contract risk, so returns are not guaranteed. ## Compliance & Security Yes. The AML API screens any wallet address against OFAC, FBI, Tether and Circle blocklists, so you can flag high-risk counterparties before sending or receiving funds. [AML Screening →](/en/use-cases/aml-screening) Yes. IP whitelisting restricts API requests to the IP addresses you allow, adding another layer of protection to your integration. [IP Whitelisting →](/en/use-cases/ip-whitelist) Some fiat corridors require your customers to be verified. Create customers with the Customer API, then submit their details and documents through [customer onboarding requests](/en/api-reference/customer-onboarding/create-request). Collect only the fields the requirements schema asks for — see [Dynamic Forms](/en/guides/dynamic-forms). ## Other Products Yes. [Checkout](/en/use-cases/checkout) lets you accept stablecoin payments through shareable links — no customer accounts or complex integration required. Yes. [Gateway](/en/use-cases/gateway) gives you a unified, chain-abstracted USDC balance: deposit from any supported chain and withdraw to any supported chain, without manual bridging. Yes. [Auto Settlements](/en/use-cases/auto-settlements) convert incoming deposits to your preferred asset and route them to your destination chain, based on rules you define once. The [Liquidity Pool](/en/use-cases/liquidity-pool) lets approved Liquidity Providers set exchange rates for asset pairs. Those rates power Blockradar's swap engine, which picks the best available rate from active providers. Yes. The [Smart Contract API](/en/use-cases/smart-contracts) lets you read from and write to any smart contract directly from your wallet, without managing RPC endpoints or signing flows yourself. ## Feature Requests No. Blockradar focuses on stablecoins. Bitcoin is not currently supported. Blockradar is blockchain and stablecoin agnostic — additional networks and assets can be integrated upon request. [Contact us](mailto:info@blockradar.co) to discuss your requirements. ## Billing & Subscriptions Yes. You can pay via the payment link sent to your email, or withdraw from your master wallet to the payment link address. Currently, we only support stablecoin payments for subscriptions. ## Supported Blockchains & Assets Ethereum, BNB Chain, Polygon, Tron, Base, Arbitrum, Optimism, Solana, Stellar, Celo, Lisk, Avalanche, Asset Chain, Arc, Plasma, and Tempo Blockradar is blockchain and stablecoin agnostic — additional networks can be integrated upon request. [Supported Networks →](/en/use-cases/integrations) USDT, USDC, DAI, BUSD, cUSD, cNGN, EURC, IDRX, ZARP, JPYC, MXNB, PYUSD, AlphaUSD, OUSD Additional assets can be integrated upon request. [Supported Assets →](/en/use-cases/supported-assets) ## Developer Tips * **Wallet ID:** Identifies your master wallet * **Address ID:** Identifies a specific child address within a wallet * **Asset ID:** Identifies a specific asset (USDT, USDC, etc.) within your wallet Always use the wallet-specific asset ID from your wallet's asset list, not a general asset ID. * Always use Live Mode for real transactions * Store wallet IDs and address IDs in your database * Implement webhook handlers for real-time transaction updates * Use Deposit Finder as a backup for missed transactions * Monitor master wallet balance for gas (native tokens) * Enable gasless withdrawals if your users shouldn't need to hold native tokens ## Need Help? docs.blockradar.co dashboard.blockradar.co Schedule here # Overview Source: https://docs.blockradar.co/en/introduction/overview Everything you need to know to start building with Blockradar.

Get started

Create your account

Set up a Blockradar account and immediately start building your integration. Free to start, no credit card required.

Create account →
## Common use cases Send and settle business payments internationally using stablecoins, with faster settlement and lower fees than traditional banking rails. Power low-cost, real-time money transfers across borders with stablecoin infrastructure built for high-volume corridors. Let users move seamlessly between fiat and stablecoins with API-native conversion flows. Issue wallets, accept deposits, and move money for your customers, without touching traditional banking infrastructure. Give users access to USD-backed stablecoin accounts as an alternative to local currency savings. Automate stablecoin sweeping, conversion, and settlement to optimize how your business holds and moves funds. ## Start building Sign up, complete business info, and get your workspace ready in minutes. Set up a wallet, pick your network, and start receiving deposits. Receive payments, send funds, and monitor transactions from the dashboard, no code required. Connect Claude, Cursor, and other AI tools to the Blockradar docs. ## More resources See the full Blockradar product suite: wallets, virtual accounts, gateway, liquidity pools, and more. # See All Products Source: https://docs.blockradar.co/en/introduction/see-all-products Browse the full Blockradar product suite. ## Wallets ***
Wallets

Create and manage non-custodial master wallets across any supported chain.

Addresses

Generate dedicated deposit addresses for your users and track balances in real time.

Webhooks

Receive real-time notifications for deposits, withdrawals, and other on-chain events.

Signing

Sign messages and EIP-712 typed data from any wallet or address.

Transactions

Fetch, monitor, and manage all on-chain activity across your wallets.

Asset Management

Control which tokens are active on your master wallet.

## Receive Payments ***
Deposit Stablecoins

Accept stablecoin deposits via dedicated addresses with automatic sweeping and webhook notifications.

Stablecoin Checkout

Generate shareable payment links and branded checkout flows for stablecoin payments.

Deposit Fiat

Issue bank account numbers linked to on-chain addresses for fiat-to-stablecoin funding.

## Send Payments ***
Withdraw Stablecoins

Send stablecoins programmatically from master wallets or individual user addresses.

Withdraw Fiat

Convert stablecoins to local fiat currencies and send directly to bank accounts.

## Convert & Manage ***
Gateway

Move USDC across chains natively via Circle's CCTP protocol, with no bridge risk.

Swap & Bridge

Swap and bridge stablecoins across chains with a single API call.

Auto Settlements

Automatically convert and route assets to a destination wallet based on configurable rules.

Liquidity Pool

A liquidity orchestration layer that connects customers to multiple liquidity providers, intelligently routes swaps, and manages end-to-end settlement across assets and chains.

## Compliance & Recovery ***
AML Screening

Screen addresses against OFAC, FBI, Tether, and Circle blocklists in real time.

Asset Recovery

Recover tokens accidentally sent to a wallet outside your supported asset list.

IP Whitelist

Lock your API access to approved IP addresses only for an additional layer of protection.

## Integrations ***
Smart Contracts

Read and write to any smart contract directly from your Blockradar wallet.

Supported Blockchains

Overview of blockchain networks supported by Blockradar on both mainnet and testnet.

Supported Assets

Overview of stablecoins and digital assets supported by Blockradar across all networks.

# Why Blockradar Source: https://docs.blockradar.co/en/introduction/why-blockradar Secure stablecoin wallet infrastructure for fintechs. Blockradar Blockradar is a wallet and settlement infrastructure platform for fintechs. We provide Wallet-as-a-Service (WaaS), enabling fintechs to move stablecoins without having to build or maintain the underlying blockchain infrastructure themselves. Whether you're building a remittance corridor, a neobank, a cross-border payments product, or a savings platform, Blockradar provides the APIs, wallet primitives, settlement rails, and compliance tooling you need to go live fast and scale reliably. ## What you can build Generate dedicated wallet addresses for your users and receive real-time webhook notifications on every deposit, across any supported chain. Convert stablecoins to fiat and send to bank accounts programmatically from master wallets or individual user addresses, with built-in fee estimation and gasless options. Issue bank account numbers linked to on-chain addresses. Let users fund their wallets via local bank transfer with no crypto knowledge required. Move USDC across chains natively via Circle's CCTP protocol through the Blockradar Gateway. No bridge risk, no manual intervention. Generate shareable payment links or embed a checkout flow directly into your product. Accept stablecoin payments without writing custom smart contracts. Manage stablecoin liquidity pools for corridor-based settlement, powering remittance and FX desk use cases at scale. ## Why fintechs choose Blockradar **One API, without Blockchain Complexity .** Blockradar abstracts multi-chain complexity behind a single consistent API. Add a new blockchain to your product by changing a parameter, not rewriting your integration. **Non-custodial by design.** Your users' wallets are generated and controlled through your API keys. Blockradar never holds funds on your behalf. You and your customer stay in control. **Compliance built in.** Every wallet comes with real-time AML screening against OFAC, FBI, Tether, and Circle blocklists. Flag or block transactions automatically before they settle. **Gasless transactions.** Sponsor network fees on behalf of your users so they never need to hold native tokens to transact. Remove the single biggest friction point in onboarding. **Auto-sweep and auto-settle.** Funds deposited to child addresses are automatically swept to your master wallet. Settlement rules convert and route assets without manual intervention. **Built for global teams.** Blockradar was built from emerging marketsto serve the world. Our infrastructure is optimized for the high-volume, corridor-specific needs of fintechs operating in Africa, Asia and LATAM, with local stablecoin support including cNGN and IDRX alongside USDT and USDC. ## Who uses Blockradar Blockradar is used by savings platforms, cross-border payment companies, neobanks, exchanges, and remittance operators. Customers include Risevest, Shiga, Azza, and BloccPay, and infrastructure partners include Circle, Tether, Base, Celo, and Lisk. ## Ready to start? Set up your account and make your first API call. See how Blockradar fits your specific product. # Disaster Recovery Source: https://docs.blockradar.co/en/security/disaster-recovery Learn how Blockradar ensures business continuity and fund security during disasters. Blockradar ensures your funds remain accessible even in the most extreme scenarios through a combination of enterprise-grade infrastructure redundancy and user-controlled backup capabilities. In particular, there are two main categories of data that we consider to be critical: **Organization data**: Core data within your organization, including details for users, encrypted seed phrases, derivation paths, transaction history, API keys, etc. **Seed Phrase Data**: Encrypted seed phrases used to generate private keys and derive addresses for transaction signing and fund access. For organization data, our persistence strategy is similar to a traditional web application. Data is encrypted using AES-256-GCM, stored redundantly across geographies, and consistently backed up and exported to our disaster recovery accounts. For seed phrase data, we encrypt the seed phrases using advanced AES-256-GCM encryption with random IV and salt-based key derivation. The encrypted seed phrases are stored across geographically distributed locations with multiple layers of redundancy. In the unlikely event of a complete system failure, users can use the exported seed phrase backups to recover their funds independently. ## User-Controlled Backup System Blockradar provides you with **complete control** over your disaster recovery through seed phrase backups you can export via the dashboard security page. **Critical Points:** * **Immediate Backup Required**: We strongly advise backing up your seed phrases immediately after creating your account * **Complete Independence**: Your seed phrases provide access to all funds outside Blockradar * **Extreme Caution**: If exposed, there is nothing Blockradar can do to recover your funds * **Secure Storage**: Store backups with maximum security precautions **Critical**: We strongly advise backing up your seed phrases immediately after creating your account. Store them securely offline. If your seed phrases are compromised, there is nothing Blockradar can do to recover your funds. ## Related Documentation Learn about Blockradar's overall security philosophy and approach to protecting your funds. Learn about our revolutionary key management system and how we eliminate private key storage risks. Learn about the shared responsibility model for security between Blockradar and your organization. Learn how to report security vulnerabilities to help improve our platform. # Security & Architecture Source: https://docs.blockradar.co/en/security/introduction Learn how Blockradar achieves innovative, enterprise-grade, no single point of failure security. ```mermaid theme={null} flowchart LR %% Main Transaction Flow A@{ shape: stadium, label: "Transaction Request" } --> B@{ shape: rounded, label: "Validate Request" } --> C@{ shape: rounded, label: "Retrieve Encrypted Seed" } --> D@{ shape: rounded, label: "AES-256-GCM Decrypt" } --> E@{ shape: rounded, label: "Derive Private Key" } --> F@{ shape: rounded, label: "Sign Transaction" } --> G@{ shape: rounded, label: "Secure Memory Wipe" } --> H@{ shape: stadium, label: "Return Signed Transaction" } %% Security Layer subgraph SecurityLayer ["Security Layer"] direction TB I@{ shape: cyl, label: "Encrypted Storage" } J@{ shape: rect, label: "Authentication Tags" } K@{ shape: rect, label: "Random IV & Salt" } end %% Real-Time Computation Layer subgraph RealTime ["Real-Time Computation"] direction TB L@{ shape: rect, label: "BIP44 Derivation" } M@{ shape: rect, label: "Elliptic Curve Math" } N@{ shape: rect, label: "Transaction Signing" } end %% Memory Protection Layer subgraph MemProtect ["Memory Protection"] direction TB O@{ shape: rect, label: "Secure Allocation" } P@{ shape: rect, label: "Cryptographic Clear" } Q@{ shape: rect, label: "Zero Persistence" } end %% Contextual Connections C -. "Seed Source" .-> I D -. "Tag Validation" .-> J D -. "Nonce/Salt" .-> K E -.-> L E -.-> M F -.-> N G -.-> O G -.-> P G -.-> Q %% Styling classDef mainStep fill:#353553,stroke:#6088FF,stroke-width:2px,color:#fff; classDef secLayer fill:#402345,stroke:#D885FF,stroke-width:2px,color:#fff; classDef compLayer fill:#18333B,stroke:#36BEBC,stroke-width:2px,color:#fff; classDef memLayer fill:#2B3A36,stroke:#88ED79,stroke-width:2px,color:#fff; class A,B,C,D,E,F,G,H mainStep; class I,J,K secLayer; class L,M,N compLayer; class O,P,Q memLayer; ``` Blockradar represents a paradigm shift in blockchain key management, implementing a verifiable, non-custodial architecture that ensures private keys are never exposed or stored on our infrastructure, your applications, or our team. Our security model is built on cryptographic guarantees, advanced encryption algorithms, and end-to-end verifiability. Every component of our system is designed to be auditable, reproducible, and mathematically provable in its security properties. Unlike traditional custodial solutions, Blockradar's architecture makes it cryptographically impossible for us to access user funds, even with full system compromise. Through our custom Advanced AES-256-GCM encryption, dual seed phrase system (mainnet/testnet), and real-time key computation, we provide enterprise-grade security while maintaining complete user sovereignty over their cryptographic assets. Learn about the approach Blockradar takes to ensure high security of your funds. Learn how Blockradar manages keys and ensures the security of your funds. Learn how Blockradar ensures the security of your funds in the event of a disaster. Learn how Blockradar shares responsibility for the security of your funds. Learn how to report a vulnerability to Blockradar. # Key Management Source: https://docs.blockradar.co/en/security/key-management Learn how Blockradar achieves innovative, enterprise-grade, no single point of failure security. Blockradar's key management system represents a revolutionary approach to blockchain security, eliminating the traditional risks associated with private key storage while maintaining full functionality and user control. Our architecture ensures that private keys are never stored, never transmitted, and only computed when absolutely necessary for transaction signing. ## Core Security Principles ### **No Private Key Storage** Unlike traditional custodial solutions, Blockradar **never stores private keys** on our infrastructure. This fundamental design choice eliminates the single largest attack vector in blockchain applications - private key compromise through storage breaches. ### **Derivation Path Architecture** Instead of storing private keys, Blockradar stores only **wallet derivation paths** - mathematical instructions that can generate private keys when needed. This approach provides: * **Zero private key exposure** in our systems * **Mathematical impossibility** of key extraction from stored data * **Complete user sovereignty** over cryptographic assets * **Auditable security model** with verifiable properties ## Business-Level Key Management ### **Dual Seed Phrase System** Each business account operates with two encrypted seed phrases: **Production Environment** * Encrypted using advanced AES-256-GCM * Generates all mainnet wallet addresses * Protected by enterprise-grade encryption * Never accessible in plaintext **Development Environment** * Separate encrypted seed phrase * Isolated testnet operations * Same security standards as mainnet * Complete environment separation ### **Advanced Encryption System** Blockradar employs a sophisticated multi-layer encryption system for seed phrase protection: **Encryption Process:** 1. **Seed Generation**: Cryptographically secure seed phrases generated 2. **Advanced Encryption**: Seeds encrypted using AES-256-GCM with custom key derivation 3. **Encrypted Storage**: Only encrypted seeds stored in our infrastructure 4. **Access Control**: Strict authentication and authorization controls **Security Benefits:** * **AES-256-GCM Encryption**: Industry-standard authenticated encryption * **Custom Key Derivation**: PBKDF2-based key derivation with high iteration counts * **Random IV Generation**: Unique initialization vectors for each encryption * **Authentication Tags**: Built-in integrity verification for encrypted data ## Real-Time Key Computation ### **On-Demand Private Key Generation** Private keys are computed **only when transactions need to be signed**: ```mermaid theme={null} flowchart LR %% Main Transaction Flow A@{ shape: stadium, label: "Transaction Request" } --> B@{ shape: rounded, label: "Validate Request" } --> C@{ shape: rounded, label: "Retrieve Encrypted Seed" } --> D@{ shape: rounded, label: "AES-256-GCM Decrypt" } --> E@{ shape: rounded, label: "Derive Private Key" } --> F@{ shape: rounded, label: "Sign Transaction" } --> G@{ shape: rounded, label: "Secure Memory Wipe" } --> H@{ shape: stadium, label: "Return Signed Transaction" } %% Security Layer subgraph SecurityLayer ["Security Layer"] direction TB I@{ shape: cyl, label: "Encrypted Storage" } J@{ shape: rect, label: "Authentication Tags" } K@{ shape: rect, label: "Random IV & Salt" } end %% Real-Time Computation Layer subgraph RealTime ["Real-Time Computation"] direction TB L@{ shape: rect, label: "BIP44 Derivation" } M@{ shape: rect, label: "Elliptic Curve Math" } N@{ shape: rect, label: "Transaction Signing" } end %% Memory Protection Layer subgraph MemProtect ["Memory Protection"] direction TB O@{ shape: rect, label: "Secure Allocation" } P@{ shape: rect, label: "Cryptographic Clear" } Q@{ shape: rect, label: "Zero Persistence" } end %% Contextual Connections C -. "Seed Source" .-> I D -. "Tag Validation" .-> J D -. "Nonce/Salt" .-> K E -.-> L E -.-> M F -.-> N G -.-> O G -.-> P G -.-> Q %% Styling classDef mainStep fill:#353553,stroke:#6088FF,stroke-width:2px,color:#fff; classDef secLayer fill:#402345,stroke:#D885FF,stroke-width:2px,color:#fff; classDef compLayer fill:#18333B,stroke:#36BEBC,stroke-width:2px,color:#fff; classDef memLayer fill:#2B3A36,stroke:#88ED79,stroke-width:2px,color:#fff; class A,B,C,D,E,F,G,H mainStep; class I,J,K secLayer; class L,M,N compLayer; class O,P,Q memLayer; ``` ### **Transaction Signing Flow** ```rust theme={null} // Simplified transaction signing process async fn sign_transaction(derivation_path: &str, transaction: &Transaction) -> Result { // 1. Retrieve encrypted seed phrase let encrypted_seed = get_encrypted_seed(derivation_path).await?; // 2. Decrypt using advanced AES-256-GCM let seed_phrase = advanced_decrypt(&encrypted_seed).await?; // 3. Compute private key let private_key = derive_private_key(&seed_phrase, derivation_path)?; // 4. Sign transaction let signed_tx = sign_with_private_key(&private_key, transaction)?; // 5. Securely clear private key from memory secure_clear(&private_key); Ok(signed_tx) } ``` ## Security Architecture Benefits ### **Eliminated Attack Vectors** Our architecture eliminates common attack vectors: **Traditional Risk**: Private keys stored in database **Our Solution**: Only encrypted derivation paths stored **Result**: Database breach reveals no usable private keys **Traditional Risk**: Private keys in memory dumps **Our Solution**: Keys computed and destroyed immediately **Result**: Memory dumps contain no private key data **Traditional Risk**: Employees with key access **Our Solution**: Keys only computed during transactions **Result**: No persistent access to private keys **Traditional Risk**: Private keys transmitted over network **Our Solution**: Keys never leave secure environment **Result**: Network interception reveals no private keys ### **Compliance & Auditing** * **SOC 2 Type II**: Comprehensive security controls audit * **ISO 27001**: Information security management certification * **PCI DSS**: Payment card industry security standards * **GDPR Compliance**: Data protection and privacy regulations Blockradar's key management system provides enterprise-grade security while maintaining the flexibility and ease of use that modern applications require. Our architecture ensures that your private keys are never at risk, even in the event of a complete system compromise. ## Related Documentation Learn about Blockradar's overall security philosophy and approach to protecting your funds. Understand how Blockradar ensures business continuity and fund security during disasters. Learn about the shared responsibility model for security between Blockradar and your organization. Learn how to report security vulnerabilities to help improve our platform. # Our Approach Source: https://docs.blockradar.co/en/security/our-approach Learn how Blockradar achieves innovative, enterprise-grade, no single point of failure security. At Blockradar, we've developed a security framework that allows us and eventually our users to prove that private keys are never stored, that no single engineer can access or reconstruct private keys, and that the system remains safe even if all systems are compromised. At the highest level, Blockradar runs all critical workloads using real-time key computation and our custom Advanced AES-256-GCM encryption. We store only encrypted seed phrases (dual mainnet/testnet system) and derivation paths, never private keys. Every time a transaction needs to be signed, we compute the private key in real-time, use it once, and immediately destroy it. This helps to ensure that we can trust the secure applications running our infrastructure, which perform actions such as private key generation, transaction signing, and fund management. Our architecture gives us end-to-end transparency into the code we're running and ensures no single developer at Blockradar can access private keys or reconstruct core secrets. We augment that trust in the application layer by ensuring the applications only act on verifiable data; every single change to a customer's organization data must be approved and cryptographically stamped before it is considered by our systems. The system architecture ensures that even if all systems are compromised, your assets remains safe because private keys are never stored. Over time, we plan to open source more of this stack to enable other developers to verify our security claims themselves, and to allow clients to integrate with our security framework via their own applications. This, and more, is covered in depth in our documentation. Our security architecture is the foundation of the Blockradar product. Read on for deeper dives on each of the topics referenced above. ## Related Documentation Learn about our revolutionary key management system and how we eliminate private key storage risks. Understand how we ensure business continuity and fund security during disasters. Learn about the shared responsibility model for security between Blockradar and your organization. Learn how to report security vulnerabilities to help improve our platform. # Reporting a Vulnerability Source: https://docs.blockradar.co/en/security/report-vulnerability Learn how Blockradar achieves innovative, enterprise-grade, no single point of failure security. Blockradar highly values the security of our software, services, and systems and we actively encourage the ethical reporting of any security vulnerabilities discovered. We invite researchers and users to report potential security vulnerabilities to our security team at [support@blockradar.co](mailto:support@blockradar.co). When submitting a report, please provide a thorough description of the vulnerability, including steps to reproduce it and its potential impact. ## Our Response Process Upon receiving a report, our team promptly assesses and prioritizes the vulnerability based on its severity and potential impact. We then take reasonable and appropriate steps to mitigate and remediate the identified risks in accordance with our internal policies and timelines. Where feasible, we will endeavor to keep the reporter informed throughout the process. Our approach is designed to ensure confidentiality and offer safe harbor to researchers, promising that those who report vulnerabilities ethically and in good faith will not face legal action. ## Confidentiality and Disclosure We expect reporters to treat vulnerability reports submitted to Blockradar, along with all associated information and/or data, with a high degree of care, use it solely for the purpose of reporting to Blockradar, and to not disclose it to any third parties without our written consent. With the reporter's consent, we may publicly disclose details of the vulnerability and acknowledge their contribution after it has been resolved. ## Contact Information For further inquiries or more information about our security program, please contact our security team at [support@blockradar.co](mailto:support@blockradar.co). We take security seriously and appreciate the security research community's efforts to help us maintain the highest security standards. All vulnerability reports are handled with the utmost confidentiality and professionalism. ## Related Documentation Learn about Blockradar's overall security philosophy and approach to protecting your funds. Learn about our revolutionary key management system and how we eliminate private key storage risks. Understand how we ensure business continuity and fund security during disasters. Learn about the shared responsibility model for security between Blockradar and your organization. # Shared Responsibility Model Source: https://docs.blockradar.co/en/security/shared-responsibility Learn how Blockradar achieves innovative, enterprise-grade, no single point of failure security. When integrating your product with Blockradar, it's critical to understand which security tasks are Blockradar's responsibility and which tasks are your responsibility. Blockradar provides secure, scalable, and programmable blockchain infrastructure. Our flexibility means you have the freedom to integrate Blockradar in ways that may or may not fully meet your product's security requirements. As detailed below, you are responsible for securing both your Blockradar organization and your integration with Blockradar. ## Blockradar's Responsibility: Security of the Platform Blockradar is responsible for securing the infrastructure that runs the services offered by Blockradar. This includes the security of all Blockradar-authored code, from our encryption systems to our APIs, and everything in between. Blockradar commits to securing the **Confidentiality, Integrity, and Availability** of the Blockradar platform. Blockradar's responsibilities therefore include: * **Maintaining the confidentiality** of secret materials stored with Blockradar, in particular but not limited to encrypted seed phrases and derivation paths; * **Ensuring the integrity** of all end user requests that are made to Blockradar's system and all data associated with those requests; and * **Providing constant availability** of Blockradar's services. Blockradar also offers multiple options for various components of our product in order to accommodate customers with varying security and user experience profiles. This allows each Blockradar customer to choose a security approach tailored to their specific needs. ## Customer's Responsibility: Security Using the Platform Customers are responsible for the decisions they make when using Blockradar. Each customer's unique product and threat model play a critical role in determining the appropriate configurations and integration patterns, including choices that could impact security. Customers are responsible for securely integrating their product with Blockradar. Blockradar provides extensive documentation and examples for building multiple products, including guidance on authentication flows, appropriate feature selection, credential management, and more. Each customer's implementation choices differ significantly based on the unique integration of Blockradar, and therefore the ultimate responsibility remains with the customer to select the right approach. In addition, customers are responsible for securing their Blockradar organizations. This requires the proper configuration for API access, appropriate backups for seed phrases, and properly securing authenticator credentials, such as API keys. ## Illustrations of the Shared Responsibility Model ### **Authentication and Authorization** Blockradar is responsible for ensuring authentication correctness and that any action taken within an authenticated context is unable to exceed previously granted permissions. Customers are responsible for ensuring that authorization permissions are appropriately configured for each user and that user authentication credentials are securely managed. ### **Key Management and Transactions** Blockradar is responsible for securing the infrastructure that enables private key computation and transaction signing, including the protection of encrypted seed phrases and derivation paths. Customers are responsible for securely backing up their seed phrases and ensuring that transaction parameters are properly validated before submission to Blockradar. ### **Disaster Recovery and Business Continuity** Blockradar is responsible for maintaining infrastructure redundancy and providing access to seed phrase backups through the dashboard. Customers are responsible for creating and securely storing their seed phrase backups, and implementing their own disaster recovery procedures using these backups. The shared responsibility model ensures that both Blockradar and our customers work together to maintain the highest security standards. While Blockradar secures the platform, customers must implement secure integrations and properly manage their seed phrase backups. ## Related Documentation Learn about Blockradar's overall security philosophy and approach to protecting your funds. Learn about our revolutionary key management system and how we eliminate private key storage risks. Understand how we ensure business continuity and fund security during disasters. Learn how to report security vulnerabilities to help improve our platform. # Accept Agent Payments Source: https://docs.blockradar.co/en/use-cases/accept-agent-payments Get paid by AI agents in stablecoins, with payments arriving in your Blockradar wallet as ordinary deposits In a nutshell
AI agents can pay for APIs and data per request, in stablecoins, through open agent payment protocols. If you sell to agents, a Blockradar address can receive those payments. They arrive as ordinary deposits, with the usual webhook and the paying agent's wallet as the sender, so there is nothing new to integrate on the Blockradar side.
## Supported Protocols | Protocol | Networks and tokens | | - | - | | [x402](https://www.x402.org) | EVM chains, USDC (EIP-3009) | | [x402](https://www.x402.org) on Solana | Solana, USDC | | [MPP](https://mpp.dev) | EVM charge on EVM chains, USDC (EIP-3009 `authorization` credential) | | [MPP](https://mpp.dev) on [Tempo](https://tempo.xyz), charge | Tempo mainnet: OUSD, USDC.e, USDT | | [MPP](https://mpp.dev) on [Tempo](https://tempo.xyz), sessions | Coming soon | Building the agent that pays? See [Make Agent Payments](/en/use-cases/make-agent-payments). ## Prerequisites Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. Create a master wallet in the dashboard on the chain you charge on, such as Base (see [Create a Master Wallet](/en/guides/create-master-wallet)). Enable USDC on the wallet. Your wallet only detects deposits for assets you have added. See [Asset Management](/en/use-cases/asset-management). Configure a webhook endpoint in your dashboard under **Developers → Webhooks** to be notified of each payment. *** ## How x402 Works [x402](https://www.x402.org) is an open protocol that lets an API charge per request. Your API answers an unpaid request with HTTP `402 Payment Required` and the price, the agent retries with a signed USDC authorization, and a **facilitator** verifies that authorization and submits the transfer on-chain, paying the gas. The USDC moves straight from the agent's wallet to your `payTo` address. You run the x402 server middleware and choose the facilitator. Blockradar is where the money lands. ## Get Paid with x402 Use the master wallet's address, or [generate a child address](/en/api-reference/addresses/generate-address) per product or customer and attach `metadata` so each payment maps back to what was bought. On the [Checkout plan](/en/use-cases/checkout#checkout-plan), child addresses are not available, so use the master wallet's address. Point your x402 middleware at a facilitator that supports your network. [Circle's Facilitator Service](https://developers.circle.com/facilitator-service) settles USDC on Arc, Base, and Polygon PoS. Use a Circle API key when configuring it. For Solana, use a facilitator that supports Solana. When the facilitator settles, the USDC transfer to your `payTo` address is detected like any other deposit and fires the usual [`deposit.success` webhook](/en/use-cases/deposit-stablecoins#webhook-payload). In the webhook, `senderAddress` is the **buyer's wallet**, not the facilitator that submitted the transaction, so you can see who paid. `hash` matches the `transaction` in the `PAYMENT-RESPONSE` your server returned. x402 payments are often a cent or less. If `payTo` is a child address with auto-sweep on, each payment is swept to the master wallet separately. Set a [sweep threshold](/en/use-cases/asset-management) on USDC, or use the master wallet's address as `payTo`, so you are not paying to sweep amounts smaller than the sweep fee. ### Receiving x402 on Solana On Solana, the agent signs a USDC transfer and the facilitator pays the network fee. The payment arrives the same way: a `deposit.success` webhook with the agent's wallet as `senderAddress`, not the facilitator that paid the fee. The `payTo` address needs a USDC token account before its first x402 payment, and an x402 payment cannot create one. A Blockradar address gets its token account the first time it receives USDC, so send it any amount of USDC first. Enabling USDC on the wallet does not create the account on its own. *** ## How MPP Works [MPP](https://mpp.dev) (Machine Payments Protocol) is another open protocol for paying per request over HTTP. Its EVM charge settles the same way as x402: the agent signs an EIP-3009 USDC authorization to your `recipient` address, your server submits it on-chain, and the USDC moves straight from the agent's wallet to that address. The headers differ (`WWW-Authenticate: Payment`, `Authorization: Payment` and `Payment-Receipt`), but the deposit Blockradar records is the same. ## Get Paid with MPP MPP calls the receiving address `recipient`. Use a Blockradar address exactly as you would for x402 `payTo`, including the same Checkout plan rule. The official [`mppx`](https://www.npmjs.com/package/mppx) server settles EVM charges through an x402 facilitator, so the facilitator you use for x402 works here too. The settled transfer fires the usual [`deposit.success` webhook](/en/use-cases/deposit-stablecoins#webhook-payload), with the agent's wallet as `senderAddress`. ```javascript JavaScript theme={null} import { Mppx, evm } from 'mppx/server'; const mppx = Mppx.create({ methods: [ evm.charge({ currency: evm.assets.base.USDC, // Base mainnet; evm.assets.baseSepolia.USDC for testing recipient: process.env.BLOCKRADAR_ADDRESS, // your Blockradar master wallet or child address x402: { facilitator: process.env.FACILITATOR_URL }, }), ], secretKey: process.env.MPP_SECRET_KEY, // at least 32 bytes: openssl rand -base64 32 }); export async function handler(request) { const response = await mppx.evm.charge({ amount: '0.01', description: 'Premium data' })(request); if (response.status === 402) return response.challenge; return response.withReceipt(Response.json({ data: 'premium data' })); } ``` The `reference` in the `Payment-Receipt` your server returns is the on-chain transaction hash, and it matches the deposit's `hash`. The sweep tip above applies to MPP payments too. *** ## Get Paid with MPP on Tempo An MPP charge on Tempo is a direct stablecoin transfer to your `recipient` address, carrying a memo that ties it to the challenge. The agent or your server broadcasts it, so no facilitator is involved. Your wallet only detects deposits for assets you have added. See [Asset Management](/en/use-cases/asset-management). Use your Tempo master wallet's address or a child address (the master wallet's address on the [Checkout plan](/en/use-cases/checkout#checkout-plan)), and set `currency` to the token you want to receive: OUSD, USDC.e or USDT. Their addresses are in the example below. USDT shows as USDT0 on-chain. The transfer fires the usual [`deposit.success` webhook](/en/use-cases/deposit-stablecoins#webhook-payload), with the agent's wallet as `senderAddress`. ```javascript JavaScript theme={null} import { Mppx, tempo } from 'mppx/server'; // Tempo mainnet tokens supported by Blockradar const TEMPO_TOKENS = { OUSD: '0x20c0000000000000000000006a37DA5C996874BE', 'USDC.e': '0x20C000000000000000000000b9537d11c60E8b50', USDT: '0x20C00000000000000000000014f22CA97301EB73', // on-chain symbol: USDT0 }; const mppx = Mppx.create({ methods: [tempo.charge()], secretKey: process.env.MPP_SECRET_KEY, // at least 32 bytes: openssl rand -base64 32 }); export async function handler(request) { const response = await mppx.charge({ amount: '0.01', currency: TEMPO_TOKENS.OUSD, // or TEMPO_TOKENS['USDC.e'], TEMPO_TOKENS.USDT recipient: process.env.BLOCKRADAR_TEMPO_ADDRESS, // your Blockradar Tempo address description: 'Premium data', })(request); if (response.status === 402) return response.challenge; return response.withReceipt(Response.json({ data: 'premium data' })); } ``` To pay the agent's transaction fee for it, pass a `feePayer` to `tempo.charge()`. Use a key held on your own server, not your Blockradar address: the fee payer co-signs each charge transaction, and Blockradar cannot co-sign Tempo fee-payer transactions. *** ## Limitations * **EVM networks and Solana only.** Payments on other networks are not supported. * **MPP sessions on Tempo are coming soon.** Until then, session settlements are not supported. * **Circle Gateway nanopayments land in a Gateway balance.** Circle settles these batched sub-cent payments into the seller's Gateway balance, not as an on-chain transfer to `payTo`, so they do not arrive as Blockradar deposits and are out of scope for this guide. *** ## Best Practices * **One address per product or customer.** Generate a child address per paid resource or per buyer account and tag it with `metadata`, so every deposit webhook tells you what was bought without a lookup. * **Reconcile by hash.** Match each `deposit.success` webhook's `hash` to the `transaction` in `PAYMENT-RESPONSE` (x402) or the `reference` in `Payment-Receipt` (MPP). * **Test on testnet first.** Point your middleware at a testnet network, such as Base Sepolia (`eip155:84532`), and pay yourself with testnet USDC from the [faucets](/en/use-cases/supported-assets) before going live. *** ## API Reference | Endpoint | Description | | - | - | | [Generate Address](/en/api-reference/addresses/generate-address) | Create a dedicated `payTo` or `recipient` address | | [Update Address](/en/api-reference/addresses/update-address) | Turn auto-sweep on or off for an address | # AML Screening Source: https://docs.blockradar.co/en/use-cases/aml-screening Screen wallet addresses against global sanctions and blocklists in real time In a nutshell
The AML API lets you screen any wallet address against OFAC, FBI, Tether, and Circle blocklists before sending or receiving funds. Use it to flag high-risk counterparties and meet your compliance obligations without building your own screening infrastructure.
## Prerequisites Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. ## How It Works Before sending funds to an external address or before crediting a deposit from one, you can run a real-time AML check. Blockradar screens the address against multiple blocklists and returns a risk assessment you can use to decide whether to proceed. Screen against the US Office of Foreign Assets Control sanctions list, covering individuals and entities subject to economic sanctions. Check addresses flagged by the FBI in connection with cybercrime, ransomware, and other illicit activity. Identify addresses that Tether has blacklisted and frozen from transacting in USDT. Identify addresses that Circle has blacklisted and frozen from transacting in USDC. ## Screening an Address ```bash theme={null} GET /v1/aml/lookup?address={address} ``` ```javascript theme={null} const result = await fetch( `https://api.blockradar.co/v1/aml/lookup?address=0xabc123...`, { headers: { 'x-api-key': apiKey } } ).then(r => r.json()); if (result.isBlacklisted) { console.log('High risk address — do not proceed'); } else { console.log('Address is clear'); } ``` ## Response ```json theme={null} { "isBlacklisted": false, "provider": "ofac, fbi, tether, circle", "status": "success", "message": "Address is not sanctioned" } ``` If the address is flagged, `isBlacklisted` will be `true` and the `message` will indicate the sanction source. ## When to Screen Screen the destination address before executing a withdrawal to avoid sending to a sanctioned or blacklisted wallet. Screen the sender address when a deposit arrives before crediting the funds in your system. ## Best Practices * **Screen before every outbound transfer** — run a check before executing any withdrawal to an external address you haven't previously vetted. * **Screen inbound deposits** — use the sender address from your webhook payload to screen deposits before crediting them to your user's account. * **Log screening results** — store the AML check result alongside each transaction for audit and compliance purposes. * **Have a clear escalation policy** — decide in advance what happens when an address is flagged: block the transaction, hold for review, or alert your compliance team. ## API Reference | Endpoint | Description | | - | - | | [AML Lookup](/en/api-reference/aml/lookup) | Screen a wallet address against global blocklists | # Asset Management Source: https://docs.blockradar.co/en/use-cases/asset-management Control which tokens are active on your master wallet In a nutshell
Asset Management lets you configure which stablecoins are enabled on your master wallet. Add a new token to start accepting it, remove one to stop, or update its settings. Your wallet only monitors and indexes assets that are explicitly enabled.
## Prerequisites Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. You'll need a `walletId` to manage assets. Create one in the dashboard (see [Create a Master Wallet](/en/guides/create-master-wallet)). Get the `assetId` for the token you want to add from **Assets** in the dashboard or via the [Get Assets API](/en/api-reference/miscellaneous/get-assets). ## How It Works When you create a master wallet, it doesn't automatically track every supported stablecoin, only the ones you've explicitly enabled. This gives you precise control over what your wallet accepts and indexes. Adding an asset to your wallet tells Blockradar to start monitoring incoming transactions for that token, include it in balance queries, and fire webhooks when deposits arrive. Removing an asset stops all of that. Enable a new stablecoin on your wallet to start accepting deposits and executing withdrawals in that token. Disable a token to stop monitoring it. Existing balances are unaffected — you can re-enable it at any time. Adjust asset-level configuration such as auto-sweep thresholds and gasless transaction settings. Fetch all assets currently enabled on your wallet along with their IDs, symbols, and configuration. ## Adding an Asset to Your Wallet ```bash theme={null} POST /v1/wallets/{walletId}/assets ``` ```javascript theme={null} const asset = await fetch( `https://api.blockradar.co/v1/wallets/${walletId}/assets`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ assetId: 'asset_usdc_base_mainnet' }) } ).then(r => r.json()); console.log('Asset added:', asset.data); ``` Once added, Blockradar will immediately begin monitoring this token on your wallet. ## Viewing Active Assets Fetch the list of all assets currently enabled on your wallet, useful for retrieving wallet-specific asset IDs for use in swaps, withdrawals, and other operations. ```bash theme={null} GET /v1/wallets/{walletId}/assets ``` Always use the asset IDs returned from this endpoint when calling other APIs. These are wallet-specific asset IDs, not global ones, and they are required for swaps, withdrawals, and balance queries. ## Removing an Asset Disabling an asset stops Blockradar from monitoring new deposits for that token. It does not affect existing balances or transaction history. ```bash theme={null} DELETE /v1/wallets/{walletId}/assets/{assetId} ``` Removing an asset means incoming deposits of that token will no longer be detected or indexed. Make sure you've migrated any existing balance before removing an asset you plan to stop using. ## Updating Asset Settings You can update asset-level settings such as sweep thresholds and gasless configuration. ```bash theme={null} PATCH /v1/wallets/{walletId}/assets/{assetId} ``` ## Best Practices * **Only enable what you need** — a focused asset list keeps your wallet clean, reduces noise in webhooks, and makes balance queries faster. * **Always fetch asset IDs from your wallet** — use `GET /v1/wallets/{walletId}/assets` to get the correct wallet-specific asset IDs before executing swaps or withdrawals. * **Test on testnet first** — enable and configure assets on testnet before replicating the setup on mainnet. ## API Reference | Endpoint | Description | | - | - | | [Get Wallet Assets](/en/api-reference/asset/get-wallet-assets) | List all active assets on a wallet | | [Add Asset to Wallet](/en/api-reference/asset/add-asset-to-wallet) | Enable a new token on your wallet | | [Remove Asset from Wallet](/en/api-reference/asset/remove-asset-from-wallet) | Disable a token | | [Update Wallet Asset](/en/api-reference/asset/update-wallet-asset) | Update asset-level configuration | # Asset Recovery Source: https://docs.blockradar.co/en/use-cases/asset-recovery Recover assets sent to the correct address on the wrong blockchain In a nutshell
The Blockradar Asset Recovery API allows you to retrieve assets that were accidentally sent to the correct address on the wrong blockchain. It supports native currency and custom assets (ERC-20 and compatible standards) across all supported networks.
Blockradar Asset Recovery ## What is Asset Recovery? Asset recovery enables you to retrieve funds that were sent to the correct wallet address but on the wrong blockchain network. This commonly happens when: * Users send assets on Ethereum but meant to send on Polygon * Assets are sent on BNB Smart Chain instead of Arbitrum * Any cross-chain address confusion where the same address exists on multiple EVM-compatible networks Since EVM-compatible blockchains share the same address format, the same address can receive assets on multiple networks. Asset recovery allows you to access these funds programmatically. For a detailed guide on asset recovery concepts and dashboard usage, read our blog post: [How to Recover Assets Sent to the Wrong Blockchain](https://www.blockradar.co/blog/how-to-recover-tokens-sent-to-the-wrong-blockchain) ## Prerequisites Before using the Asset Recovery API, ensure you have: Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. Create a wallet in the dashboard (see [Create a Master Wallet](/en/guides/create-master-wallet)). You'll need the `walletId` for recovery operations. Get the `blockchainId` for the network where assets are stuck. You can find this in the dashboard or via the [Get Blockchains API](/en/api-reference/miscellaneous/get-blockchains). Ensure the sender address has enough native currency (ETH, BNB, MATIC, etc.) on the recovery blockchain to cover gas fees. ## How It Works The Asset Recovery API transfers assets from a sender address (where assets are stuck) to a recipient address on the same blockchain: Recover native currency like ETH, BNB, MATIC, or AVAX sent to the wrong network. Recover ERC-20 and compatible assets by specifying the contract address. Calculate network fees before execution to ensure sufficient balance. Recover assets on unsupported blockchains by providing your own RPC endpoint. ## Supported Blockchains Asset recovery is available on **all blockchains** supported by Blockradar, including EVM-compatible networks, Tron, and Solana. See [Integrations](/en/use-cases/integrations) for the complete list of supported networks and faucet links. For EVM networks not directly supported, you can provide a custom RPC URL and optionally enable Layer 2 mode for rollup-based networks. Start with testnets during development to avoid spending real funds. *** ## Recover Assets Initiate an asset recovery operation to transfer stuck assets to a recipient address. ### Request Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `senderAddress` | string | Yes | The Blockradar address where assets are currently stuck. | | `recipientAddress` | string | Yes | The destination address where recovered assets will be sent. | | `amount` | string | Yes | The amount to recover. Use the full amount or a portion. | | `blockchainId` | string (UUID) | Yes | The blockchain UUID where recovery will occur. Get this from the [Get Blockchains API](/en/api-reference/miscellaneous/get-blockchains). | | `tokenAddress` | string | No | Contract address for custom asset recovery. Omit for native currency. | | `crossNetwork` | boolean | No | Set to `true` to recover assets sent to the wrong network environment (e.g., mainnet assets on a testnet-derived address). Defaults to `false`. | | `rpcUrl` | string | No | Custom RPC endpoint for unsupported blockchains. Cannot be used with `crossNetwork`. | | `isL2` | boolean | No | Set to `true` if the RPC URL points to a Layer 2 network. | ### Native Currency Recovery Recover native currency (ETH, BNB, MATIC, etc.) from the wrong network: ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/salvage \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "senderAddress": "0x1234567890abcdef1234567890abcdef12345678", "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12", "amount": "0.5", "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa" }' ``` ```javascript JavaScript theme={null} const response = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, body: JSON.stringify({ senderAddress: '0x1234567890abcdef1234567890abcdef12345678', recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12', amount: '0.5', blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa' }) } ); const data = await response.json(); console.log(data); ``` ```python Python theme={null} import requests response = requests.post( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', headers={ 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, json={ 'senderAddress': '0x1234567890abcdef1234567890abcdef12345678', 'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12', 'amount': '0.5', 'blockchainId': 'polygon-mainnet' } ) print(response.json()) ``` ### Custom Asset Recovery Recover ERC-20 or compatible assets by specifying the contract address: ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/salvage \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "senderAddress": "0x1234567890abcdef1234567890abcdef12345678", "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12", "amount": "100", "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa", "tokenAddress": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359" }' ``` ```javascript JavaScript theme={null} const response = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, body: JSON.stringify({ senderAddress: '0x1234567890abcdef1234567890abcdef12345678', recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12', amount: '100', blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa', tokenAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359' }) } ); const data = await response.json(); console.log(data); ``` ```python Python theme={null} import requests response = requests.post( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', headers={ 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, json={ 'senderAddress': '0x1234567890abcdef1234567890abcdef12345678', 'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12', 'amount': '100', 'blockchainId': 'polygon-mainnet', 'tokenAddress': '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359' } ) print(response.json()) ``` ### Custom RPC Recovery Recover assets on unsupported blockchains by providing your own RPC endpoint: ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/salvage \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "senderAddress": "0x1234567890abcdef1234567890abcdef12345678", "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12", "amount": "0.5", "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa", "rpcUrl": "https://rpc.custom-network.io", "isL2": true }' ``` ```javascript JavaScript theme={null} const response = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, body: JSON.stringify({ senderAddress: '0x1234567890abcdef1234567890abcdef12345678', recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12', amount: '0.5', blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa', rpcUrl: 'https://rpc.custom-network.io', isL2: true }) } ); const data = await response.json(); console.log(data); ``` ```python Python theme={null} import requests response = requests.post( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', headers={ 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, json={ 'senderAddress': '0x1234567890abcdef1234567890abcdef12345678', 'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12', 'amount': '0.5', 'blockchainId': 'custom', 'rpcUrl': 'https://rpc.custom-network.io', 'isL2': True } ) print(response.json()) ``` ### Cross-Network Recovery Recover assets that were accidentally sent to a testnet-derived address on mainnet, or vice versa. This works because EVM, Tron, and Solana addresses are derived from the same keys regardless of network environment. Cross-network recovery requires `blockchainId` and cannot be used with `rpcUrl`. The blockchain must match the wallet's blockchain — you cannot cross-chain and cross-network at the same time. ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/salvage \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "senderAddress": "0x1234567890abcdef1234567890abcdef12345678", "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12", "amount": "100", "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa", "tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7", "crossNetwork": true }' ``` ```javascript JavaScript theme={null} const response = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, body: JSON.stringify({ senderAddress: '0x1234567890abcdef1234567890abcdef12345678', recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12', amount: '100', blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa', tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', crossNetwork: true }) } ); const data = await response.json(); console.log(data); ``` ```python Python theme={null} import requests response = requests.post( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage', headers={ 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, json={ 'senderAddress': '0x1234567890abcdef1234567890abcdef12345678', 'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12', 'amount': '100', 'blockchainId': 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa', 'tokenAddress': '0xdAC17F958D2ee523a2206206994597C13D831ec7', 'crossNetwork': True } ) print(response.json()) ``` When `crossNetwork` is enabled, the transaction metadata will include `crossNetwork: true` and `keyDerivationNetwork` fields for audit purposes. ### Success Response ```json theme={null} { "message": "Salvage asset initiated successfully", "statusCode": 200 } ``` *** ## Network Fee Estimation Before executing a recovery, estimate the network fees to ensure sufficient balance. ### Fee Estimation Request ```bash Curl theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/salvage/network-fee \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "senderAddress": "0x1234567890abcdef1234567890abcdef12345678", "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12", "amount": "0.5", "blockchainId": "b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa" }' ``` ```javascript JavaScript theme={null} const response = await fetch( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage/network-fee', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, body: JSON.stringify({ senderAddress: '0x1234567890abcdef1234567890abcdef12345678', recipientAddress: '0xabcdef1234567890abcdef1234567890abcdef12', amount: '0.5', blockchainId: 'b80d3d5e-16f1-4d99-be5e-6dfcd27f89aa' }) } ); const data = await response.json(); console.log(data); ``` ```python Python theme={null} import requests response = requests.post( 'https://api.blockradar.co/v1/wallets/{walletId}/salvage/network-fee', headers={ 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, json={ 'senderAddress': '0x1234567890abcdef1234567890abcdef12345678', 'recipientAddress': '0xabcdef1234567890abcdef1234567890abcdef12', 'amount': '0.5', 'blockchainId': 'polygon-mainnet' } ) print(response.json()) ``` ### Fee Response Parameters | Parameter | Description | | - | - | | `networkFee` | Estimated gas fee in native currency units | | `networkFeeInUSD` | Gas fee converted to USD | | `nativeBalance` | Current native currency balance of sender | | `nativeBalanceInUSD` | Native balance converted to USD | Always estimate fees before executing recovery operations. The sender address must have sufficient native currency to cover gas fees on the recovery blockchain. *** ## Webhooks Subscribe to webhook events to receive real-time notifications about recovery operations. ### Recovery Events | Event | Description | | - | - | | `salvage.success` | Triggered when a recovery operation completes successfully. | | `salvage.failed` | Triggered when a recovery operation fails due to insufficient funds, network issues, or other errors. | | `salvage.cancelled` | Triggered when a recovery operation is cancelled before completion. | ### Webhook Payload ```json theme={null} { "event": "salvage.success", "data": { "id": "txn_abc123", "type": "SALVAGE", "status": "SUCCESS", "amount": "0.5", "senderAddress": "0x1234567890abcdef1234567890abcdef12345678", "recipientAddress": "0xabcdef1234567890abcdef1234567890abcdef12", "blockchain": "polygon-mainnet", "txHash": "0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba", "networkFee": "0.001", "createdAt": "2025-01-12T10:30:00Z" } } ``` Configure webhooks in the [Blockradar Dashboard](https://dashboard.blockradar.co) under **Settings → Webhooks**. See the [Webhooks documentation](/en/utilities/webhooks) for setup instructions. *** ## Common Use Cases A user meant to send USDC on Ethereum but accidentally sent it on Polygon. Since the address is the same, the funds arrived on Polygon. Use asset recovery with the USDC contract address on Polygon to retrieve the funds. A user bridged ETH to Arbitrum but sent it to a Blockradar address. The same address exists on Arbitrum due to EVM compatibility. Recover the ETH from Arbitrum using native currency recovery. A user sent a custom ERC-20 asset on an L2 network like Optimism. Provide the asset contract address and use the recovery API to retrieve it. Assets are stuck on a blockchain not directly supported by Blockradar. Provide your own RPC endpoint and set `isL2: true` if it's a rollup to recover the funds. A user sent mainnet USDT to an address that was created on testnet. Since the same private key derives the same address on both networks, use cross-network recovery with `crossNetwork: true` to recover the mainnet funds using the testnet wallet's keys. *** ## Error Handling ```json theme={null} { "error": "Insufficient native balance for gas", "code": "INSUFFICIENT_GAS", "details": { "required": "0.01", "available": "0.001", "currency": "MATIC" } } ``` **Solution:** Fund the sender address with enough native currency to cover gas fees before retrying. ```json theme={null} { "error": "Sender address not found in wallet", "code": "INVALID_SENDER" } ``` **Solution:** Ensure the sender address belongs to your Blockradar wallet and is a valid child address. ```json theme={null} { "error": "No balance found for specified asset", "code": "ASSET_NOT_FOUND", "details": { "tokenAddress": "0x...", "blockchain": "polygon-mainnet" } } ``` **Solution:** Verify the contract address and blockchain. Use a block explorer to confirm the asset exists at the sender address. ```json theme={null} { "error": "Failed to connect to custom RPC", "code": "RPC_ERROR" } ``` **Solution:** Verify your RPC URL is correct and accessible. Ensure it supports the required JSON-RPC methods. *** ## Best Practices Use the network fee endpoint before recovery to ensure sufficient gas balance and display accurate costs. Double-check sender and recipient addresses using a block explorer before initiating recovery. Configure webhooks to receive real-time status updates instead of polling the API. Test your recovery integration on testnet before using it in production. *** ## API Reference | Endpoint | Description | | - | - | | [Salvage](/en/api-reference/asset-recovery/salvage) | Initiate asset recovery operation | | [Salvage Network Fee](/en/api-reference/asset-recovery/salvage-network-fee) | Estimate network fees for recovery |
Happy recovering! # Auto Settlements Source: https://docs.blockradar.co/en/use-cases/auto-settlements Automate asset settlements and conversions across blockchain networks In a nutshell
Auto Settlements automatically convert incoming deposits to your preferred asset on any blockchain. Define rules once, and all matching deposits are swapped and routed to your destination chain—no manual intervention required.
Auto Settlements ## Prerequisites Before setting up auto-settlement rules, ensure you have: Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one. Create a master wallet in the [Blockradar Dashboard](https://dashboard.blockradar.co). Rules are configured per wallet — look one up with [Get Wallet](/en/api-reference/wallet/get-wallet). If settling cross-chain, ensure you have a wallet on the destination blockchain to receive converted assets. Fund your wallets with native tokens (ETH, BNB, MATIC, etc.) to cover swap and transfer fees. Set up webhooks to receive settlement notifications. The event family depends on which settlement type ran: `swap.*`, `withdraw.*`, `gateway-deposit.*`, or `reward-deposit.*`. See [Webhook notifications](#webhook-notifications) below and the [Webhooks](/en/utilities/webhooks) guide for details. ## How It Works Auto Settlements allow you to automatically convert incoming deposits into any destination asset on any blockchain network based on your configured rules. This eliminates the need to manually swap or bridge assets, ensuring your treasury can be automatically converted to your preferred assets across multiple chains. Create and manage auto-settlement rules to automate asset conversions. Automatically convert any stablecoin to any other asset based on your rules. Settle assets to any blockchain network seamlessly. Apply slippage tolerance and rules to protect against poor executions. ## How Auto Settlements Work ### **1. Rule Creation** Define settlement rules that specify when and how deposits should be automatically converted. ### **2. Deposit Detection** When funds arrive at your addresses, Blockradar automatically detects deposits matching your rules. ### **3. Asset Conversion** Deposits are automatically swapped to your destination asset (typically USDC) on your chosen chain. ### **4. Balance Unification** All converted assets are consolidated into a single, unified balance on your destination chain. ## Settlement Types Every rule resolves to one of four settlement flows. Set it explicitly with the `type` field: | Type | What happens | Required companion field | | - | - | - | | `withdraw` | The source asset is transferred out as-is to `destination.address` on the same blockchain. No conversion. | `destination.address`, and `destination.blockchain` must equal the source blockchain | | `swap` | The source asset is converted to a different asset and/or bridged to a different blockchain. | Source assets must differ from the destination asset when both are on the same chain | | `gateway` | USDC is deposited into Circle's Gateway unified balance. | `isGateway: true` | | `earn` | Funds are deposited into an Earn position with Aave or Compound. | `isReward: true` | `type` is optional for backwards compatibility. Rules created before it existed have no `type` and keep their **inferred** behavior — Blockradar decides between withdraw and swap by comparing the source and destination asset and chain. Send `type` on every new rule so the flow is explicit, and send it on an update to migrate a legacy rule onto the explicit system. On a **child address**, `type` is not just a hint. If you create a child-address rule without `type`, the extended fields — `isReward`, `rewardProvider`, `rewardType`, `productKey`, `useTransactionAmount`, and `deductionPercentage` — are silently discarded and the rule is stored in the legacy shape. Always send `type` when creating child-address rules. ### Type validation rules The API rejects contradictory combinations: * `type: gateway` requires `isGateway: true`, and `isGateway: true` requires `type: gateway` * `type: earn` requires `isReward: true`, and `isReward: true` requires `type: earn` * A rule can never be both gateway and earn * `type: withdraw` requires a `destination.address`, and the destination blockchain must equal the source blockchain * `type: swap` rejects a source asset that equals the destination asset on the same blockchain * Two rules on the same wallet cannot cover the same source asset on the same blockchain ### Gateway rules can fall through to swap A `gateway` rule only performs a Gateway deposit when the source chain and asset are Gateway-eligible. When they are not, the rule falls through and executes as a **swap** to `destination.blockchain` / `destination.asset` instead. The funds still settle, but you receive `swap.*` webhooks rather than `gateway-deposit.*`, so handle both when you configure gateway rules on chains outside Gateway's supported set. ## Auto Settlement Rules ### **Rule Components** Each auto-settlement rule defines the following parameters: | Component | Description | Example | | - | - | - | | **Type** | Settlement flow for the rule | withdraw, swap, gateway, earn | | **Rule Name** | Descriptive name for your settlement rule | "Swap from USDC to Optimism USDC" | | **Order** | Routing preference for the swap leg. Ignored for gateway and earn rules | FASTEST, CHEAPEST, RECOMMENDED, NO\_SLIPPAGE | | **Slippage Tolerance** | Maximum acceptable price deviation (%). Use `-1` for unlimited slippage | 5 or -1 | | **Source Assets** | Array of assets to auto-settle | \["USDC", "USDT"] | | **Source Min/Max Amount** | Control deposit size that triggers settlement | Min: $1, Max: $1,000 | | **Destination Blockchain** | Target blockchain network | optimism, base, ethereum | | **Destination Asset** | Target asset for conversion | USDC, USDT, cNGN, DAI | | **Destination Address** | (Optional except for withdraw rules) Specific address to receive converted assets. If not provided, smart fallback logic applies | 0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22 | | **Is Gateway** | Route the settlement through Circle's Gateway | false | | **Is Reward** | Route the settlement into an Earn position | false | | **Use Transaction Amount** | Settle the triggering deposit amount instead of the address balance | false | | **Deduction Percentage** | Percentage held back from the settled amount | "0" | | **Inheritance** | Which child addresses a master-wallet rule cascades to | `{ "mode": "all_children" }` | ### **How much gets settled** By default a settlement is sized from the address's balance, not from the deposit that triggered it. Set `useTransactionAmount` to choose: | `useTransactionAmount` | What is settled | | - | - | | `false` *(default)* | The address's **current balance** of the source asset — which can be more than the deposit that triggered the rule, for example when earlier deposits were left unsettled | | `true` | Only the amount of the deposit that triggered the rule | The amount is then clamped and adjusted in this order: 1. The amount is compared against `source.minAmount`. Below it, nothing settles. 2. The amount is capped at `source.maxAmount` (`"-1"` means no cap). 3. `deductionPercentage` is withheld from what remains. `"2.5"` settles 97.5% and leaves 2.5% on the address. Set `useTransactionAmount: true` when you need each deposit to map to exactly one settlement — reconciliation per payment, for example. Leave it `false` when you want the address swept clean each time. ## Earn Settlement Rules An `earn` rule deposits incoming funds into a yield position instead of transferring them out. It is the auto-settlement entry point to [Earn](/en/use-cases/earn). | Field | Value | | - | - | | `type` | `earn` | | `isReward` | `true` | | `rewardProvider` | `aave` or `compound` | | `rewardType` | `defi` (optional) | Constraints: * **Mainnet only.** Earn rules are rejected on testnet. * Every asset in `source.assets` must be supported by the chosen provider on the wallet's blockchain, otherwise the rule is rejected at creation. * `rewardType` is optional and defaults from the resolved product — both providers are `defi`. * `productKey` (optional) pins a specific earn product; only needed when a provider offers more than one product for a source asset, and the rule must then have exactly one source asset. * A rule cannot be both `isGateway` and `isReward`. ```bash theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/auto-settlements/rules \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "type": "earn", "name": "Earn on Base USDC deposits", "isReward": true, "rewardProvider": "aave", "rewardType": "defi", "source": { "assets": ["USDC"], "minAmount": "10", "maxAmount": "-1" }, "destination": { "blockchain": "base", "asset": "USDC" } }' ``` Earn settlements create a `REWARD_DEPOSIT` transaction and emit `reward-deposit.*` webhooks. Balance-based earn rules (`useTransactionAmount: false`) skip a new settlement while one is already pending or processing for the same address and asset — the in-flight settlement will absorb the newly arrived funds anyway. Amount-based earn rules (`useTransactionAmount: true`) are never skipped. ### **Rule Configuration Options** #### **Amount Thresholds** * **Minimum Amount**: Only settle when the amount is above this threshold * **Maximum Amount**: Cap the size of individual settlements * **Accumulation**: With `useTransactionAmount: false` (the default), the rule settles the address's whole balance of the source asset, so deposits that individually fell below `minAmount` are picked up together once the balance clears it #### **Slippage Protection** * **Unlimited**: `-1` (no slippage limit) * **Conservative**: 0.1% - 0.5% (minimal price impact) * **Moderate**: 0.5% - 1.0% (balanced approach) * **Aggressive**: 1.0% - 2.0% (faster execution) Before executing, the settlement fetches a quote and compares its slippage against your tolerance. If the quote exceeds the tolerance, the settlement fails rather than executing at a worse rate. Always send `slippageTolerance` explicitly on swap rules. `"-1"` means unlimited, and a value like `"5"` means 5%. A tolerance of `"0"` only permits a settlement at exactly zero slippage, which rejects almost every real swap quote. Slippage tolerance is not used by gateway or earn rules. #### **Destination Address (Optional)** The `destination.address` field is optional for `swap`, `gateway`, and `earn` rules. When not provided, the system uses smart fallback logic to determine the recipient address: | Scenario | Fallback Behavior | | - | - | | **Explicit address provided** | Uses the specified address | | **Same chain settlement** | Uses the deposit address (source address) | | **EVM-to-EVM cross-chain** | Uses the same address on the destination chain | | **Cross-chain (non-EVM destination)** | Uses the destination chain's master wallet address | For most use cases, you can omit the destination address and let the system automatically route funds to the appropriate address based on the settlement type. `withdraw` rules are the exception: they require an explicit `destination.address`, and `destination.blockchain` must be the same blockchain as the source. `destination.blockchain` and `destination.asset` are always required, on every rule type. #### **Execution Preferences** * **Fastest**: Prioritize speed over cost * **Cheapest**: Optimize for lowest fees * **Recommended**: Balance speed and cost with reliability * **No Slippage**: Execute only when no price deviation occurs ## Rule Hierarchy and Precedence ### **How Rules Apply** **Key Concept**: By default, rules created on a master wallet apply to the master wallet and all child addresses under it. A rule on a child address takes precedence over the master wallet's rules for the deposit it matches. | Rule Level | Scope | Behavior | | - | - | - | | **Master Wallet Rules** | The master wallet, plus the child addresses selected by the rule's `inheritance` setting (all of them by default) | Default rules for the wallet hierarchy | | **Child Address Rules** | Only that specific address | Take precedence over master wallet rules for any deposit they match | ### **Rule Application Order** Precedence is evaluated **per deposit**, not per address: 1. **Look for a matching child address rule.** A rule matches when it is active and its `source.assets` and `source.blockchain` cover the deposit. 2. **Fall back to the master wallet rules.** A master rule is then considered only if its `inheritance` setting allows it to apply to the address that received the deposit. 3. **No match at either level:** no auto-settlement occurs. A child address having *some* rules does not disable the master wallet's rules for that address. If none of the child address's rules match the deposited asset and chain, the master wallet rules are evaluated next. To stop a master rule from reaching an address, set that rule's `inheritance` explicitly — see below. ### **Per-Rule Inheritance** Each master-wallet rule controls which child addresses it cascades to through the optional `inheritance` object: | `mode` | The rule applies to | | - | - | | `all_children` | The master wallet and every child address | | `master_only` | The master wallet only — deposits on child addresses are ignored by this rule | | `selected_children` | The master wallet plus the specific addresses listed in `childAddressIds` | Omitting `inheritance` entirely keeps the original behavior and is equivalent to `all_children`. ```bash theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/auto-settlements/rules \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "type": "swap", "name": "Settle USDT deposits from partner addresses", "slippageTolerance": "1", "inheritance": { "mode": "selected_children", "childAddressIds": [ "0f9a1c3e-58c2-4a1b-9f0d-6d5f2a7c1b34", "7b3d9e21-4f6a-4c0e-8a52-1c9b0e4d7f88" ] }, "source": { "assets": ["USDT"], "minAmount": "1", "maxAmount": "-1" }, "destination": { "blockchain": "optimism", "asset": "USDC" } }' ``` Rules for `selected_children`: * `childAddressIds` must be present and non-empty, otherwise the request fails with `At least one child address must be selected`. * Every ID must be an active address belonging to your business on the same network. * The addresses must match the wallet's chain family. A rule on a non-EVM wallet (for example Tron, Solana, or Stellar) only accepts addresses on that same chain; a rule on an EVM wallet accepts any EVM address. A mismatch fails with `One or more selected child addresses are not valid for this chain or are inactive`. `inheritance` only exists on master-wallet rules. A rule created directly on a child address has nothing to cascade to, so the field is ignored and never stored there. ### **Blockchain-Specific Rules** **Important**: Rules are isolated and tied to each blockchain. A rule configured for one blockchain (e.g., Ethereum) will NOT affect deposits on another blockchain (e.g., Base or Optimism). This means: * You must create separate rules for each source blockchain you want to auto-settle * A rule for "USDC on Ethereum" will not trigger for "USDC on Base" * This allows granular control over settlement behavior per chain **Example**: If you want to auto-settle USDC deposits from both Ethereum and Base to Optimism, you need two separate rules: 1. Rule for Ethereum USDC → Optimism USDC 2. Rule for Base USDC → Optimism USDC ### **Use Cases for Each Level** #### **Master Wallet Rules** * **Consistent Strategy**: Same settlement behavior across all child addresses * **Simplified Management**: Single place to configure default behavior * **Bulk Operations**: Apply rules to multiple addresses at once * **Standardization**: Ensure compliance and consistency #### **Child Address Rules** * **Testing**: Try different settlement strategies on specific addresses * **Custom Requirements**: Address-specific settlement needs * **Override Defaults**: Modify behavior for particular use cases * **Granular Control**: Fine-tune settlement for specific addresses ## Creating Auto Settlement Rules ### **Via Dashboard** 1. Navigate to your wallet's Auto Settlements section 2. Click "Create New Rule" 3. Configure rule parameters 4. Set amount thresholds and slippage tolerance 5. Choose source and destination assets/chains 6. Save and activate the rule ### **Via API** Create settlement rules programmatically using the Auto Settlement Rules API: ```bash theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/auto-settlements/rules \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "type": "swap", "name": "Swap from USDC to Optimism USDC", "order": "FASTEST", "slippageTolerance": "-1", "source": { "assets": [ "USDC", "USDT" ], "minAmount": "1", "maxAmount": "1000" }, "destination": { "blockchain": "optimism", "asset": "USDC" } }' ``` In this example, `slippageTolerance` is set to `-1` for unlimited slippage, and `destination.address` is omitted. The system will automatically use smart fallback logic to determine the recipient address. **With explicit destination address:** ```bash theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/auto-settlements/rules \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "type": "swap", "name": "Swap from USDC to Optimism USDC", "order": "FASTEST", "slippageTolerance": "5", "source": { "assets": [ "USDC", "USDT" ], "minAmount": "1", "maxAmount": "1000" }, "destination": { "blockchain": "optimism", "asset": "USDC", "address": "0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22" } }' ``` ## Copying Rules Across Wallets Rules are per-blockchain, so rolling one strategy out across every chain you operate on means recreating the same rule many times. The copy endpoint does it in one call: ```bash theme={null} curl --request POST \ --url https://api.blockradar.co/v1/wallets/{walletId}/auto-settlements/rules/copy \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "rules": [ { "type": "withdraw", "name": "Sweep USDC to treasury", "slippageTolerance": "0", "source": { "assets": ["USDC"], "minAmount": "1", "maxAmount": "-1" }, "destination": { "blockchain": "base", "asset": "USDC", "address": "0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22" } } ], "targetWalletIds": [ "3f6c9a11-9a7e-4a3c-8f2b-0d51e6c4a7b2", "c81e7d40-5b6a-4f9e-9c3d-2a7f10b8e654" ] }' ``` Rules are sent **by value**, not by ID, so the source can be a master wallet's rules, a child address's rules, or a payload you composed yourself. Each rule's `source.blockchain` is rewritten to the target wallet's own blockchain before it is saved. ### **Partial success is normal** The call returns `200` even when some rules are skipped or some wallets fail. Always read the response rather than relying on the status code: ```json theme={null} { "data": { "summary": { "walletsTargeted": 2, "rulesRequested": 1, "applied": 1, "skipped": 1, "failed": 0 }, "results": [ { "walletId": "3f6c9a11-9a7e-4a3c-8f2b-0d51e6c4a7b2", "walletName": "Base Mainnet Wallet", "chain": "base", "applied": [{ "name": "Sweep USDC to treasury" }], "skipped": [] }, { "walletId": "c81e7d40-5b6a-4f9e-9c3d-2a7f10b8e654", "walletName": "Optimism Mainnet Wallet", "chain": "optimism", "applied": [], "skipped": [ { "name": "Sweep USDC to treasury", "reason": "A settlement rule for USDC already exists on the optimism wallet" } ] } ] }, "message": "Settlement rules copied", "statusCode": 200 } ``` | Outcome | Meaning | | - | - | | `applied` | The rule was written to that wallet | | `skipped` | The rule was rejected for that wallet only — the asset is not enabled there, a rule already covers that asset on that chain, or the rule failed validation against that wallet | | `failed` | The whole wallet could not be written, for example because it does not exist or is inactive on this network | Each target wallet is locked and written in its own transaction, so a failure on one target never leaves another partially written. Applying at least one rule to a wallet also switches auto-settlement **on** for that wallet. The request itself fails with `400` when the `rules` array is malformed, when `rules` or `targetWalletIds` is empty, or when the only target listed is the source wallet (the source is always removed from the target list). ## Use Cases ### **Treasury Management** * **Flexible Asset Conversion**: Convert to any preferred asset (USDC, ETH, USDT, etc.) * **Cross-Chain Operations**: Maintain balances across multiple networks * **Automated Consolidation**: No manual intervention required * **Multi-Asset Strategy**: Support various asset preferences and strategies ### **Business Operations** * **Payment Processing**: Automatically settle incoming payments to preferred assets * **Revenue Management**: Convert various stablecoins to your chosen destination asset * **Risk Mitigation**: Apply slippage protection automatically * **Asset Diversification**: Maintain target asset allocations automatically ### **DeFi Integration** * **Yield Farming**: Automatically settle rewards to preferred asset * **Liquidity Management**: Consolidate LP rewards and fees * **Portfolio Rebalancing**: Maintain target asset allocations ## Best Practices ### **Rule Configuration** * **Start Conservative**: Begin with low slippage tolerance * **Monitor Performance**: Track settlement success rates * **Adjust Gradually**: Fine-tune rules based on market conditions * **Test on Testnet**: Validate rules before mainnet deployment ### **Risk Management** * **Slippage Limits**: Set appropriate tolerance levels * **Amount Caps**: Limit maximum settlement sizes * **Network Selection**: Choose reliable destination chains * **Fallback Rules**: Create backup settlement options ### **Operational Efficiency** * **Accumulation**: Leave `useTransactionAmount` at `false` so small deposits settle together once the balance clears `minAmount` * **Timing Optimization**: Consider network congestion patterns * **Cost Analysis**: Balance speed vs. cost preferences * **Monitoring**: Set up alerts for failed settlements ## Monitoring and Alerts ### **Dashboard Monitoring** * **Rule Status**: Active/inactive rule indicators * **Settlement History**: Track successful and failed settlements * **Performance Metrics**: Success rates and execution times * **Asset Balances**: Monitor unified balance growth ### **Webhook Notifications** Auto-settlements trigger webhook events when settlements are executed. Which event family you receive depends on the settlement type that ran: | Settlement type | Events | | - | - | | `swap` | `swap.success`, `swap.failed`, `swap.cancelled`, `swap.processing` | | `withdraw` | `withdraw.success`, `withdraw.failed`, `withdraw.cancelled`, `withdraw.processing` | | `gateway` | `gateway-deposit.success`, `gateway-deposit.failed`, `gateway-deposit.cancelled`, `gateway-deposit.processing` | | `earn` | `reward-deposit.success`, `reward-deposit.failed`, `reward-deposit.cancelled`, `reward-deposit.processing` | A `gateway` rule on a chain that is not Gateway-eligible falls through to a swap, so it emits `swap.*` events instead of `gateway-deposit.*`. Subscribe to both if you run gateway rules outside Gateway's supported chains. ### **Webhook Payload Example** ```json theme={null} { "event": "swap.success", "data": { "id": "99a2b490-0798-460b-9265-4d99f182fe52", "reference": "ZMxcorDGtf", "senderAddress": "0xAA2d5fd5e7bE97E214f8565DCf3a4862719960b5", "recipientAddress": "0xb55c054D8eE75224E1033e6eC775B4F62D942b43", "amount": "5", "status": "SUCCESS", "type": "SWAP", "network": "mainnet", "toAmount": "4.965398", "rate": "0.9930796000000001", "asset": { "name": "USD Coin", "symbol": "USDC", "network": "mainnet" }, "toAsset": { "name": "Tether USD", "symbol": "USDT", "network": "mainnet" }, "toBlockchain": { "name": "optimism", "slug": "optimism" }, "toWallet": { "name": "Optimism Mainnet Wallet", "address": "0xb55c054D8eE75224E1033e6eC775B4F62D942b43" }, "metadata": { "swapAutoSettlement": { "rule": { "id": "rule-id-123", "name": "USDT to USDC on Base", "order": "RECOMMENDED", "slippageTolerance": 5, "source": { "assets": ["USDC", "USDT"], "minAmount": "1", "maxAmount": "1000" }, "destination": { "blockchain": "optimism", "asset": "USDC", "address": "0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22" } }, "settleAmount": "5" }, "transactionId": "transaction-id" } } } ``` ### **Identifying Auto-Settlement Transactions** The best way to identify auto-settlement transactions is by checking the metadata field. Depending on the action, the metadata will contain one of these keys: | Metadata Key | Description | | - | - | | `swapAutoSettlement` | Present when the auto-settlement triggered a swap operation | | `gatewayAutoSettlement` | Present when the auto-settlement triggered a Gateway operation | | `withdrawAutoSettlement` | Present when the auto-settlement triggered a withdrawal operation | | `rewardAutoSettlement` | Present when the auto-settlement triggered an Earn deposit | The swap, gateway, and withdraw objects contain: | Field | Description | | - | - | | `rule` | Complete auto-settlement rule payload that triggered this transaction | | `settleAmount` | Amount that was settled according to the rule | `rewardAutoSettlement` has a different shape — it carries the rule **ID** rather than the whole rule: | Field | Description | | - | - | | `ruleId` | ID of the earn rule that triggered this deposit | | `settleAmount` | Amount that was settled according to the rule | | `sourceTransactionId` | ID of the deposit transaction that triggered the settlement | When any of these metadata keys is present, the transaction was triggered by an auto-settlement rule. For swap, gateway, and withdraw settlements the `rule` field contains the complete rule configuration, not just an ID; for earn settlements, look up the rule with `ruleId`. ### **Key Webhook Data Fields** | Field | Description | | - | - | | `toAmount` | Final amount received after swap (accounting for fees and slippage) | | `rate` | Exchange rate used for the swap | | `toAsset` | Destination asset details (USDT in this example) | | `toBlockchain` | Destination blockchain network (Optimism in this example) | | `toWallet` | Destination wallet that received the converted assets | | `assetSwept` | Whether the original assets were swept after conversion | ## API Reference ### **Endpoints** #### **Master Wallet Auto Settlements** | Endpoint | Method | Description | API Reference | | - | - | - | - | | `/v1/wallets/{walletId}/auto-settlements/rules` | GET | List all settlement rules for master wallet | [Get All Rules](/en/api-reference/auto-settlements/master-wallet-get-rules) | | `/v1/wallets/{walletId}/auto-settlements/rules` | POST | Create new settlement rule for master wallet | [Create Rule](/en/api-reference/auto-settlements/master-wallet-create-rule) | | `/v1/wallets/{walletId}/auto-settlements/rules/copy` | POST | Copy settlement rules onto other master wallets | [Copy Rules](/en/api-reference/auto-settlements/master-wallet-copy-rules) | | `/v1/wallets/{walletId}/auto-settlements/rules/{id}` | GET | Get specific master wallet rule details | [Get Rule](/en/api-reference/auto-settlements/master-wallet-get-rule) | | `/v1/wallets/{walletId}/auto-settlements/rules/{id}` | PATCH | Update existing master wallet rule | [Update Rule](/en/api-reference/auto-settlements/master-wallet-update-rule) | | `/v1/wallets/{walletId}/auto-settlements/rules/{id}` | DELETE | Delete master wallet settlement rule | [Delete Rule](/en/api-reference/auto-settlements/master-wallet-delete-rule) | | `/v1/wallets/{walletId}/auto-settlements` | GET | Get master wallet settlement history | [Get Settlement](/en/api-reference/auto-settlements/master-wallet) | | `/v1/wallets/{walletId}/auto-settlements` | PATCH | Update master wallet settlement settings | [Update Settlement](/en/api-reference/auto-settlements/master-wallet-update) | #### **Child Address Auto Settlements** | Endpoint | Method | Description | API Reference | | - | - | - | - | | `/v1/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules` | GET | List all settlement rules for specific address | [Get All Rules](/en/api-reference/auto-settlements/child-address-get-rules) | | `/v1/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules` | POST | Create new settlement rule for specific address | [Create Rule](/en/api-reference/auto-settlements/child-address-create-rule) | | `/v1/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules/{id}` | GET | Get specific address rule details | [Get Rule](/en/api-reference/auto-settlements/child-address-get-rule) | | `/v1/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules/{id}` | PATCH | Update existing address rule | [Update Rule](/en/api-reference/auto-settlements/child-address-update-rule) | | `/v1/wallets/{walletId}/addresses/{addressId}/auto-settlements/rules/{id}` | DELETE | Delete address settlement rule | [Delete Rule](/en/api-reference/auto-settlements/child-address-delete-rule) | | `/v1/wallets/{walletId}/addresses/{addressId}/auto-settlements` | GET | Get address settlement history | [Get Settlement](/en/api-reference/auto-settlements/child-address) | | `/v1/wallets/{walletId}/addresses/{addressId}/auto-settlements` | PATCH | Update address settlement settings | [Update Settlement](/en/api-reference/auto-settlements/child-address-update) | There is no copy endpoint for child addresses — copying always targets master wallets, though the rules you copy can come from a child address. ### **Update semantics differ by level** | Endpoint | Body handling | | - | - | | `PATCH /wallets/{walletId}/auto-settlements/rules/{id}` | **Partial merge.** Send only the fields you are changing; everything else keeps its current value. Nested objects such as `source` and `destination` are replaced wholesale, so send them complete when you send them at all | | `PATCH /wallets/{walletId}/addresses/{addressId}/auto-settlements/rules/{id}` | **Full rule.** `source` and `destination` are required, and any optional field you omit is reset to its default — `order` to `RECOMMENDED`, `slippageTolerance` and `deductionPercentage` to `"0"`, `useTransactionAmount` to `false`, `isActive` to `true`, `source.minAmount` to `"0"`, `source.maxAmount` to `"-1"` | Read the rule first and send the whole object back when updating a **child address** rule. Sending only the field you want to change will silently reset the rest of the rule to defaults. In both cases the merged rule is re-validated, so an update can be rejected because of a field you did not send. ### **Rule Parameters** | Parameter | Type | Required | Description | | - | - | - | - | | `type` | string | No | Settlement flow: `withdraw`, `swap`, `gateway`, or `earn`. Send it on every new rule | | `name` | string | No | Rule name for identification | | `isActive` | boolean | No | Whether the rule is enabled. Defaults to `true` | | `order` | string | No | Routing preference (FASTEST/CHEAPEST/RECOMMENDED/NO\_SLIPPAGE). Defaults to `RECOMMENDED`; ignored for gateway and earn rules | | `slippageTolerance` | string | No | Maximum acceptable slippage (%). Use `-1` for unlimited. Send it explicitly on swap rules | | `isGateway` | boolean | No | Route through Circle's Gateway. Required with `type: gateway` | | `isReward` | boolean | No | Route into an Earn position. Required with `type: earn`. Mainnet only | | `rewardProvider` | string | Conditional | `aave` or `compound`. Required when `isReward` is `true` | | `rewardType` | string | No | `defi`. Optional — defaults from the resolved product | | `productKey` | string | No | Pins a specific earn product. Only needed when a provider offers more than one product for a source asset | | `useTransactionAmount` | boolean | No | `false` (default) settles the address balance; `true` settles only the triggering deposit | | `deductionPercentage` | string | No | Percentage withheld from the settled amount. Defaults to `"0"` | | `inheritance.mode` | string | No | `master_only`, `all_children`, or `selected_children`. Master-wallet rules only | | `inheritance.childAddressIds` | array | Conditional | Required and non-empty when mode is `selected_children` | | `source.assets` | array | Yes | Array of source assets to auto-settle | | `source.minAmount` | string | No | Minimum amount to trigger settlement. Defaults to `"0"` | | `source.maxAmount` | string | No | Maximum amount per settlement. Use `-1` for unlimited (default) | | `source.blockchain` | string | No | Ignored on create — always set to the wallet's own blockchain | | `destination.blockchain` | string | Yes | Target blockchain network. Must equal the source blockchain for `withdraw` rules | | `destination.asset` | string | Yes | Target asset for conversion. Forced to USDC for gateway rules | | `destination.address` | string | Conditional | Required for `withdraw` rules. Otherwise optional — uses smart fallback logic (see above) | ## Getting Started ### **1. Enable Auto Settlements** * Navigate to your wallet settings * Enable auto-settlement functionality * Configure default preferences ### **2. Create Your First Rule** * Start with a simple USDT to ETH rule (or any asset you prefer) * Set conservative slippage tolerance * Choose your preferred destination chain and asset ### **3. Test and Monitor** * Deploy on testnet first * Monitor settlement success rates * Adjust parameters as needed ### **4. Scale Gradually** * Add rules for additional assets * Implement batch processing * Optimize for your use case ## Support and Resources ### **Getting Help** * **Email**: [support@blockradar.co](mailto:support@blockradar.co) * **API Reference**: [Auto Settlement Rules](/en/api-reference/auto-settlements/master-wallet) * **Documentation**: [Gateway Configuration](/en/use-cases/gateway) Auto settlements are a powerful way to automate your treasury management. Start with simple rules and gradually add complexity as you become more familiar with the system. # Stablecoin Checkout Source: https://docs.blockradar.co/en/use-cases/checkout Create and manage checkout payment links for seamless stablecoin payments In a nutshell
Blockradar Checkout lets you accept stablecoin payments via shareable links—no customer accounts or complex integrations required. Create a link, share it, and receive payments directly to your wallet.