We resell Cryptorefills products to AI agents over x402, fulfilled through x402.cryptorefills.com on Base. Our first mainnet purchase on 2026-09-13 used the official @x402/core and @x402/evm SDK at 2.25.0, and it hit two compatibility issues. We worked around both on our side. Posting here in case the fix belongs upstream and to help others who run into the same errors.
1. PAYMENT-REQUIRED says x402Version: 2, but its requirements use the V1 shape
POST /v1/orders (with X-Preferred-Network: base) returns a challenge whose accepts[] entries look like this:
{
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"maxAmountRequired": "590000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x…",
"extra": { "name": "USD Coin", "version": "2", "decimals": 6 }
}],
"resource": "…",
"expiresAt": "…"
}
Compared with the V2 PaymentRequirements in the x402 spec:
maxAmountRequired is the V1 field name. V2 uses amount.
maxTimeoutSeconds is missing.
What happens with the SDK at 2.25.0:
x402Client.createPaymentPayload() throws Invalid amount: undefined — use decimal notation. The spend controls added in 2.23 read amount.
- After copying the value into
amount, EIP-3009 signing throws Cannot convert NaN to a BigInt, because validBefore is computed from maxTimeoutSeconds.
Suggested fix: include amount and maxTimeoutSeconds in V2 challenges. Keeping maxAmountRequired alongside would stay backward compatible.
2. The SDK's PAYMENT-SIGNATURE header is rejected
The header produced by x402HTTPClient.encodePaymentSignatureHeader() is standard base64 of the full V2 PaymentPayload, including accepted and resource. Retrying POST /v1/orders with it returns:
400 {"error":"processing_error","message":"Invalid PAYMENT-SIGNATURE: Failed to decode PAYMENT-SIGNATURE header"}
What the endpoint does accept is the same wrapper as the Solana flow: base64url of
{ "x402Version": 2, "scheme": "exact", "network": "eip155:8453", "payload": { "authorization": { … }, "signature": "0x…" } }
We haven't isolated whether the decoder fails on the alphabet (base64 vs base64url) or on the extra V2 fields. Either way, a stock x402 V2 client can't pay this endpoint without a custom encoder.
Suggested fix: accept the standard V2 PaymentPayload: standard base64, with accepted and resource present.
3. Minor: gift cards and eSIMs also require beneficiary_account
Omitting beneficiary_account for a non-mobile product returns {"error":"processing_error","message":"item.beneficiary_account is required"}. We expected it to be optional there, since the voucher goes to email. Either documenting that it's required for every item, or defaulting it to email, would help agents get this right on the first try.
Environment: Node 22, @x402/core and @x402/evm 2.25.0, Base mainnet USDC. Happy to test a fix. Contact: info@hfsp.xyz
We resell Cryptorefills products to AI agents over x402, fulfilled through
x402.cryptorefills.comon Base. Our first mainnet purchase on 2026-09-13 used the official@x402/coreand@x402/evmSDK at 2.25.0, and it hit two compatibility issues. We worked around both on our side. Posting here in case the fix belongs upstream and to help others who run into the same errors.1.
PAYMENT-REQUIREDsaysx402Version: 2, but its requirements use the V1 shapePOST /v1/orders(withX-Preferred-Network: base) returns a challenge whoseaccepts[]entries look like this:{ "x402Version": 2, "accepts": [{ "scheme": "exact", "network": "eip155:8453", "maxAmountRequired": "590000", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "payTo": "0x…", "extra": { "name": "USD Coin", "version": "2", "decimals": 6 } }], "resource": "…", "expiresAt": "…" }Compared with the V2
PaymentRequirementsin the x402 spec:maxAmountRequiredis the V1 field name. V2 usesamount.maxTimeoutSecondsis missing.What happens with the SDK at 2.25.0:
x402Client.createPaymentPayload()throwsInvalid amount: undefined — use decimal notation. The spend controls added in 2.23 readamount.amount, EIP-3009 signing throwsCannot convert NaN to a BigInt, becausevalidBeforeis computed frommaxTimeoutSeconds.Suggested fix: include
amountandmaxTimeoutSecondsin V2 challenges. KeepingmaxAmountRequiredalongside would stay backward compatible.2. The SDK's
PAYMENT-SIGNATUREheader is rejectedThe header produced by
x402HTTPClient.encodePaymentSignatureHeader()is standard base64 of the full V2PaymentPayload, includingacceptedandresource. RetryingPOST /v1/orderswith it returns:What the endpoint does accept is the same wrapper as the Solana flow: base64url of
{ "x402Version": 2, "scheme": "exact", "network": "eip155:8453", "payload": { "authorization": { … }, "signature": "0x…" } }We haven't isolated whether the decoder fails on the alphabet (base64 vs base64url) or on the extra V2 fields. Either way, a stock x402 V2 client can't pay this endpoint without a custom encoder.
Suggested fix: accept the standard V2
PaymentPayload: standard base64, withacceptedandresourcepresent.3. Minor: gift cards and eSIMs also require
beneficiary_accountOmitting
beneficiary_accountfor a non-mobile product returns{"error":"processing_error","message":"item.beneficiary_account is required"}. We expected it to be optional there, since the voucher goes toemail. Either documenting that it's required for every item, or defaulting it toemail, would help agents get this right on the first try.Environment: Node 22,
@x402/coreand@x402/evm2.25.0, Base mainnet USDC. Happy to test a fix. Contact: info@hfsp.xyz