Install
openclaw skills install clawallexPay for anything with USDC — virtual cards for any online checkout
openclaw skills install clawallexPay for anything with USDC. Clawallex converts your stablecoin balance into virtual cards that work at any online checkout.
refillNew user — browser signup (recommended):
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:
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:
python3 {baseDir}/scripts/clawallex.py setup --action connect --api-key YOUR_KEY --api-secret YOUR_SECRET
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.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
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:
python3 {baseDir}/scripts/clawallex.py <command> [args]
| User Intent | Command |
|---|---|
| Quick signup — browser-based new account creation (recommended for first-time setup) | signup |
| Check signup result with existing token | signup-check --token TOKEN |
| Connect account | setup --action connect --api-key KEY --api-secret SECRET |
| Check config status | setup --action status |
| Get sign-up link | setup --action register |
| Check API Key binding | whoami |
| Bind client_id | bootstrap or bootstrap --preferred-client-id MY_ID |
| User Intent | Command |
|---|---|
| Pay for something | pay --amount N --description "X" |
| Pay with custom expiry | pay --amount N --description "X" --ttl SECONDS — flash card only; default 86400 (24 h) |
| Start subscription | subscribe --amount N --description "X" |
| Top up card | refill --card-id CID --amount N |
| User Intent | Command |
|---|---|
| Check balance | wallet |
| Deposit funds | recharge-addresses --wallet-id WID |
| List cards | cards — returns mode_code (100=Mode A, 200=Mode B) to determine refill path |
| Check card balance | card-balance --card-id CID |
| Batch check balances | batch-balances --card-ids CID1,CID2 — multiple cards in one call |
| Update card controls | update-card --card-id CID --client-request-id UUID [--tx-limit] [--allowed-mcc] [--blocked-mcc] |
| Get card details | card-details --card-id CID — returns masked_pan, expiry, balance, first_name, last_name, tx_limit, allowed_mcc, blocked_mcc, encrypted PAN/CVV |
| View transactions | transactions |
| User Intent | Command |
|---|---|
| Get x402 payee address | x402-address --chain ETH --token USDC — MUST call before Mode B Refill |
When the user wants to use Clawallex for the first time:
setup --action status to check current configuration.setup --action connect --api-key KEY --api-secret SECRET
This automatically verifies credentials, binds client_id, and saves locally.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:
signup-check --token <token from signup output>
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:
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):
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.
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"}| Error | Cause | Action |
|---|---|---|
| "not configured" | No credentials saved | Run setup --action connect with valid credentials |
| "Invalid credentials" | Wrong API Key/Secret | Check at app.clawallex.com/dashboard/settings |
| Insufficient balance | Wallet balance too low | Run recharge-addresses for deposit info, or use Mode B |
| 402 response | Mode B Stage 1 (expected) | This is the quote — proceed to Stage 2 with same client_request_id |
| Settle rejected (Mode B) | Invalid x402 params | Order stays pending_payment — fix params and retry with same client_request_id |
| Card not found | Wrong card_id | Run cards to list valid card IDs |
| Decryption failed | Bad data or apiSecret changed | Re-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.