Skip to content

Mandates & x402 payments ​

A mandate is a spending budget the user signs in their FluxA Wallet: a description, a currency, a limit and a time window. Once it's signed, the agent can pay inside it with no further prompts: x402 APIs, payouts, agent-card funding, AgentMarket topups. The wallet enforces the limit and the window.

text
1. fluxa-wallet mandates                          → reuse a signed mandate if one fits
2. fluxa-wallet mandate-create --desc ... --amount ...
3. user opens authorizationUrl and signs
4. fluxa-wallet mandate-status --id <mandateId>   → wait for "signed"
5. fluxa-wallet x402 --mandate <mandateId> --payload <402 payload>
6. retry the API request with the returned payment header

Plan mandates around the whole task, not each call. Pay-per-call APIs cost very little, so one budget covering many calls (for example about 100) saves the user from approving every request. Always say what the budget is for and get the user's agreement first.

mandate-create ​

Creates a mandate draft and returns the URL where the user signs it.

bash
fluxa-wallet mandate-create \
  --desc "Spend up to 1 USDC on social-search API calls for 14 days" \
  --amount 1000000 \
  --seconds 1209600
FlagTypeRequiredDefaultDescription
--descstringYes—Plain-language description the user sees when signing
--amountinteger, atomic unitsYes—Budget limit. USDC/XRP: 6 decimals (1000000 = 1). Credits: 2 decimals (500 = 5 credits). CARD_USD: cents
--secondsinteger > 0No28800 (8 h)How long the mandate stays valid
--categorystringNogeneralFree-form category tag
--currencystringNoUSDCUSDC, XRP, FLUXA_MONETIZE_CREDITS, or CARD_USD (linked card, Beta)

--currency is not case-sensitive and accepts these aliases: credits, fluxa-monetize-credits, fluxa-monetize-credit for Monetize Credits; card, card-usd for CARD_USD. The merchant flags (--merchant-name, --merchant-url, --merchant-country, --transaction-ref, --ext) work only with CARD_USD and are covered on Linked card.

json
{
  "success": true,
  "data": {
    "status": "ok",
    "mandateId": "mand_xxxxxxxxxxxxx",
    "authorizationUrl": "https://wallet.fluxapay.xyz/onboard/intent?oid=...",
    "expiresAt": "2026-10-27T18:00:00.000Z"
  }
}

Give the user the complete authorizationUrl as a clickable link and tell them they need to approve it. The mandate can't be used until it's signed.

ErrorWhat to do
Missing required parameters: --desc, --amountSupply both. Both are always required
Amount must be a positive integer (atomic units)No decimals: convert to atomic units first
Unsupported currency: "..."Use one of the listed currencies or aliases
Seconds must be a positive integerPass a whole number of seconds
Merchant flags are only valid with --currency CARD_USDDrop the merchant flags, or set --currency CARD_USD

mandate-status ​

Shows one mandate's status, limit and remaining budget.

bash
fluxa-wallet mandate-status --id mand_xxxxxxxxxxxxx
FlagTypeRequiredDescription
--idstringYesMandate ID. Use --id, not --mandate
json
{
  "success": true,
  "data": {
    "status": "ok",
    "mandate": {
      "mandateId": "mand_xxxxxxxxxxxxx",
      "status": "signed",
      "naturalLanguage": "Spend up to 1 USDC on social-search API calls for 14 days",
      "currency": "USDC",
      "limitAmount": "1000000",
      "spentAmount": "0",
      "remainingAmount": "1000000",
      "validFrom": "2026-10-27T10:00:00.000Z",
      "validUntil": "2026-11-10T10:00:00.000Z"
    }
  }
}

Output trimmed. The mandate is ready to use once mandate.status is signed. Until then it is awaiting the user's approval: send them the authorizationUrl again.

x402 ​

Signs a payment for an HTTP 402 Payment Required response, using a signed mandate. x402 and x402-v3 are the same command and accept the same flags.

bash
fluxa-wallet x402 --mandate mand_xxxxxxxxxxxxx --payload "$PAYLOAD"
FlagTypeRequiredDescription
--mandatestringYesA signed mandate ID
--payloadJSON string, or base64-encoded JSONYesThe complete 402 payment requirements, unmodified

What to pass as --payload ​

The CLI supports both x402 payload formats and detects which one it has from the payload itself:

The 402 response…Pass as --payloadRetry headerToken field in output
has a PAYMENT-REQUIRED header (x402 v2)The header value as-is (base64)PAYMENT-SIGNATUREdata.paymentPayloadB64
has the requirements in the JSON body (x402 v1)The full response bodyX-Paymentdata.xPaymentB64

Pass the whole payload, accepts array included. Don't pick out individual fields.

For a v1 payload, the CLI uses the accepts entry whose currency matches the mandate. So if an API accepts both USDC and credits, a USDC mandate pays in USDC. For a v2 payload, the wallet picks the asset.

v1 output:

json
{
  "success": true,
  "data": {
    "status": "ok",
    "xPaymentB64": "eyJ4NDAyVmVyc2lvbiI6...",
    "paymentRecordId": 123,
    "expiresAt": 1761500060
  }
}

v2 output:

json
{
  "success": true,
  "data": {
    "status": "ok",
    "paymentPayloadB64": "eyJ4NDAyVmVyc2lvbiI6...",
    "paymentRecordId": 42,
    "expiresAt": 1761500300
  }
}

End-to-end script ​

bash
API_URL="https://api.example.com/paid-endpoint"
MANDATE_ID="mand_xxxxxxxxxxxxx"

RESP=$(curl -s -D /tmp/x402_headers -w "\n%{http_code}" "$API_URL")
CODE=$(echo "$RESP" | tail -n1)
BODY=$(echo "$RESP" | sed '$d')

if [ "$CODE" = "402" ]; then
  PR=$(grep -i '^payment-required:' /tmp/x402_headers | sed 's/^[^:]*: *//' | tr -d '\r')
  if [ -n "$PR" ]; then
    PAYLOAD="$PR"; HEADER="PAYMENT-SIGNATURE"; FIELD="paymentPayloadB64"
  else
    PAYLOAD="$BODY"; HEADER="X-Payment"; FIELD="xPaymentB64"
  fi
  TOKEN=$(fluxa-wallet x402 --mandate "$MANDATE_ID" --payload "$PAYLOAD" | jq -r ".data.$FIELD")
  curl -s -H "$HEADER: $TOKEN" "$API_URL"
fi

Errors ​

ErrorWhat to do
Missing required parameters: --mandate, --payloadCreate and sign a mandate first, then pass both flags
Invalid --payload: not valid JSON or base64-encoded JSONPass the body or header exactly as received
Invalid payload: missing accepts arrayPass the complete payload, not a single accepts entry
Invalid v2 payload: missing resource.urlThe v2 payload is incomplete. Pass the full PAYMENT-REQUIRED value
No accepts entry matches mandate currency "..."The API doesn't accept the mandate's currency. Create a mandate in one of the listed currencies
mandate_not_signedThe mandate is awaiting approval. Send the user the authorizationUrl
mandate_expiredThe time window has passed. Create a new mandate
mandate_budget_exceeded / mandate_insufficient_budgetNot enough budget left for this payment. Create a new mandate with a higher limit
mandate_not_foundWrong ID, or the mandate belongs to a different agent. Mandates belong to the agent that created them

See also: x402 Payment guide.

Released under the MIT License.