X402 exact and upto Billing Schemes
Ace Data Cloud X402 currently uses two types of schemes: exact and upto. They address different billing issues.
¶ exact
exact means that the price can be determined before the request enters the upstream API. The amount signed by the client is the final deduction amount.
Suitable for:
- Fixed price image generation;
- Fixed price video task creation;
- Fixed price search or tool APIs;
- Order payments.
EVM exact uses USDC EIP-3009 TransferWithAuthorization:
{
"x402Version": 2,
"scheme": "exact",
"network": "base",
"payload": {
"authorization": {
"from": "0x...",
"to": "0x...",
"value": "95215",
"validAfter": "1780237345",
"validBefore": "1780240945",
"nonce": "0x..."
},
"signature": "0x..."
}
}
The Facilitator verifies the signature and amount in the /verify stage, and submits this authorization on-chain in the /settle stage.
¶ upto
upto means the client authorizes a maximum limit, and Ace Data Cloud settles based on actual usage after the request is completed, with the actual deduction not exceeding the limit.
Suitable for:
- Chat completion: The final price depends on prompt tokens and completion tokens;
- Streaming responses: The true output length is only known after it ends;
- Future post-measurement APIs.
upto uses Permit2 PermitWitnessTransferFrom. The amount signed by the client is not a fixed transfer, but a limit authorization with a witness:
{
"x402Version": 2,
"scheme": "upto",
"network": "base",
"payload": {
"permit2Authorization": {
"from": "0x...",
"spender": "0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002",
"nonce": "123456789",
"deadline": "1780240945",
"permitted": {
"token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "95215"
},
"witness": {
"to": "0x...",
"facilitator": "0x...",
"validAfter": "1780237345"
}
},
"signature": "0x..."
}
}
permitted.amount is the limit, not necessarily the final deduction. The Gateway will convert the actual usage into amount and pass it to the Facilitator in the /record stage. The Facilitator is only allowed to settle amount <= permitted.amount.
Base upto program run result:
payer 0x5d4f08D5c2bb60703284bc06671Eb680fA41B105
elapsed_ms 5104
content ADC_BASE_UPTO_OK
id chatcmpl-DlcbyS4IT8kUAMo4Ri97HiIHc9T8V
tx 0x4b0b836ce1cd1171cdbc37df1637150b024214ec28e7f6f2d09122f15cbfc036
block 46726437
explorer https://basescan.org/tx/0x4b0b836ce1cd1171cdbc37df1637150b024214ec28e7f6f2d09122f15cbfc036
signed ceiling 95215 atomic USDC
transfer value 3 atomic USDC
Explanation:
- The authorization limit returned in 402 is
95215atomic USDC, and the client signs according to this limit. - After the model's actual response, only
3atomic USDC is settled, and the on-chain transaction can be checked on BaseScan. - This result illustrates the key difference of
upto: the signed amount is a limit, and the on-chain settlement can be less than the limit. - If the actual usage exceeds the limit, the Facilitator should refuse the settlement, and the client needs to reauthorize with a higher limit.
SKALE upto program run result:
=== Live X402 upto E2E (skale) ===
Payer wallet: 0xd0479FA9FD8C678303d477433d24C15e3723CC1C
Network: skale
Endpoint: POST https://api.acedata.cloud/v1/chat/completions
--- Step 1: POST without auth -> expect 402 ---
Got 402 with 5 accept entries
Scheme: upto
Ceiling: 4760750 atomic (4.76075 USDC)
PayTo: 0x4F0E2D3477a1B94CF33d16E442CEe4733dadCeE7
PayUSDC: 0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20
ChainId: 1187947933
Facilitator: 0xd0479FA9FD8C678303d477433d24C15e3723CC1C
--- Step 3: Retry with X-Payment -> expect 200 ---
Status: 200
x-usage-exempt: true
body preview: {"id":"msg_01HRrEHx41PTgU28EY1M","model":"claude-sonnet-4-5-20250929"}
Live upto E2E SUCCESS.
SKALE on-chain result:
Permit2 approve
tx 0x646e92908cc31614bf99f22b13f48a00a74ddd89f7614327ea59802f1094629e
status 0x1
block 1969933
explorer https://skale-base-explorer.skalenodes.com/tx/0x646e92908cc31614bf99f22b13f48a00a74ddd89f7614327ea59802f1094629e
Settlement
trace_id ca6f63a9-36b7-434a-b8a1-eb0857475e59
tx 0x51831a97fb97802951bee5dfb36735f4a0b589f153e6a23976fad5495c3925bc
status 0x1
block 1969936
settlement amount 151 atomic USDC
explorer https://skale-base-explorer.skalenodes.com/tx/0x51831a97fb97802951bee5dfb36735f4a0b589f153e6a23976fad5495c3925bc
Result explanation:
- SKALE
uptohas completed HTTP 402 -> HTTP 200, and the on-chain settlement was completed after/record. - The signature limit for this verification request is
4760750atomic USDC, and the actual settlement is151atomic USDC. - Before using SKALE
upto, the payment wallet needs to complete Permit2 approval for SKALE USDC; if not authorized, it will returnPERMIT2_ALLOWANCE_REQUIRED. - EVM typed data will bind chain id, Permit2 spender, USDC contract, payee address, and facilitator address. Always use real-time parameters from the 402 response to construct the signature.
¶ Why Permit2 Approval is Needed
upto is ultimately pulled from the payment wallet through Permit2 by the x402 proxy. Before the first use, the payment wallet needs to give Permit2 an ERC-20 allowance.
Python CLI:
pip install 'acedatacloud-x402[cli]'
X402_PRIVATE_KEY=0x... acedatacloud-x402 approve-permit2 --network base
Programmatic way:
from acedatacloud_x402 import EVMAccountSigner, approve_permit2
approve_permit2(
rpc_url="https://mainnet.base.org",
signer=EVMAccountSigner.from_private_key("0x..."),
token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
)
After authorization is completed, a new upto envelope still needs to be signed for each request, as the nonce, deadline, witness, and amount limit are all different.
¶ Zero Amount Settlement
upto supports cases where the actual amount is 0. For example, if the upstream API does not successfully generate billable quantity, the Gateway can pass amount = "0". The Facilitator will return success but will not send an on-chain transaction.
This can avoid the issue of "the request was not successful but still incurs on-chain fees."
¶ Selection Recommendations
| Scenario | Recommendation |
|---|---|
| Fixed Price API | Use exact, the logic is simple. |
| Order Payment | Use exact. |
| Chat Completion, Token Billing | Prefer using Base upto. |
| Permit2 approval not done yet | First use exact to run through, then switch to upto. |
SKALE upto |
On-chain verification completed; confirm chain id, facilitator address, and Permit2 allowance are consistent with the 402 response before going live. |
If you are unsure which to choose, use the SDK default behavior; the SDK will select the payment requirement that matches the network returned by the server.
¶ SKALE upto Checklist
SKALE upto has completed HTTP paid retry and on-chain settlement verification. When integrating or troubleshooting, please ensure the following parameters come from the same 402 response and remain consistent during client signing:
| Parameter | Checkpoint |
|---|---|
network |
Must be skale. |
scheme |
Must be upto. |
extra.chainId |
The current SKALE Base chain id is 1187947933. |
asset |
Use the SKALE USDC contract address from the 402 response. |
extra.facilitatorAddress |
Must participate in witness and be consistent with Facilitator's supported capabilities. |
| Permit2 allowance | The payment wallet needs to authorize Permit2 for SKALE USDC first. |
Common errors and handling methods:
| Error | Handling Method |
|---|---|
invalid_upto_evm_payload_invalid_signature |
Check if the chain id, facilitator address, Permit2 domain, spender, signing account, and witness are consistent with the 402 response. |
PERMIT2_ALLOWANCE_REQUIRED |
Re-initiate the request after executing Permit2 approve for the target chain USDC. |
amount exceeds permitted amount |
The actual usage exceeds the signed limit, requiring a new signature with a higher limit. |
