X402 Order Payment Tutorial
In addition to directly paying via API requests, Ace Data Cloud also supports paying for orders through the X402 payment console. The core protocol for order payment and API calls is the same: the first request returns 402, the client checks out X-Payment, and then retries the same request.
The difference is that order payment belongs to the platform API and requires an account token; whereas directly calling the AI API at api.acedata.cloud can be done using only X402, without needing an API Token.
¶ Prepare the Order
Go to the Ace Data Cloud Console, select the order you need to pay for, and record the order ID.
If you do not have an order yet, you can create a pending payment order on the package page. The order price is based on what is displayed on the page, and the maxAmountRequired in the X402 402 response is the final basis for signing.
¶ Create Account Token
The order payment request requires an account token. Open the Platform Token Page and create a token in the platform-v1-... format.
Subsequent requests use:
Authorization: Bearer {platform_token}
The account token is different from a regular API Token. A regular API Token is used to consume API quotas; the account token is used to operate platform resources on behalf of your account, such as order payments.
¶ Trigger 402
First, send a request without X-Payment:
POST https://platform.acedata.cloud/api/v1/orders/{order_id}/pay/
Authorization: Bearer {platform_token}
Content-Type: application/json
{
"pay_way": "X402"
}
The returned status is 402, and the response includes accepts:
{
"x402Version": 1,
"error": "Payment required for this order.",
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "1200000",
"resource": "http://platform.acedata.cloud/api/v1/orders/.../pay/",
"payTo": "0x...",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": {
"name": "USD Coin",
"version": "2",
"chainId": 8453,
"verifyingContract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
}
}
]
}
On 2026-05-31, the actual output of creating a 10 Credits production order and triggering 402 is:
created order 78481793-304e-47f7-bc0c-8231aec9cc1e
created state Pending
created price 1.26
http_status=402
x402Version 1
error Payment required for this order.
accepts [
('base', 'exact', '1200000', '0x4F0E2D3477a1B94CF33d16E442CEe4733dadCeE7'),
('solana', 'exact', '1200000', '5iVXFrYaYWX2GUTbkQj8mDBoBhAX8bneYigS2LJTia43')
]
description Ace Data Cloud Credits x 10.0
The price of the order at creation was 1.26, and after entering the X402 payment process, the X402 payment discount is applied, resulting in an actual signed and settled amount of 1.2 USDC, corresponding to 1200000 atomic USDC.
Note that the resource here is a field returned by the server and involved in the signing; the client should not modify the protocol, path, or order ID within it.
¶ Sign and Retry
Order payments can reuse the low-level signing functions from @acedatacloud/x402-client or acedatacloud-x402. Below is a TypeScript example:
import { Wallet } from 'ethers';
import { signEVMPayment } from '@acedatacloud/x402-client';
const platformToken = process.env.ACE_PLATFORM_TOKEN!;
const orderId = process.env.ACE_ORDER_ID!;
const wallet = new Wallet(process.env.EVM_PRIVATE_KEY!);
const url = `https://platform.acedata.cloud/api/v1/orders/${orderId}/pay/`;
const body = { pay_way: 'X402' };
const first = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${platformToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
if (first.status !== 402) {
throw new Error(`expected 402, got ${first.status}`);
}
const paymentRequired = await first.json();
const requirement = paymentRequired.accepts.find(
(item: any) => item.network === 'base' && item.scheme === 'exact'
);
const evmProvider = {
async request({ method, params }: { method: string; params?: unknown[] }) {
if (method !== 'eth_signTypedData_v4') throw new Error(`unsupported method: ${method}`);
const [, typedDataJson] = params as [string, string];
const typedData = JSON.parse(typedDataJson);
return wallet.signTypedData(typedData.domain, typedData.types, typedData.message);
}
};
const envelope = await signEVMPayment(requirement, evmProvider, wallet.address);
const xPayment = Buffer.from(JSON.stringify(envelope), 'utf8').toString('base64');
const paid = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${platformToken}`,
'Content-Type': 'application/json',
'X-Payment': xPayment
},
body: JSON.stringify(body)
});
if (!paid.ok) {
throw new Error(`payment failed: ${paid.status} ${await paid.text()}`);
}
console.log(await paid.json());
The actual output after signing and retrying the same order with Base exact is:
status 200
payer 0x5d4f08D5c2bb60703284bc06671Eb680fA41B105
has_x_payment_response True
settle_header {'success': True, 'network': 'base', 'transaction': '0xfec08cc00a159ea1ec692b32faa9bf3d17595a986301169e689d94f58bc44151', 'errorReason': None}
order {'id': '78481793-304e-47f7-bc0c-8231aec9cc1e', 'state': 'Finished', 'pay_way': 'X402', 'price': 1.2, 'pay_id': '0xfec08cc00a159ea1ec692b32faa9bf3d17595a986301169e689d94f58bc44151'}
On-chain confirmation results:
tx 0xfec08cc00a159ea1ec692b32faa9bf3d17595a986301169e689d94f58bc44151
status 1
block 46726704
explorer https://basescan.org/tx/0xfec08cc00a159ea1ec692b32faa9bf3d17595a986301169e689d94f58bc44151
transfer {"from":"0x5d4f08D5c2bb60703284bc06671Eb680fA41B105","to":"0x4F0E2D3477a1B94CF33d16E442CEe4733dadCeE7","value":"1200000"}
¶ Successful Response and Receipt
After a successful order payment, the response body contains the order information. The platform will also carry a Base64 encoded settlement response in the response header X-PAYMENT-RESPONSE, which, when decoded, includes common fields such as:
| Field | Description |
|---|---|
success |
Whether the facilitator settlement was successful. |
transaction |
On-chain settlement transaction hash. |
network |
Payment network. |
payer |
Payer wallet address. |
amount |
Actual settlement amount, using atomic units. |
If you need to reconcile, it is recommended to save the order ID, payer wallet address, transaction, and the final status of the order.
¶ Notes
- Order payment requires a platform account token and cannot be completed solely with the X402 wallet signature.
maxAmountRequireduses USDC atomic units, where1200000represents1.2USDC.- Do not manually concatenate the receiving address or asset address; refer to the
acceptsin the 402 response. - If the same
X-Paymentis submitted multiple times, the Facilitator will implement replay protection based on the nonce.
