Programmatic top-up

Pay-per-use with x402

An agent or script can buy prepaid inference credit by paying USDC over x402 — no account, no card, no dashboard. The endpoint returns a standard OpenAI-compatible key preloaded with that balance, which then meters per call like any other key.

When to use this

The normal way to fund a key is the dashboard top-up (card, one-time or auto-recharge). This page is for the other case: a program that needs to provision its own credit without a human in the loop — an autonomous agent, a CI job, a backend that spins up workers. It pays a fixed USDC amount and gets a working key back in one request.

Everything downstream is unchanged: the key calls the same https://api.quicksilverpro.io/v1 endpoint, the same models, at the same per-token pricing. x402 is only how the balance is funded.

How it works

  • Request credit. POST to the top-up endpoint for the amount you want. Unpaid, it answers 402 Payment Required with the payment details.
  • Pay. An x402 client signs an authorization to transfer that many USDC and retries. You only need USDC on Base — the facilitator broadcasts the transfer and covers the gas, so the payer wallet needs no ETH.
  • Receive a key. Once the payment settles on chain, the endpoint returns JSON with an api_key and api_base, preloaded with the amount you paid.
  • Call the API. Point any OpenAI-compatible client at api_base with that key. Per-call cost is metered against the prepaid balance.

The full flow

End to end, from a wallet that holds only USDC to a working key and the first metered call. Steps (1)–(8) are the x402 handshake; (9)–(11) are ordinary API calls against the prepaid balance.

text
AGENT                      pay.quicksilverpro.io    x402 FACILITATOR      BASE CHAIN
(private key + USDC only)   (seller)                 (pays the gas)        (eip155:8453)
   │                            │                        │                    │
   │ (1) POST /x402/topup/1     │                        │                    │
   │     (bare request)         │                        │                    │
   ├───────────────────────────►│                        │                    │
   │                            │                        │                    │
   │ (2) 402 Payment Required   │                        │                    │
   │     PAYMENT-REQUIRED: <b64>│                        │                    │
   │◄───────────────────────────┤                        │                    │
   │     decodes to:
   │       { x402Version: 2,
   │         accepts: [{ scheme: "exact", network: "eip155:8453",
   │                     asset:  "0x8335…2913" (USDC),
   │                     amount: "1000000" ($1),
   │                     payTo:  "0x9fF2…f9b9",
   │                     maxTimeoutSeconds: 300 }] }
   │                            │                        │                    │
   │ (3) local decision (offline — no network call)
   │       · known chain?      eip155:8453   ok
   │       · asset is USDC?                   ok
   │       · $1 ≤ my spend cap?               ok   ← client spend policy here
   │       · balance enough?                  ok
   │                            │                        │                    │
   │ (4) sign an EIP-3009 authorization
   │       transferWithAuthorization(from: me, to: payTo,
   │         value: 1000000, validBefore: now+300, nonce: random)
   │       offline signature only — not on chain, no gas, nothing charged yet
   │                            │                        │                    │
   │ (5) resend the same request│                        │                    │
   │     PAYMENT-SIGNATURE: <b64 signed>
   ├───────────────────────────►│                        │                    │
   │                            │ (6) verify(payload)    │                    │
   │                            ├───────────────────────►│                    │
   │                            │◄──────── ok ───────────┤                    │
   │                            │ (7) settle(payload)    │                    │
   │                            ├───────────────────────►│ broadcast (pays gas)
   │                            │                        ├───────────────────►│
   │                            │                        │◄── 2–4s confirm ───┤
   │                            │◄─────── txHash ────────┤   $1 USDC received
   │                            │                        │                    │
   │ (8) 200 OK                 │                        │                    │
   │     PAYMENT-RESPONSE: txHash
   │     { api_key: "sk-…", credit_usd: 1,
   │       api_base: "https://api.quicksilverpro.io/v1" }
   │◄───────────────────────────┤                        │                    │
   │
   │  ── x402 ends here. Everything below is a plain API call, no chain. ──
   │
   │ (9) POST api.quicksilverpro.io/v1/chat/completions   ← different host now
   │     Authorization: Bearer sk-…
   │     { model: "qwen3.8-max", messages: [ … ] }
   │                            │
   │ (10) 200 + answer + usage  │  metered from the $1 balance
   │◄───────────────────────────┤  ($2 / 1M input, $6 / 1M output)
   │                            │
   │ (11) balance spent → back to (1)

Endpoint

http
POST https://pay.quicksilverpro.io/x402/topup/{amount}

amount    1, 5, or 10   (USD of prepaid credit)
network   Base (eip155:8453)
asset     USDC

The endpoint follows the x402 open standard, so any x402-aware client works. The example below uses the reference Python client.

Example (Python)

shell
pip install 'x402[evm,httpx]' eth_account
python
import asyncio, os
from eth_account import Account
from x402 import x402Client
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
from x402.http.clients import x402HttpxClient

# A wallet holding USDC on Base. No ETH needed — the facilitator pays gas.
account = Account.from_key(os.environ["EVM_PRIVATE_KEY"])

client = x402Client()
register_exact_evm_client(client, EthAccountSigner(account), networks="eip155:8453")

async def buy_credit(amount=1):
    url = f"https://pay.quicksilverpro.io/x402/topup/{amount}"
    # The client handles the 402 -> sign -> retry handshake for you.
    async with x402HttpxClient(client, timeout=120) as http:
        resp = await http.post(url)
        await resp.aread()
        return resp.json()   # {"api_key": "sk-...", "credit_usd": 1, "api_base": "..."}

print(asyncio.run(buy_credit()))

The response

On a settled payment you get:

json
{
  "api_key": "sk-...",
  "credit_usd": 1,
  "api_base": "https://api.quicksilverpro.io/v1",
  "note": "OpenAI-compatible. Set base_url to api_base and use this key as the API key."
}

Use it exactly like any other QuickSilver Pro key:

shell
curl https://api.quicksilverpro.io/v1/chat/completions \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{"model": "deepseek-v4-flash",
       "messages": [{"role": "user", "content": "hello"}]}'

Good to know

  • The key is a one-time prepaid balance (the amount you paid), not a subscription — it does not reset. Top up again for more.
  • Each payment is settled at most once; a repeated request for the same authorization is rejected rather than double-charged.
  • If a payment settles but you lose the response, the balance is safe — email hello@quicksilverpro.io with the settlement transaction hash and we'll return the key.