▲HIGHLAND DOCS

Buy credits with USDC

Credits are bought with USDC on Base (chain id 8453). There is no card processor, no account form and no ID check. You send USDC from any wallet (Coinbase, MetaMask, Rabby, Rainbow, a hardware wallet, an exchange withdrawal to Base) and the balance appears after 3 confirmations.

The easy way is the buy page: paste your key, pick an amount, then pay with a browser wallet, a phone wallet, or a manual send. Wallets lists what each button does. This page explains the API behind that page, so you (or your agent) can do it without the browser.

How it works

  1. Ask for an intent. You say how many dollars you want to spend. The API answers with an exact USDC amount (your dollars plus a few random micro-cents), the address to pay and a 24-hour expiry.
  2. Send exactly that amount of USDC on Base to the payTo address.
  3. Claim it. Send the transaction hash. The API reads the receipt from the chain, matches the Transfer to your open intent by its exact amount, and credits your balance once.

The unique amount is what ties a payment to your account, so nobody can claim your transfer and the same transaction can never be credited twice.

LimitValue
Minimum top-up$1.00 USD
Maximum top-up$1,000.00 USD
Intent lifetime24 hours
Open (unpaid) intents per account10
Confirmations before credit3
Exchange rateX402_USD_PER_CAD = 0.75 USD per CAD (so $10 USD buys 1,333 credits)

1. Create an intent

bash
curl -s https://api.highlnd-intel.group/v1/topup/crypto/intent \
  -H "authorization: Bearer $HIGHLAND_KEY" \
  -H "content-type: application/json" \
  -d '{"usd": 10}'
json
{
  "intentId": "int_3f0c9a...",
  "network": "base",
  "chainId": 8453,
  "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "payTo": "0xfdb6ea04e7e75d39d3bdb4ba21e6b6c8fec36048",
  "amount": "10.004217",
  "amountMicro": "10004217",
  "creditCents": 1333,
  "expiresAt": "2026-10-24T23:10:00.000Z",
  "paymentUri": "ethereum:0x8335...2913@8453/transfer?address=0xfdb6...6048&uint256=10004217",
  "next": "Send exactly `amount` USDC on this network to `payTo`, then POST /v1/topup/crypto {\"txHash\":\"0x...\"} with the same API key."
}

2. Send the USDC

Any wallet that can send USDC on Base works. Check three things before you confirm:

CheckMust be
NetworkBase (not Ethereum mainnet, not Arbitrum, not Polygon)
TokenUSDC, contract 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Amountexactly amount from the intent

3. Claim the payment

bash
curl -s https://api.highlnd-intel.group/v1/topup/crypto \
  -H "authorization: Bearer $HIGHLAND_KEY" \
  -H "content-type: application/json" \
  -d '{"txHash": "0x5c1e...9ab2"}'
json
{ "intentId": "int_3f0c9a...", "txHash": "0x5c1e...9ab2", "credited": true, "creditCents": 1333 }

Calling claim again with the same hash is safe: it answers "credited": false, "creditCents": 0, "note": "already_credited" and adds nothing. Check the balance with GET /v1/account.

Automate it (Python, with web3.py)

python
import os, time, requests
from web3 import Web3

API = "https://api.highlnd-intel.group"
H = {"authorization": f"Bearer {os.environ['HIGHLAND_KEY']}"}
USDC_ABI = [{"name": "transfer", "type": "function", "inputs": [
    {"name": "to", "type": "address"}, {"name": "value", "type": "uint256"}],
    "outputs": [{"type": "bool"}], "stateMutability": "nonpayable"}]

intent = requests.post(f"{API}/v1/topup/crypto/intent", headers=H, json={"usd": 10}, timeout=30).json()

w3 = Web3(Web3.HTTPProvider("https://mainnet.base.org"))
acct = w3.eth.account.from_key(os.environ["WALLET_PRIVATE_KEY"])  # your own wallet, never shared
usdc = w3.eth.contract(address=Web3.to_checksum_address(intent["asset"]), abi=USDC_ABI)
tx = usdc.functions.transfer(Web3.to_checksum_address(intent["payTo"]), int(intent["amountMicro"])).build_transaction(
    {"from": acct.address, "nonce": w3.eth.get_transaction_count(acct.address)})
tx_hash = w3.eth.send_raw_transaction(acct.sign_transaction(tx).raw_transaction).hex()

for _ in range(20):                       # about 3 confirmations on Base takes ~10 seconds
    r = requests.post(f"{API}/v1/topup/crypto", headers=H, json={"txHash": tx_hash}, timeout=30)
    if r.status_code == 200:  # 409 pending_confirmations until 3 blocks
        print(r.json()); break
    time.sleep(5)

Claim errors

StatusErrorWhat to do
400invalid_tx_hashSend the full 0x + 64 hex characters.
404tx_not_foundNot mined yet or sent on another network. Retry in a minute.
404intent_not_foundNo open intent with this exact amount on this key. Use the key that made the intent.
409pending_confirmationsFewer than 3 confirmations so far (confirmations, required in the body). Wait a few seconds and retry.
409intent_already_claimed / tx_already_usedThat payment was already credited.
422tx_failedThe transaction reverted on-chain. Nothing was sent; try again from your wallet.
422no_matching_transferThe transaction did not send USDC to payTo.
422outside_intent_windowThe payment landed after the intent expired. Contact us with the hash.
429too_many_open_intentsYou have 10 unpaid intents. Pay one or wait for them to expire.

Prefer a monthly pass?

The same flow buys a monthly plan with bonus credits: use POST /v1/plans/intent {"plan":"solo"} instead of step 1.