Agent programmatic top-up: on-chain balance funding with x-api-key
Fund accounts on-chain programmatically with an API key, dedicated deposit addresses, and transaction polling for autonomous AI agents and server programs without a browser.
For autonomous AI agents, automated scripts, and backend server programs, BlockVectra provides a programmatic on-chain top-up workflow over standard HTTP endpoints. Without requiring browser interaction, programs can use an existing API key to retrieve an account-dedicated EVM deposit address, inspect open networks and tokens, and poll deposit status after broadcasting an on-chain transfer.
API key security and server-side requirement
The x-api-key header can only be called from server-side environments. Browser cross-origin preflight requests intentionally do not permit this header on top-up endpoints. Never call top-up endpoints from client-side browser code, and never expose your API key in frontend bundles, public repositories, or AI chat conversations.
Applicable scenarios
- Autonomous AI agents: When Compute Units (CU) or account balance run low, agents can inspect top-up availability and replenish funds on-chain independently.
- CI/CD and automation pipelines: Automated test suites and recurring server jobs can maintain an active account balance programmatically.
- Backend services without browsers: Headless server services can manage balance top-ups directly via standard HTTP clients.
Prerequisites
- Existing API key: Calling authenticated top-up endpoints requires an active BlockVectra RPC API key. If you do not have an API key yet, follow the Programmatic sign-up guide to sign up and create a key using an Ethereum wallet signature, or create one in the Console.
- On-chain assets: Your agent environment or funding wallet must hold USDT or USDC on a supported network, along with sufficient native gas tokens to broadcast transactions.
- Environment variable: Store your key in the
BLOCKVECTRA_API_KEYenvironment variable.
The authenticated top-up endpoints accept the x-api-key header directly using the same API key used for RPC calls. No browser session is required.
Four-step top-up workflow
All endpoints use the official production host:
https://api.blockvectra.com1. Check availability (GET /v1/topup/status)
Before initiating a transfer, verify global top-up status and check which networks and tokens are currently open. This endpoint is public and requires no credentials.
curl -s https://api.blockvectra.com/v1/topup/statusExample response:
{
"enabled": true,
"networks": [
{
"network": "base_mainnet",
"chain_id": 8453,
"token": "USDC",
"enabled": true
},
{
"network": "bsc_mainnet",
"chain_id": 56,
"token": "USDT",
"enabled": true
},
{
"network": "bsc_mainnet",
"chain_id": 56,
"token": "USDC",
"enabled": true
}
],
"min_deposit_usd": "1.000000"
}enabled: Global switch. Iffalse, top-up is closed across all networks.networks: Open status per network and token. Whenenabledisfalsefor a network or token, do not transfer funds on that network.min_deposit_usd: Global minimum deposit amount in USD formatted to 6 decimal places.
2. Retrieve deposit address and parameters (GET /v1/topup/deposit-address)
Retrieve or allocate the customer EVM deposit address and inspect supported networks and token contracts. This endpoint requires x-api-key authentication and must be called from server-side environments only.
curl -s \
-H "x-api-key: $BLOCKVECTRA_API_KEY" \
https://api.blockvectra.com/v1/topup/deposit-addressExample response:
{
"address": "0x<your-dedicated-deposit-address>",
"min_deposit_usd": "1.000000",
"deposits_url": "https://api.blockvectra.com/v1/topup/deposits",
"networks": [
{
"chain": "base_mainnet",
"chain_id": 8453,
"name": "Base",
"typical_credit_seconds": 30,
"explorer_tx_url": "https://basescan.org/tx/{tx_hash}",
"tokens": [
{
"symbol": "USDC",
"contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"decimals": 6,
"min_amount_raw": "1000000"
}
]
},
{
"chain": "bsc_mainnet",
"chain_id": 56,
"name": "BNB Smart Chain",
"typical_credit_seconds": 60,
"explorer_tx_url": "https://bscscan.com/tx/{tx_hash}",
"tokens": [
{
"symbol": "USDT",
"contract": "0x55d398326f99059fF775485246999027B3197955",
"decimals": 18,
"min_amount_raw": "1000000000000000000"
},
{
"symbol": "USDC",
"contract": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
"decimals": 18,
"min_amount_raw": "1000000000000000000"
}
]
}
]
}address: EIP-55 checksummed EVM deposit address dedicated to your account.networks: List of open EVM networks. Closed networks are omitted. Includes chain slugchain, EVM chain IDchain_id, display namename, typical credit latency in seconds after block inclusiontypical_credit_seconds, and block explorer transaction URL templateexplorer_tx_url.tokens: Supported stablecoins on this network, including token symbolsymbol(USDT or USDC), contract addresscontract, token decimalsdecimals, and minimum deposit amount in raw atomic unitsmin_amount_raw.
Token decimals and amount conversion
The same token can have different decimals on different chains (for example, USDT and USDC on BSC are 18 decimals, whereas USDC on Base is 6 decimals). Amount calculation must use the decimals returned for that specific network rather than hardcoding a single token decimal value.
Error responses
Authenticated top-up endpoints (/v1/topup/deposit-address and /v1/topup/deposits) return standard JSON error structures:
- HTTP 401 (Authentication failure): Returned when the
x-api-keyheader is missing (missing_api_key) or the key is invalid, revoked, or disabled (invalid_api_key):
{
"error": {
"code": "missing_api_key",
"message": "missing x-api-key header"
}
}- HTTP 409 (Top-up disabled): Returned when top-up is closed globally or across all networks (
topup_disabled):
{
"error": {
"code": "topup_disabled",
"message": "topup is disabled"
}
}When HTTP 409 is returned, no new address is allocated.
3. Broadcast on-chain transfer
Using your agent's wallet or script, submit an ERC-20 transfer transaction to the deposit address retrieved in Step 2.
Transfer requirements:
- Send only tokens and contracts listed in the
tokensarray for that network. - Ensure the transfer amount is greater than or equal to
min_amount_raw(ormin_deposit_usd), formatted according to the token'sdecimalson that network. - Record the on-chain transaction hash (
tx_hash) once submitted.
4. Poll deposit records and verify credit (GET /v1/topup/deposits)
After the transaction is included in a block, query deposit transfer history to track crediting status. This endpoint requires x-api-key and is server-side only.
Query parameters
limit: Number of deposit records to return per page. Default is20, valid range is1–100.before: Cursor pagination parameter based ondeposit_id. Pass thenext_beforevalue from the previous page response to fetch the next page of earlier records.tx_hash: Optional 0x-prefixed 64-character hexadecimal transaction hash to filter for a specific transfer.
Filter by transaction hash (tx_hash) to inspect your specific transfer:
curl -s \
-H "x-api-key: $BLOCKVECTRA_API_KEY" \
"https://api.blockvectra.com/v1/topup/deposits?tx_hash=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"Example response:
{
"items": [
{
"deposit_id": 42,
"chain": "base_mainnet",
"chain_id": 8453,
"token": "USDC",
"contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "25.000000",
"tx_hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"tx_log_ordinal": 0,
"block_number": 123456789,
"external_ref": "eip155:8453:0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890:0",
"status": "credited",
"reason": null,
"credited_units": 250000,
"credited_cu": 250000000,
"detected_at": "2026-10-02T10:00:00Z"
}
],
"next_before": null
}items: Array of deposit records matching the query parameters.next_before: Cursor ID for the next page when more records exist, ornullif there are no earlier records. Combine with thebeforequery parameter for cursor-based pagination.
Deposit status values:
processing: Transfer detected on-chain, awaiting required block confirmations.credited: Transfer confirmed and credited to the account balance.credited_unitsandcredited_cuindicate the credited amounts.not_credited: Transfer cannot be credited. Thereasonfield indicates the cause:below_minimum: Deposit amount is below the minimum threshold.large_amount: Deposit amount exceeds threshold and requires manual review.other: Other crediting exception.
Credit latency and polling guidance:
- Arrival and crediting time: Credit time is governed by the
typical_credit_secondsreturned in Step 2. - Polling interval: Poll at a recommended interval of every 20–60 seconds, not more frequently, to avoid triggering rate limits.
- Status progression: Once sufficient block confirmations are reached, status transitions automatically from
processingtocredited.
Code examples
The following examples demonstrate how to read BLOCKVECTRA_API_KEY from the environment and query top-up endpoints in Node.js and Python.
Node.js (fetch)
import process from "node:process";
const apiKey = process.env.BLOCKVECTRA_API_KEY;
if (!apiKey) {
throw new Error("Missing BLOCKVECTRA_API_KEY environment variable");
}
const BASE_URL = "https://api.blockvectra.com";
// 1. Check availability
const statusRes = await fetch(`${BASE_URL}/v1/topup/status`);
const status = await statusRes.json();
if (!status.enabled) {
throw new Error("Top-up is currently disabled");
}
// 2. Retrieve deposit address and open networks
const addressRes = await fetch(`${BASE_URL}/v1/topup/deposit-address`, {
headers: { "x-api-key": apiKey },
});
if (addressRes.status === 401) {
throw new Error("Missing or invalid API key (HTTP 401)");
}
if (addressRes.status === 409) {
throw new Error("Top-up is disabled (topup_disabled)");
}
if (!addressRes.ok) {
throw new Error(`Failed to retrieve deposit address: ${addressRes.status}`);
}
const depositData = await addressRes.json();
console.log("Deposit address:", depositData.address);
console.log("Open networks count:", depositData.networks.length);
// 3. Poll deposit status
async function checkDepositStatus(txHash) {
const url = new URL(`${BASE_URL}/v1/topup/deposits`);
url.searchParams.set("tx_hash", txHash);
const res = await fetch(url, {
headers: { "x-api-key": apiKey },
});
if (res.status === 401) {
throw new Error("Missing or invalid API key (HTTP 401)");
}
if (!res.ok) {
throw new Error(`Failed to query deposits: ${res.status}`);
}
return res.json();
}Python (requests)
# pip install requests
import os
import requests
api_key = os.environ.get("BLOCKVECTRA_API_KEY")
if not api_key:
raise ValueError("Missing BLOCKVECTRA_API_KEY environment variable")
base_url = "https://api.blockvectra.com"
# 1. Check availability
resp = requests.get(f"{base_url}/v1/topup/status", timeout=10)
resp.raise_for_status()
status_data = resp.json()
if not status_data.get("enabled"):
raise RuntimeError("Top-up is currently disabled")
# 2. Retrieve deposit address
resp = requests.get(
f"{base_url}/v1/topup/deposit-address",
headers={"x-api-key": api_key},
timeout=10,
)
if resp.status_code == 401:
raise RuntimeError("Missing or invalid API key (HTTP 401)")
if resp.status_code == 409:
raise RuntimeError("Top-up is disabled (topup_disabled)")
resp.raise_for_status()
deposit_data = resp.json()
print("Deposit address:", deposit_data["address"])
# 3. Poll deposit status
def check_deposit_status(tx_hash: str):
resp = requests.get(
f"{base_url}/v1/topup/deposits",
headers={"x-api-key": api_key},
params={"tx_hash": tx_hash},
timeout=10,
)
if resp.status_code == 401:
raise RuntimeError("Missing or invalid API key (HTTP 401)")
resp.raise_for_status()
return resp.json()Important notes
- Supported networks and tokens: Only transfer to networks and token contracts explicitly listed in
GET /v1/topup/statusandGET /v1/topup/deposit-address. Ifenabledisfalsefor a network instatus, do not transfer funds to it. - Token decimals: Token decimals differ across chains (e.g. 18 on BSC vs 6 on Base). Always calculate amounts using the
decimalsreturned for that network. - Minimum deposit amount: Minimum amounts are determined by
min_deposit_usdandmin_amount_rawreturned by the API. Transfers below this threshold are not credited automatically. - Irreversible transfers: Transfers sent to unsupported chains or with incorrect tokens cannot be credited automatically. Always verify chain ID and contract address prior to broadcasting.
- Plan and rate limit updates: Once your first paid top-up is credited, the account transitions from the Free Plan to a paid account, removing the Free Plan's per-second call limit. Each key remains subject to Compute Unit (CU) rate and burst limits. For complete details, see Billing rules and Free plan.
- Polling frequency: Poll
GET /v1/topup/depositsat a recommended interval of every 20–60 seconds, not more frequently, to avoid triggering rate limits. - Server-side only: Never expose
x-api-keyin frontend applications or client-side browser code.
Next steps
- Query balance (
GET /v1/account) to verify your account balance and remaining Compute Units (CU). - Billing rules to review Compute Unit (CU) metering, rate limits, and non-billed errors.
- Programmatic sign-up guide to create accounts and provision API keys using wallet signatures.
Last updated:
Billing rules
A detailed breakdown of billing rules across HTTP status codes, JSON-RPC errors, and the Data API, with recommended actions for developers.
Connect AI agents
Integration guide for AI agents and LLM tools: connect the keyless docs MCP server, then discover capabilities with llms.txt and OpenAPI specs and call BlockVectra APIs.