X402 payment endpoint (V1)
POST/api/payment/x402V1PaymentBearer agent-jwtGet a signed x402 payment for one resource, using the agent's JWT. If the user's wallet settings require it, V1 first returns an approval link for the user. To pay without per-payment approval, use V3 with a mandate.
Request:
curl -X POST https://walletapi.fluxapay.xyz/api/payment/x402V1Payment \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $JWT_TOKEN" \
-d '{
"scheme": "exact",
"network": "base",
"amount": "10000",
"currency": "USDC",
"assetAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0xfA0eE7B2F13D80680F31771abc93D06a2C749150",
"host": "x402whois.com",
"resource": "https://x402whois.com/api/v1/whois?domain=fluxapay.xyz",
"description": "WHOIS lookup for fluxapay.xyz",
"tokenName": "USD Coin",
"tokenVersion": "2",
"validityWindowSeconds": 60
}'Request fields
Copy these fields from the resource's 402 response.
| Field | Required | Description |
|---|---|---|
scheme | Yes | exact. |
network | Yes (USDC/XRP) | base, base-sepolia (or eip155:8453 / eip155:84532), xrpl-mainnet, or fluxa-monetize-credits. |
amount | Yes | Atomic units: USDC 6 decimals, XRP drops, credits 2 decimals. |
currency | No | USDC (default), XRP, or FLUXA_MONETIZE_CREDITS. |
assetAddress | Yes (USDC) | Token contract (asset in the 402). |
payTo | Yes | Recipient address. For credits it must be monetize.fluxapay.xyz. |
host | Yes | Host of the resource you are paying for. |
resource | No | Full resource URL. |
description | No | Shown to the user. |
tokenName / tokenVersion | Yes (USDC) | EIP-712 domain from extra.name / extra.version (USD Coin / 2 for Base USDC). |
validityWindowSeconds | No | How long the signed payment stays valid. Default 60. Values are clamped to 30–300. |
approvalId | No | The approvalId from an earlier need_approval response, sent after the user has approved. |
XRP is only available where it is enabled for the wallet.
Response (200, signed)
{
"status": "ok",
"xPaymentB64": "<base64-encoded X-Payment>",
"xPayment": { "x402Version": 1, "scheme": "exact", "network": "base", "payload": { "...": "..." } },
"paymentRecordId": 12345,
"expiresAt": 1700000060,
"message": "Payment authorization signed successfully. ...",
"payment_model_context": { "instructions": "..." }
}Send xPaymentB64 as the X-Payment header and retry the original request:
curl -H "X-Payment: $X_PAYMENT_B64" \
"https://x402whois.com/api/v1/whois?domain=fluxapay.xyz"The signature expires at expiresAt. If it has expired, call the endpoint again to get a new one.
Response (approval required)
200 — the user has to approve this payment first:
{
"status": "need_approval",
"approvalId": "papr_abc12345",
"approvalUrl": "https://agentwallet.fluxapay.xyz/authorize-payment/papr_abc12345",
"expiresAt": 1730400000,
"message": "User approval required. ...",
"payment_model_context": { "instructions": "..." }
}Show approvalUrl to the user. After they approve, repeat the same request with "approvalId" added. The approval expires after about 5 minutes.
403 — the agent isn't linked to an authorized FluxA Wallet yet:
{
"status": "need_approval",
"code": "need_approval",
"message": "User approval required",
"authorizationUrl": "https://agentwallet.fluxapay.xyz/onboard/...",
"payment_model_context": { "instructions": "..." }
}Show authorizationUrl to the user, then retry.
For XRP payments the response can be status: "need_manual_signature" with an approvalUrl. The user signs the transaction in FluxA Wallet.
Errors
Error bodies look like { "status": "error" | "denied", "code", "message", "payment_model_context" }. Show payment_model_context.instructions to the model. It explains what to do next.
| HTTP | code | Meaning |
|---|---|---|
| 400 | missing_fields / invalid_amount / invalid_pay_to / invalid_currency / unsupported_network | The request body is invalid. |
| 401 | agent_auth_failed | The agent JWT is missing, invalid or expired. Refresh it. A VC token returns { "error": "wrong_token_type" }. |
| 403 | agent_not_authorized | The agent isn't authorized in the user's wallet. |
| 403 | policy_denied | Blocked by the user's spending limits. The body may include policyManagementUrl. |
| 403 | risk_control_rejected | Blocked by risk checks. |
| 403 | user_denied | The user rejected the approval. |
| 403 | approval_mismatch | The approvalId doesn't match this payment. |
| 404 | approval_not_found | Unknown approvalId. |
| 410 | approval_expired / approval_used | Start a new approval by calling again without approvalId. |
| 409 | duplicate_authorization | The same authorization was already used. Request a new one. |
| 4xx / 5xx | other | The wallet can't sign right now. Ask the user to check the agent in FluxA Wallet, then retry. |
See Error Codes.
Intent fields (optional)
You can attach a suggested mandate. FluxA uses it to prefill a mandate for the user to sign:
intentNaturalLanguage: plain-language description.intentCategory: label.intentLimitAmount: total budget in atomic units.intentValidFrom/intentValidUntil: ISO timestamps.
These fields don't change how this V1 payment is handled. For mandate-based payments, see X402 V3 payment.
