How an autonomous agent refills its prepaid SeqDesign credit balance by paying USDC on Base, over plain HTTP.
SeqDesign runs on a prepaid balance. Every job (ProteinHunter, BindCraft, Boltz, …) is billed by deducting from that balance, and a pre-flight 402 blocks a key with no credits. x402 is a way to refill the balance with USDC. It is a dedicated route, separate from job submission.
So an agent's loop is:
POST /v1/credits/topup — pay USDC once, balance goes up.The crypto handshake happens only at top-up time, never on the job hot path.
sk_live_…) — the account that gets credited.transferWithAuthorization; the facilitator submits and pays gas), so the wallet needs USDC only, no ETH.POST https://public.seq.design/v1/credits/topup
Authorization: Bearer <SEQDESIGN_API_KEY>
Content-Type: application/json
{ "amount_usd": 25 }
1 USDC = 100 credit-cents (strict 1:1). Bounded $1–$500 per request.
Step 1. Send the POST with no X-PAYMENT header. The server answers 402 with the payment terms:
{
"x402Version": 1,
"error": "X-PAYMENT header is required",
"accepts": [{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "25000000",
"resource": "https://public.seq.design/v1/credits/topup",
"payTo": "0x5Cf5bBF765F7e281493549D0fe88397E7b34a58c",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"maxTimeoutSeconds": 120,
"extra": { "name": "USD Coin", "version": "2" }
}]
}
maxAmountRequired is the atomic USDC amount to pay ($25 → 25000000); use it verbatim. payTo is the SeqDesign receiving wallet; asset is Base-mainnet USDC. A 503 here means x402 is disabled server-side; a 401 means the API key is invalid.
Step 2. EIP-712-sign an EIP-3009 TransferWithAuthorization with the payer key:
| Field | Value |
|---|---|
| domain | { name: extra.name, version: extra.version, chainId: 8453, verifyingContract: asset } (Base = 8453; Base Sepolia = 84532) |
| types.TransferWithAuthorization | from, to, value, validAfter, validBefore (uint256), nonce (bytes32) |
| message | from=payer, to=payTo, value=maxAmountRequired, validAfter=0, validBefore=now+maxTimeoutSeconds, nonce=random 32 bytes |
Step 3. Resend the same POST with an X-PAYMENT header — base64 of:
{
"x402Version": 1,
"scheme": "exact",
"network": "base",
"payload": {
"signature": "0x<65-byte sig>",
"authorization": {
"from": "0x<payer>",
"to": "0x5Cf5bBF765F7e281493549D0fe88397E7b34a58c",
"value": "25000000",
"validAfter": "0",
"validBefore": "<unix>",
"nonce": "0x<32 bytes hex>"
}
}
}
Success is 200:
{ "data": { "credited": true, "amount_cents": 2500, "balance_cents": 2500,
"transaction": "0x<settlement tx>", "network": "base" } }
The grant is idempotent on the settlement transaction hash, so a replayed X-PAYMENT can never double-credit.
Nothing special. Submit jobs with the same API key; each run deducts from the balance, and a pre-flight 402 blocks a run the balance can't cover. The only thing an agent has to manage is keeping the balance topped up.
The signing is standard EIP-712, so any Ethereum library works (viem/ethers in JS, eth_account in Python). A working Python client (topup() + the three steps + spend caps) is available on request.