Test x402 payment terms before a release

A well-formed 402 can still ask for a price or recipient you did not approve. Keep the policy fixed, change one term, and inspect the decision yourself.

In short

Reproduce five synthetic x402 V2 cases through the public Settlens evaluator: approved terms, a higher price, another recipient, another resource and a missing recipient policy. Use the browser or curl, then run the same reviewed fixtures in CI without a wallet or private CLI.

On this page

See three decisions in 60 seconds

Three still captures of real browser-checker responses, edited to 20 seconds each. Synthetic examples, recorded October 15, 2026. No audio, live merchant incident, signature or payment. The steps below are the text equivalent.

Try the same three steps yourself, or download the 60-second video.

Reproduce it in your browser

  1. Open the free checker, select Load sample, then Check the request. The expected decision is pay under the complete example policy.
  2. Select Price doubles, then check again. The quote is now 20000 atomic units, above the unchanged 10000 ceiling. Expected decision: do_not_pay.
  3. Select Recipient changes, then check again. The recipient differs from the unchanged allowlist. Expected decision: do_not_pay.

The policy belongs to the reviewer. Copying an untrusted quote into its own allowlist would defeat the check. A change may be intentional: review it before updating the policy.

Expected results from the same evaluator used by the public checker
Synthetic caseDecisionFailed or warned checks
Approved examplepayNone
Price doublesdo_not_paypolicy.maximum_amount, policy.acceptable_option
Recipient changesdo_not_paypolicy.recipient, policy.acceptable_option
Resource changesdo_not_paybinding.resource_url
Recipient policy missingreviewNone

The approved fixture uses the specification’s Base Sepolia example (eip155:84532). These are illustrative terms, not a payment destination to fund. A pay decision means that an option meets the supplied policy and evaluated checks; it is not an instruction to transfer funds or a security guarantee.

Run the same check with curl

This public call needs no token, account or access to the private Settlens CLI. It evaluates supplied data in memory; it never requests api.example.com. Do not include credentials, private keys, seed phrases or confidential payloads. See the processing and rate-limit details.

ShellApproved synthetic quote and a complete policy
curl -s https://settlens.com/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"evaluate_payment_requirements","arguments":{"payment_required":{"x402Version":2,"error":"PAYMENT-SIGNATURE header is required","resource":{"url":"https://api.example.com/premium-data","description":"Access to premium market data","mimeType":"application/json"},"accepts":[{"scheme":"exact","network":"eip155:84532","amount":"10000","asset":"0x036CbD53842c5426634e7929541eC2318f3dCF7e","payTo":"0x209693Bc6afc0C5328bA36FaF03C514EF312287C","maxTimeoutSeconds":60,"extra":{"name":"USDC","version":"2"}}]},"resource_url":"https://api.example.com/premium-data","policy":{"pay_to":["0x209693Bc6afc0C5328bA36FaF03C514EF312287C"],"assets":["0x036CbD53842c5426634e7929541eC2318f3dCF7e"],"networks":["eip155:84532"],"schemes":["exact"],"max_amount":"10000"}}}}'

In result.structuredContent, inspect decision, acceptable, reasons and checks. Keep the policy unchanged and replace only payment_required.accepts[0].amount with "20000" to reproduce the price case.

Keep reviewed cases in CI

Download the five synthetic fixtures and the small Node.js runner. Review both before using them. With Node.js 20.19 or newer:

ShellRun the public example
curl --fail --show-error -O https://settlens.com/assets/x402-policy-cases.json
curl --fail --show-error -O https://settlens.com/assets/x402-policy-regression.cjs
node x402-policy-regression.cjs x402-policy-cases.json

The runner exits nonzero on an unexpected decision, an HTTP failure, timeout or evaluator error. Its full source is below. The public evaluator is limited to 60 requests per minute per IP; each run makes five requests. Availability and shared CI egress limits can fail this job too.

JAVASCRIPTx402-policy-regression.cjs
// Public example: node x402-policy-regression.cjs x402-policy-cases.json
// Synthetic fixture checks, not a scan of a deployed merchant or a settlement test.
const { readFile } = require("node:fs/promises");

async function main() {
  const cases = JSON.parse(await readFile(process.argv[2] || "x402-policy-cases.json", "utf8"));
  if (!Array.isArray(cases) || !cases.length) throw new Error("Expected a non-empty array of reviewed cases.");
  for (const example of cases) {
    const response = await fetch("https://settlens.com/mcp", {
      method: "POST", redirect: "error", signal: AbortSignal.timeout(15000),
      headers: { "content-type": "application/json", accept: "application/json", "mcp-protocol-version": "2025-06-18" },
      body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: {
        name: "evaluate_payment_requirements", arguments: example.arguments,
      } }),
    });
    if (!response.ok) throw new Error(`Evaluator unavailable (HTTP ${response.status}).`);
    const message = await response.json();
    const result = message.result?.structuredContent;
    if (message.error || message.result?.isError || !result) throw new Error("Evaluator returned an error.");
    if (result.decision !== example.expected) throw new Error(`${example.name}: expected ${example.expected}, got ${result.decision}.`);
    console.log(`${example.name}: ${result.decision}`);
  }
}

main().catch((error) => { console.error(error.message); process.exitCode = 1; });

Commit reviewed fixtures and the runner to your own repository. For example, after checking out your code and selecting a supported Node.js version, add this step to your existing workflow:

YAMLGitHub Actions step
- name: Check reviewed x402 fixtures
  run: node x402-policy-regression.cjs x402-policy-cases.json

What this example establishes

This is a regression check for supplied challenges and policy decisions. The synthetic fixtures alone do not test a deployed merchant. For your release, capture a challenge from an endpoint you are authorized to test, review its terms independently, and decide which controlled changes must be refused. Never automatically refresh an approved reference from unreviewed live data.

It does not establish live HTTP behavior, signatures, balances, nonce use, on-chain settlement or overall payment safety. The exported decision JSON is unsigned. For a scoped endpoint scan, monitoring reference and private CLI/CI integration, request a technical pilot.

Sources

  1. x402 V2 HTTP transportx402 Foundation · github.com
  2. x402 protocol specification, version 2x402 Foundation · github.com