# Bayar RPC dengan USDC / USDT / USDG: top up terprogram untuk agen AI

> Source: https://docs.blockvectra.com/id/guides/agent-topup/

Pengembang dan Agen AI dapat melakukan top up akun RPC dan Data API melalui HTTP: periksa jaringan dan token yang terbuka, gunakan API key yang ada untuk mendapatkan alamat deposit EVM akun, lalu lakukan polling status kredit setelah mentransfer dana. Sebelum mendanai, periksa [halaman harga](https://blockvectra.com/en/pricing/) dan [perkirakan biaya RPC dan Data API dari bobot CU](https://docs.blockvectra.com/en/guides/reading-cu-pricing/).

## Dapatkan alamat deposit Anda di Penagihan

Masuk, [buka Penagihan untuk mendapatkan alamat deposit Anda](https://console.blockvectra.com/login/?next=%2Fbilling%2F), dan gunakan alamat deposit serta detail token yang ditampilkan untuk akun Anda. Periksa jaringan, token, dan deposit minimum saat ini di [GET /v1/topup/status](https://api.blockvectra.com/v1/topup/status) sebelum mentransfer dana.

> **Keamanan API key dan persyaratan penggunaan di sisi server**
>
> Header `x-api-key` **hanya dapat dipanggil dari lingkungan sisi server**. Jangan pernah memanggil endpoint top-up dari kode browser sisi klien, dan jangan pernah mengekspos API key Anda dalam bundle frontend, repositori publik, atau percakapan obrolan AI.


## Prasyarat

* **API key yang sudah ada**: Memanggil endpoint top-up terautentikasi memerlukan API key RPC BlockVectra yang aktif. Jika Anda belum memiliki API key, ikuti [Panduan pendaftaran terprogram](https://docs.blockvectra.com/en/guides/programmatic-signup/) untuk mendaftar dan membuat kunci menggunakan tanda tangan dompet Ethereum, atau buat satu di [Konsol](https://console.blockvectra.com/login/?next=%2Fkeys%2F).
* **Aset on-chain**: Lingkungan agen atau dompet pendanaan Anda harus memiliki USDC / USDT / USDG yang tercantum di `GET /v1/topup/status` pada jaringan yang didukung, bersama dengan token gas native yang cukup untuk menyiarkan transaksi.
* **Variabel lingkungan**: Simpan kunci Anda dalam variabel lingkungan `BLOCKVECTRA_API_KEY`.

Endpoint top-up terautentikasi menerima header `x-api-key` secara langsung menggunakan API key yang sama dengan yang digunakan untuk panggilan RPC. Tidak diperlukan sesi browser.

## Alur kerja top up empat langkah

Setelah top up berbayar pertama dikreditkan, pengisian ulang siklus gratis berhenti, kredit gratis yang belum digunakan tetap tersedia, dan batas laju panggilan tingkat akun dihapus; batas laju per-kunci tetap tidak berubah. Lihat [aturan harga](https://blockvectra.com/en/pricing/) dan [aturan paket gratis](https://blockvectra.com/en/free/#rules); baca batas saat ini dan deposit minimum dari [GET /v1/plans](https://console-api.blockvectra.com/v1/plans) (`free`, `key_defaults`, dan `pricing.min_topup_usd`).

Endpoint top-up (status, alamat deposit, dan deposit) menggunakan host API produksi:

```
https://api.blockvectra.com
```

Batas paket dan parameter harga disajikan oleh Console API di `https://console-api.blockvectra.com` (seperti [GET https://console-api.blockvectra.com/v1/plans](https://console-api.blockvectra.com/v1/plans)).

### 1. Periksa ketersediaan (GET /v1/topup/status)

Sebelum memulai transfer, verifikasi status top-up global, periksa jaringan dan token mana yang saat ini terbuka, dan baca ambang batas deposit minimum yang aktif. Endpoint ini bersifat publik dan tidak memerlukan kredensial.

```bash
curl -s https://api.blockvectra.com/v1/topup/status
```

Contoh respons (jaringan dan token yang dipilih):

```json
{
  "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
    }
  ]
}
```

* `enabled`: Sakelar global. Jika `false`, top-up ditutup di semua jaringan.
* `networks`: Status terbuka per jaringan dan token. Ketika `enabled` bernilai `false` untuk suatu jaringan atau token, **jangan transfer dana pada jaringan tersebut**.
* `min_deposit_usd`: Jumlah deposit minimum global dalam USD yang diformat hingga 6 tempat desimal. Ambang batas deposit minimum bersifat dinamis: selalu rujuk `min_deposit_usd` yang dikembalikan secara real-time oleh `GET https://api.blockvectra.com/v1/topup/status`.

Untuk membaca `min_deposit_usd` yang aktif secara langsung:

```bash
curl -s https://api.blockvectra.com/v1/topup/status | jq -r .min_deposit_usd
```

### 2. Dapatkan alamat deposit dan parameter (GET /v1/topup/deposit-address)

Dapatkan atau alokasikan alamat deposit EVM pelanggan dan periksa jaringan serta kontrak token yang didukung. Endpoint ini memerlukan autentikasi `x-api-key` dan hanya boleh dipanggil dari lingkungan sisi server.

```bash
curl -s \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  https://api.blockvectra.com/v1/topup/deposit-address
```

Contoh respons (jaringan dan token yang dipilih):

```json
{
  "address": "0x<your-dedicated-deposit-address>",
  "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`: Alamat deposit EVM ber-checksum EIP-55 yang didedikasikan untuk akun Anda.
* `deposits_url`: URL untuk mengueri rekaman deposit pelanggan.
* `networks`: Daftar jaringan EVM yang terbuka. Jaringan yang ditutup dihilangkan. Mencakup slug rantai `chain`, EVM chain ID `chain_id`, nama tampilan `name`, latensi kredit tipikal dalam detik setelah penyertaan blok `typical_credit_seconds`, dan templat URL transaksi penjelajah blok `explorer_tx_url`.
* `tokens`: Token pada jaringan ini, termasuk simbol token `symbol` (USDC / USDT / USDG), alamat kontrak `contract`, desimal token `decimals`, dan jumlah deposit minimum dalam unit atomik mentah `min_amount_raw` (rujuk nilai aktual yang dikembalikan oleh endpoint; jangan berasumsi jumlah yang diskalakan).

> **Desimal token dan konversi jumlah**
>
> Token yang sama dapat memiliki desimal yang berbeda pada rantai yang berbeda (misalnya, USDT dan USDC di BSC memiliki 18 desimal, sedangkan USDC di Base memiliki 6 desimal). Perhitungan jumlah harus menggunakan `decimals` yang dikembalikan untuk jaringan spesifik tersebut alih-alih melakukan hardcoding satu nilai desimal token.


#### Respons error

Endpoint top-up terautentikasi (`/v1/topup/deposit-address` dan `/v1/topup/deposits`) mengembalikan struktur error JSON standar:

* **HTTP 401 (Kegagalan autentikasi)**: Dikembalikan ketika header `x-api-key` tidak ada (`missing_api_key`) atau kunci tidak valid, dicabut, atau dinonaktifkan (`invalid_api_key`):

```json
{
  "error": {
    "code": "missing_api_key",
    "message": "missing API key: send it in the x-api-key header",
    "data": {
      "reason": "missing_api_key",
      "docs_url": "https://docs.blockvectra.com/en/errors/#missing_api_key",
      "retryable": false
    }
  }
}
```

* **HTTP 409 (Top-up dinonaktifkan)**: Dikembalikan ketika top-up ditutup secara global atau di semua jaringan (`topup_disabled`):

```json
{
  "error": {
    "code": "topup_disabled",
    "data": {
      "reason": "topup_disabled",
      "docs_url": "https://docs.blockvectra.com/en/errors/#topup_disabled",
      "retryable": false
    }
  }
}
```

Untuk daftar lengkap kode error, lihat [Referensi Error](https://docs.blockvectra.com/en/errors/).

### 3. Siarkan transfer on-chain

Menggunakan dompet atau skrip agen Anda, kirim transaksi `transfer` ERC-20 ke `address` deposit yang diperoleh pada Langkah 2.

Persyaratan transfer:

* Kirim hanya token dan kontrak yang tercantum dalam array `tokens` untuk jaringan tersebut.
* Pastikan jumlah transfer lebih besar dari atau sama dengan `min_amount_raw` (tunduk pada nilai aktual yang dikembalikan oleh `GET /v1/topup/deposit-address`, atau `min_deposit_usd` yang dikembalikan oleh `GET /v1/topup/status`), diformat sesuai dengan `decimals` token pada jaringan tersebut.
* Transfer yang dikirim ke rantai yang tidak didukung atau dengan token yang salah tidak dapat dikreditkan secara otomatis; verifikasi jaringan dan kontrak token sebelum menyiarkan.
* Catat hash transaksi on-chain (`tx_hash`) setelah dikirimkan.

### 4. Lakukan polling rekaman deposit dan verifikasi kredit (GET /v1/topup/deposits)

Setelah transaksi dimasukkan ke dalam blok, kueri riwayat transfer deposit untuk melacak status pengkreditan. Endpoint ini memerlukan `x-api-key` dan hanya untuk sisi server.

#### Parameter kueri

* `limit`: Jumlah rekaman deposit yang dikembalikan per halaman. Default adalah `20`, rentang valid adalah `1`–`100`.
* `before`: Parameter paginasi kursor berdasarkan `deposit_id`. Teruskan nilai `next_before` dari respons halaman sebelumnya untuk mengambil halaman berikutnya dari rekaman yang lebih lama.
* `tx_hash`: Hash transaksi heksadesimal 64 karakter berawalan 0x opsional untuk memfilter transfer tertentu.

Filter berdasarkan hash transaksi (`tx_hash`) untuk memeriksa transfer spesifik Anda:

```bash
curl -s \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  "https://api.blockvectra.com/v1/topup/deposits?tx_hash=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
```

Contoh respons:

```json
{
  "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 rekaman deposit yang cocok dengan parameter kueri.
* `next_before`: ID kursor untuk halaman berikutnya jika ada lebih banyak rekaman, atau `null` jika tidak ada rekaman yang lebih lama. Gabungkan dengan parameter kueri `before` untuk paginasi berbasis kursor.

Nilai `status` deposit:

* `processing`: Transfer terdeteksi on-chain, pengkreditan sedang berlangsung.
* `credited`: Dikreditkan ke saldo akun. `credited_units` dan `credited_cu` menunjukkan jumlah yang dikreditkan.
* `not_credited`: Transfer tidak dapat dikreditkan. Bidang `reason` menunjukkan penyebabnya:
  * `below_minimum`: Jumlah deposit di bawah ambang batas minimum.
  * `large_amount`: Jumlah deposit melebihi ambang batas dan memerlukan peninjauan manual.
  * `other`: Pengecualian pengkreditan lainnya.

Latensi kredit dan panduan polling:

* **Waktu kedatangan dan pengkreditan**: Waktu pengkreditan diatur oleh `typical_credit_seconds` yang dikembalikan pada Langkah 2.
* **Interval polling**: Lakukan polling dengan interval yang disarankan **setiap 20–60 detik**, tidak lebih sering, untuk menghindari pemicuan batas laju.

## Contoh kode

Contoh berikut menunjukkan cara membaca `BLOCKVECTRA_API_KEY` dari lingkungan dan mengueri endpoint top-up di Node.js dan Python.

### Node.js (fetch)

```javascript
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 and read minimum deposit threshold
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");
}
const minDepositUsd = status.min_deposit_usd;
console.log("Minimum deposit (USD):", minDepositUsd);

// 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)

```python
# 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 and read minimum deposit threshold
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")
min_deposit_usd = status_data.get("min_deposit_usd")
print("Minimum deposit (USD):", min_deposit_usd)

# 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()
```

## Langkah selanjutnya

* [Kueri saldo (`GET /v1/account`)](https://docs.blockvectra.com/en/guides/billing-rules/#query-balance-get-v1account) untuk memverifikasi saldo akun Anda dan sisa Compute Unit (CU).
* [Aturan penagihan](https://docs.blockvectra.com/en/guides/billing-rules/) untuk meninjau pengukuran Compute Unit (CU), batas laju, dan error yang tidak ditagih.
* [Panduan paket gratis](https://docs.blockvectra.com/en/guides/free-plan/) untuk meninjau batas tingkat gratis dan aturan peningkatan.
* [Panduan pendaftaran terprogram](https://docs.blockvectra.com/en/guides/programmatic-signup/) untuk membuat akun dan menyediakan API key menggunakan tanda tangan dompet.
