Pay for anything with USDC. Clawallex converts your stablecoin balance into virtual cards that work at any online checkout.
refillNew user — browser signup (recommended):
bash
python3 {baseDir}/scripts/clawallex.py signup
Returns a URL and token. Show the URL to the user, ask them to open it and click Authorize. The command polls automatically. If polling fails, retry with the token:
bash
python3 {baseDir}/scripts/clawallex.py signup-check --token <token>
Existing user — connect with API keys:
Get your API Key and Secret at app.clawallex.com/dashboard/settings, then run:
bash
python3 {baseDir}/scripts/clawallex.py setup --action connect --api-key YOUR_KEY --api-secret YOUR_SECRET
bash
python3 {baseDir}/scripts/clawallex.py wallet # check balance
python3 {baseDir}/scripts/clawallex.py cards # list cards
setup --action status before any payment. If not configured: use signup for new accounts, or setup --action connect if the user already has API keys.wallet before pay or subscribe to verify sufficient funds (Mode A only).masked_pan from card-details.text
1. setup --action status → check config
2. wallet → check balance
3. pay --amount 50 --description "OpenAI" → create flash card
4. card-details --card-id <ID from step 3> → get encrypted card data
5. Decrypt PAN/CVV (HKDF + AES-256-GCM) → use ONLY for checkout form
text
1. wallet → check balance
2. subscribe --amount 100 --description "AWS billing" → create stream card
3. card-details --card-id <ID from step 2> → get card for sign-up form
4. refill --card-id <ID> --amount 50 → top up when balance is low
All commands:
text
python3 {baseDir}/scripts/clawallex.py <command> [args]
User IntentCommandQuick signup — browser-based new account creation (recommended for first-time setup)signupCheck signup result with existing tokensignup-check --token TOKENConnect accountsetup --action connect --api-key KEY --api-secret SECRETCheck config statussetup --action statusGet sign-up linksetup --action registerCheck API Key bindingwhoamiBind client_idbootstrap or bootstrap --preferred-client-id MY_ID
User IntentCommandPay for somethingpay --amount N --description "X"Pay with custom expirypay --amount N --description "X" --ttl SECONDS — flash card only; default 86400 (24 h)Start subscriptionsubscribe --amount N --description "X"Top up cardrefill --card-id CID --amount N
User IntentCommandCheck balancewalletDeposit fundsrecharge-addresses --wallet-id WIDList cardscards — returns mode_code (100=Mode A, 200=Mode B) to determine refill pathCheck card balancecard-balance --card-id CIDBatch check balancesbatch-balances --card-ids CID1,CID2 — multiple cards in one callUpdate card controlsupdate-card --card-id CID --client-request-id UUID [--tx-limit] [--allowed-mcc] [--blocked-mcc]Get card detailscard-details --card-id CID — returns masked_pan, expiry, balance, first_name, last_name, tx_limit, allowed_mcc, blocked_mcc, encrypted PAN/CVVView transactionstransactions
User IntentCommandGet x402 payee addressx402-address --chain ETH --token USDC — MUST call before Mode B Refill
When the user wants to use Clawallex for the first time:
Run setup --action status to check current configuration.
If not configured, ask: "Do you have a Clawallex account?"
Yes, have API keys: Ask for API Key and Secret, then run: text
setup --action connect --api-key KEY --api-secret SECRET
This automatically verifies credentials, binds client_id, and saves locally.
No account yet: Run the browser signup flow: text
signup
This generates a URL and a token — show the URL to the user and ask them to open it and click Authorize. The command polls automatically. If polling fails or times out, use the token to retry manually: text
signup-check --token <token from signup output>
Verify with wallet to confirm connection works.
Signup result statuses — all returned as success: true:
pending — user hasn't authorized yet, call signup-check againok — credentials saved, ready to usecancelled — user cancelled, ask if they want to try againalready_exists — account already has API keys, switch to setup --action connectMode B is for callers with self-custody wallets (agent or user) (DeFi bots, autonomous purchasing agents). The agent signs on-chain transactions using its own signing system — no human intervention needed.
Stage 1 — Quote:
text
pay --amount 200 --description "GPU rental" --mode-code 200 --chain-code ETH --token-code USDC
The 402 response is EXPECTED — it is a quote, NOT an error. Returns:
client_request_id, payee_address, asset_address, x402_reference_idfinal_card_amount, issue_fee_amount, fx_fee_amount, fee_amount, payable_amountFee structure:
fee_amount = issue_fee_amount + fx_fee_amountfee_amount = issue_fee_amount + monthly_fee_amount + fx_fee_amountAgent signs — construct and sign an EIP-3009 transferWithAuthorization using your own wallet/signing library and the quote details. Only the resulting signature and your wallet address are needed for Stage 2.
EIP-3009 enables gasless USDC transfers via off-chain signatures. The authorization fields map to:
from: your wallet address (the payer)to: payee_address from Stage 1 (system receiving address)value: maxAmountRequired (payable_amount in token minimal units, USDC = 6 decimals)validAfter / validBefore: unix timestamps (seconds) defining the signature validity windownonce: random 32-byte hex, must be unique per authorizationStage 2 — Settle (MUST use same client_request_id):
text
pay --amount 200 --description "GPU rental" \
--mode-code 200 \
--client-request-id "uuid-from-stage-1" \
--x402-version 1 \
--payment-payload '{
"scheme": "exact",
"network": "ETH",
"payload": {
"signature": "0x<agent EIP-3009 signature>",
"authorization": {
"from": "0x<agent wallet address>",
"to": "<payee_address from stage 1>",
"value": "<maxAmountRequired, e.g. 207590000>",
"validAfter": "<unix timestamp seconds>",
"validBefore": "<unix timestamp seconds>",
"nonce": "0x<random 32-byte hex>"
}
}
}' \
--payment-requirements '{
"scheme": "exact",
"network": "ETH",
"asset": "<asset_address from stage 1>",
"payTo": "<payee_address from stage 1>",
"maxAmountRequired": "<payable_amount × 10^6, e.g. 207590000>",
"extra": {
"referenceId": "<x402_reference_id from stage 1>"
}
}' \
--extra '{"card_amount": "200.0000", "paid_amount": "<payable_amount, e.g. 207.5900>"}'
Stage 2 constraints:
--client-request-id MUST be identical to Stage 1 — a different value creates a NEW orderpayment_requirements.payTo MUST equal payee_address from Stage 1payment_requirements.asset MUST equal asset_address from Stage 1payment_requirements.maxAmountRequired MUST equal payable_amount × 10^decimals (USDC = 6 decimals)payment_requirements.extra.referenceId MUST equal x402_reference_id from Stage 1extra.card_amount MUST equal the --amountextra.paid_amount MUST equal payable_amount from Stage 1 ( amount + fee_amount)payment_payload.network MUST equal payment_requirements.networkpayload.authorization.to MUST equal payment_requirements.payTopayload.authorization.value MUST equal payment_requirements.maxAmountRequiredextra.mode=STANDARD — any client-provided value is ignoredpending_payment — fix params and retry with same client_request_idMode B refill goes directly to x402 settle — no 402 challenge stage. Caller signs the EIP-3009 authorization independently using their own wallet/signing library; only the resulting signature and wallet address are submitted. Must call x402-address first to get payee_address.
text
1. x402-address --chain ETH --token USDC → get payee_address
2. refill --card-id c_123 --amount 50 \
--x402-reference-id "<unique reference id>" \
--x402-version 1 \
--payment-payload '{
"scheme": "exact",
"network": "ETH",
"payload": {
"signature": "0x<EIP-3009 signature>",
"authorization": {
"from": "0x<agent wallet>",
"to": "<payee_address from step 1>",
"value": "<amount × 10^6>",
"validAfter": "<unix seconds>",
"validBefore": "<unix seconds>",
"nonce": "0x<random 32-byte hex>"
}
}
}' \
--payment-requirements '{
"scheme": "exact",
"network": "ETH",
"asset": "<asset contract address>",
"payTo": "<payee_address from step 1>",
"maxAmountRequired": "<amount × 10^6>",
"extra": { "referenceId": "<x402_reference_id>" }
}'
Mode B refill idempotency key is x402_reference_id (not client_request_id).
Check cards mode_code to determine which refill path the card uses.
card-details returns encrypted_sensitive_data with encrypted PAN/CVV:
HKDF-SHA256(ikm=api_secret, salt=empty, info="clawallex/card-sensitive-data/v1", length=32)nonce = base64_decode(nonce), raw = base64_decode(ciphertext)encrypted_data = raw[:-16], auth_tag = raw[-16:]AES-256-GCM(key, nonce, encrypted_data, auth_tag) → JSON{"pan": "4111111111111111", "cvv": "123"}ErrorCauseAction"not configured"No credentials savedRun setup --action connect with valid credentials"Invalid credentials"Wrong API Key/SecretCheck at app.clawallex.com/dashboard/settingsInsufficient balanceWallet balance too lowRun recharge-addresses for deposit info, or use Mode B402 responseMode B Stage 1 (expected)This is the quote — proceed to Stage 2 with same client_request_idSettle rejected (Mode B)Invalid x402 paramsOrder stays pending_payment — fix params and retry with same client_request_idCard not foundWrong card_idRun cards to list valid card IDsDecryption failedBad data or apiSecret changedRe-fetch via card-details, verify credentials
All commands return JSON:
success: true → data in data field, next steps in _hintsuccess: false → error message in error fieldpay. Single-use, auto-destroyed after one transaction. Cannot be refilled.subscribe. Reloadable, top up with refill.client_id never changes. Cards and transactions are isolated per client_id. When switching to a new API Key, keep using the same client_id — the new key auto-binds on first request. Once bound, it cannot be changed (TOFU). Stored locally at ~/.clawallex/credentials.json.