X402 E2E Validation and Troubleshooting
X402 involves HTTP, SDK, signatures, Facilitator, and on-chain transactions. When troubleshooting signature or settlement issues, it is recommended to confirm layer by layer in the order of “public entry point -> 402 response -> SDK payment handler -> on-chain settlement”. This tutorial explains how to check each layer and lists common errors.
¶ Check the public entry point
Facilitator capability declaration:
curl https://facilitator.acedata.cloud/.well-known/x402
If it returns facilitator, supportedKinds, and protocol endpoints, the capability metadata is normal. API resource discovery has been retired; please call the target API directly and use the real-time 402 response as the source of truth.
Facilitator supported capabilities:
curl https://facilitator.acedata.cloud/supported
If it returns kinds, the Facilitator entry point is normal.
¶ Check 402 accepts
Send a non-authenticated request that will not incur charges:
curl -sS -X POST https://x402.acedata.cloud/openai/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "hi"}],
"max_tokens": 1
}'
Check whether the returned accepts contains the network you want to use. network is a CAIP-2 identifier:
eip155:8453+exact(Base)eip155:8453+upto(Base, post-metering)eip155:1187947933+exact(SKALE)solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp+exact(Solana)
If the target network is not present, it means that the API or current environment has not configured the corresponding X402 payment method.
¶ Run the X402Client advanced validation tools
The X402Client repository provides advanced validation tools that can be used to confirm 402 response selection, signature generation, paid retry, and on-chain settlement. They require a funded wallet, RPC, private key, and development dependencies. For normal business integration, it is recommended to prioritize the TypeScript or Python SDK; only run these tools when you need to identify signature or on-chain settlement issues.
Repository address: https://github.com/AceDataCloud/X402Client
git clone https://github.com/AceDataCloud/X402Client.git
cd X402Client/typescript
npm install
npm install --no-save ethers @solana/spl-token bs58 tsx
Base:
export X402B_BASE_PAYER_PRIVATE_KEY=0x...
TEST_API_PATH='/openai/chat/completions' \
TEST_BODY='{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hi"}],"max_tokens":10}' \
npx tsx scripts/test-real-e2e.ts
SKALE:
export SKALE_BASE_PRIVATE_KEY=0x...
TEST_API_PATH='/openai/chat/completions' \
TEST_BODY='{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hi"}],"max_tokens":10}' \
npx tsx scripts/test-skale-e2e.ts
Solana:
export X402B_SOLANA_PAYER_PRIVATE_KEY=...
npx tsx scripts/test-solana-e2e.ts
The validation tools usually print:
- The 402 response from the first request.
- The selected payment requirement.
- The signed
PAYMENT-SIGNATUREsummary. - The HTTP status and response body after retry.
- The on-chain settlement transaction, or the Facilitator error reason when it fails.
Do not send private keys or complete PAYMENT-SIGNATURE values to logging systems or support tickets.
Example public API validation results:
SKALE exact
HTTP 402 -> HTTP 200
content ADC_SKALE_E2E_OK
tx 0x9fd09901e74c763325fe118b2bc64765c3fca785b86b24a78b97964384db084f
block 1969317
explorer https://skale-base-explorer.skalenodes.com/tx/0x9fd09901e74c763325fe118b2bc64765c3fca785b86b24a78b97964384db084f
paid 0.095215 USDC
Base exact
HTTP 402 -> HTTP 200
content ADC_BASE_E2E_OK
tx 0x408430ab3451bc22a51e510cdb4b063d6b9686724fea7a31fc109af20f5cd2f3
block 46726299
explorer https://basescan.org/tx/0x408430ab3451bc22a51e510cdb4b063d6b9686724fea7a31fc109af20f5cd2f3
transfer value 95215 atomic USDC
Solana exact
HTTP 402 -> HTTP 200
content ADC_SOLANA_E2E_OK
chain signature not confirmed in this run because public RPC lookup hit 429
Base upto
HTTP 402 -> HTTP 200
content ADC_BASE_UPTO_OK
tx 0x4b0b836ce1cd1171cdbc37df1637150b024214ec28e7f6f2d09122f15cbfc036
block 46726437
explorer https://basescan.org/tx/0x4b0b836ce1cd1171cdbc37df1637150b024214ec28e7f6f2d09122f15cbfc036
signed ceiling 95215 atomic USDC
transfer value 3 atomic USDC
Explanation:
- SKALE
exact, Baseexact, Solanaexact, and Baseuptoall completed the paid retry from HTTP 402 to HTTP 200. - The on-chain transaction for SKALE
exactcan be found in the SKALE explorer, and the settlement amount is0.095215USDC. - The on-chain transaction for Base
exactcan be found in BaseScan, and the settlement amount is95215atomic USDC. - The signed ceiling for Base
uptois95215atomic USDC, but the actual on-chain settlement is3atomic USDC, indicating that post-metering charges based on actual usage. - The Solana path has confirmed paid retry and model output. Public RPC may be rate-limited; when strict on-chain reconciliation is required, please use your own Solana RPC or confirm the transaction signature through platform-side settlement records.
¶ SDK smoke test
Advanced validation tools are used to check signatures and on-chain settlement. On the business side, an SDK smoke test should also be performed to confirm that application code can automatically handle 402 through the payment handler. Only the core snippets are shown below; complete code needs to include the wallet, provider, and imports.
TypeScript:
const client = new AceDataCloud({
paymentHandler: createX402PaymentHandler({
network: 'skale',
evmProvider,
evmAddress: wallet.address
})
});
const res = await client.openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'Reply with exactly ADC_SDK_X402_OK' }],
max_tokens: 8
});
Python:
client = AceDataCloud(
payment_handler=create_x402_payment_handler(
network="skale",
evm_signer=signer,
)
)
res = client.openai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Reply with exactly ADC_PY_X402_OK"}],
max_tokens=8,
)
If the model returns the fixed string as requested, it means that the SDK, payment handler, Gateway, Facilitator, and target API are connected end to end.
The two smoke tests above use SKALE exact. SKALE currently only provides exact, which settles at the fixed amount quoted by 402 and will not decrease based on actual token usage. Chat completions are a token-metered scenario; for production integration, it is recommended to switch to Base and pass preferScheme: 'upto', settling based on actual usage.
SDK smoke test program results:
TypeScript SDK
payer 0xd0479FA9FD8C678303d477433d24C15e3723CC1C
elapsed_ms 6782
content ADC_TS_SDK_X402_OK
id chatcmpl-DlcVLO4PQWvmjPDQpy9yQw2QdLGAT
Python SDK
payer 0xd0479FA9FD8C678303d477433d24C15e3723CC1C
elapsed_ms 4786
content ADC_PY_SDK_X402_OK
id chatcmpl-DlcWajqAHOop3iebmO19XRfT5bTPz
Result details:
- The TypeScript SDK automatically handles 402, signing, and retries through
createX402PaymentHandler, and ultimately receivesADC_TS_SDK_X402_OK. - The Python SDK completes the same flow through
create_x402_payment_handler, and ultimately receivesADC_PY_SDK_X402_OK. - Both smoke tests use the SKALE payer
0xd0479FA9FD8C678303d477433d24C15e3723CC1C. - The Python SDK response object is a
dict; the content can be read in the example usingres["choices"][0]["message"]["content"].
¶ Order Payment E2E
Order payment uses the platform API of platform.acedata.cloud and requires a platform account token. The complete flow is: create a Pending order, trigger 402 with POST /api/v1/orders/{order_id}/pay/, then retry with PAYMENT-SIGNATURE.
Example of small order payment verification results:
The transaction records below are historical real-world test samples under the old policy; the amounts and transaction hashes are retained as-is. New X402 orders no longer have payment method discounts; use the
amountin the current 402 response as the basis for signing and payment.
created order 78481793-304e-47f7-bc0c-8231aec9cc1e
created state Pending
created price 1.26
http_status=402
x402Version 2
accepts [('eip155:8453', 'exact', '1200000'), ('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'exact', '1200000')]
status 200
order state Finished
pay_way X402
pay_id 0xfec08cc00a159ea1ec692b32faa9bf3d17595a986301169e689d94f58bc44151
settle_header {'success': True, 'network': 'base', 'transaction': '0xfec08cc00a159ea1ec692b32faa9bf3d17595a986301169e689d94f58bc44151'}
Base tx status 1
block 46726704
explorer https://basescan.org/tx/0xfec08cc00a159ea1ec692b32faa9bf3d17595a986301169e689d94f58bc44151
transfer value 1200000 atomic USDC
Result details:
- After creating the order, the order status is
Pending, and the price is1.26. - The first
pay/request returns HTTP 402.acceptscontains Baseexactand Solanaexact, both with an amount of1200000atomic USDC. - Retrying with the Base
PAYMENT-SIGNATUREreturns HTTP 200, the order status changes toFinished, andpay_wayisX402. - After decoding
PAYMENT-RESPONSE, it showssuccess=True,network=base, and provides the same transaction hash. - The transaction status on BaseScan is
1, and the transfer amount is1200000atomic USDC, which is1.2USDC. - The creation price of
1.26was paid during the old X402 payment discount policy, and the final signed and settled amount was1.2USDC.
If order payment does not include Authorization: Bearer {platform_token}, or the order does not belong to the current account, it will fail at the platform permission layer; this differs from the account-free X402 API that directly calls x402.acedata.cloud.
¶ Common Errors
| Symptom | Troubleshooting Direction |
|---|---|
| The first request is not 402 | Check whether Authorization was included by mistake, or whether the API does not yet have X402 pricing. |
No payment requirement for network |
The target network is not in accepts; switch networks or check the Gateway configuration. |
invalid_402 |
The 402 response is not valid JSON; check the proxy, gateway, or error page. |
Authorization nonce already processed |
The same PAYMENT-SIGNATURE was reused; sign again. |
invalid_upto_evm_payload_invalid_signature |
Check whether the upto chainId, Permit2 domain, facilitator address, and signing account are consistent. |
PERMIT2_ALLOWANCE_REQUIRED |
Execute approve-permit2 for USDC on the target chain. |
Payer has insufficient USDC balance |
The payment wallet has insufficient USDC. |
| HTTP 200 but no tx hash | The actual upto amount may be 0, or the settlement record is still being written asynchronously. |
Solana Missing transaction payload |
There is no serialized transaction or signature in the PAYMENT-SIGNATURE envelope; check the wallet adapter. |
¶ Base upto Checklist
upto is currently only available on Base (eip155:8453). SKALE only provides exact. Because an upto signature binds more EVM typed data parameters, during integration you should specifically confirm that the real-time fields in the 402 response are fully consistent with the client signature.
SKALE exact
HTTP 402 -> HTTP 200
content ADC_SKALE_E2E_OK
tx 0x9fd09901e74c763325fe118b2bc64765c3fca785b86b24a78b97964384db084f
Base upto
HTTP 402 -> HTTP 200
content ADC_BASE_UPTO_OK
tx 0x4b0b836ce1cd1171cdbc37df1637150b024214ec28e7f6f2d09122f15cbfc036
explorer https://basescan.org/tx/0x4b0b836ce1cd1171cdbc37df1637150b024214ec28e7f6f2d09122f15cbfc036
signed ceiling 95215 atomic USDC
transfer value 3 atomic USDC
If Base upto returns invalid_upto_evm_payload_invalid_signature, prioritize checking:
extra.chainIdin theeip155:8453+uptoentry returned by the API (should be8453).- The
extra.facilitatorAddressreturned by the API. - The Base
uptofacilitator address returned byhttps://facilitator.acedata.cloud/supported. - The Permit2 domain, spender, USDC contract, and signing account.
- Whether the wallet has already approved Permit2 for Base USDC.
The upto signing digest simultaneously binds the Permit2 domain, chain ID, spender, recipient address, facilitator address, and validAfter. If any item is inconsistent, the Facilitator will recover an incorrect signer, resulting in an invalid signature. If all of these are consistent but it still returns 402, check the Permit2 allowance next; when unauthorized, it returns PERMIT2_ALLOWANCE_REQUIRED.
¶ Save Verification Information
A complete verification must save at least:
- API path and request body summary;
- selected network and scheme;
maxAmountRequired;- payer wallet address;
- HTTP final status;
- model output or task ID in the response;
- settlement transaction link;
- Gateway trace ID or platform usage record ID.
Do not save private keys, complete PAYMENT-SIGNATURE, complete EIP-712 signature, or mnemonic phrase.
¶ Structured Payment Errors
Signed X402 failures will return stable code, safe interpolation parameters, stage, and retry flag in extensions.acedatacloud.paymentError. Prioritize using this structure for troubleshooting; do not parse the top-level English error, and do not ask users to provide wallet signatures or original on-chain simulation text.
charged: false: verification was explicitly rejected before settlement, and no charge was initiated this time.- No
charged: the result is unknown or has entered the settlement stage; check the order and on-chain status first, and do not directly repeat payment. settlement_pending: do not repeat payment for now; refresh the order first or contact support.- Unrecognized code: handle it as
payment_failed, and retain the public technical code for customer service lookup.
