X402 exact and upto Billing Schemes

YuJun 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 reaches 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,
  "accepted": {
    "scheme": "exact",
    "network": "eip155:8453"
  },
  "payload": {
    "authorization": {
      "from": "0x...",
      "to": "0x...",
      "value": "95215",
      "validAfter": "1780237345",
      "validBefore": "1780240945",
      "nonce": "0x..."
    },
    "signature": "0x..."
  }
}

The Facilitator verifies the signature and amount during the /verify phase and submits this authorization on-chain during the /settle phase.

upto

upto means the client authorizes a maximum limit, and YuJun 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,
  "accepted": {
    "scheme": "upto",
    "network": "eip155:8453"
  },
  "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 and not necessarily the final deduction. The Gateway will convert the actual usage into amount during the /record phase and pass it to the Facilitator. 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 95215 atomic USDC, and the client signs according to this limit.
  • After the model's actual response, only 3 atomic 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 reject the settlement, and the client needs to reauthorize with a higher limit.

upto is currently only available on Base. SKALE only offers exact, so if you need post-measurement, please use Base.

Why Permit2 Approve is Needed

upto is ultimately pulled from the payment wallet via 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 complete, each request still requires signing a new upto envelope, as nonce, deadline, witness, and limit amount 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 usage, the Gateway can pass in amount = "0". The Facilitator will return success but will not issue an on-chain transaction.

This can avoid the issue of "request not successful but still deducting on-chain fees."

Recommendations

Scenario Recommendation
Fixed price API Use exact, logic is simple.
Order payment Use exact.
Chat completion, billed by token Use Base upto.
Haven't done Permit2 approve First use exact to run through, then switch to upto.
Need post-measurement on SKALE Not supported, SKALE only offers exact.

If you are unsure which to choose, use the SDK's default behavior; the SDK will select the payment requirement matching the network returned by the server.

Base upto Checklist

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 eip155:8453.
scheme Must be upto.
extra.chainId Base chain id is 8453.
asset Use the Base USDC contract address from the 402 response.
extra.facilitatorAddress Must participate in the witness and be consistent with Facilitator /supported.
Permit2 allowance The payment wallet needs to authorize Permit2 for Base USDC first.

Common errors and handling methods:

Error Handling Method
invalid_upto_evm_payload_invalid_signature Check if 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 Actual usage exceeds the signed limit, need to re-sign with a higher limit.