402402Signal

Developer guides

Add an offer check before payment

Combine a hosted observation with local verification in an existing exact-x402 buyer.

Read as Markdown · Packages and capability record

Add a check to an existing x402 buyer

Use this when your application has a supported exact-payment endpoint and needs the current offer checked against buyer requirements. For native MPP, use the charge guide.

The offline guard requires Node.js 22 or newer. The supplied file store requires private POSIX storage. Obtain the matching archive and SHA256SUMS from GitHub Releases, verify the digest, and install that archive. This is not an npm registry release; do not substitute an unverified similarly named package.

sha256sum --check SHA256SUMS
# Install the exact archive identified in the matching release notes.

1. Request bound evidence

Use url for an exact endpoint or need to find candidates. Start with an unpaid request:

curl -sS -D - https://402signal.com/route \
  -H 'Content-Type: application/json' \
  --data '{"need":"web search","networks":["base"],"max_price_usd":0.02,"require_route_binding":true}'

HTTP 402 supplies the checking-fee requirements. It is not a completed check. Your buyer validates them, reserves the budget, authorizes the fee once and submits the identical request. A qualifying observation costs $0.003 USDC; seller payment is separate.

2. Retain the original attempt

Use RouteClient and its durable store, or implement the documented contract. Keep the exact request and raw response. Parsing and reserializing untrusted JSON can erase duplicate-key evidence. Obtain the log key from independent trusted configuration, not the response being verified.

3. Compare immediately before signing

Get the seller's current unpaid challenge for the same URL, method and body bytes, with redirects disabled. Put the guard at the payment boundary:

import { withVerifiedRoute } from '@402signal/route-guard';

await withVerifiedRoute({
  routeResponseJson, routeRequestJson, trustedLogVkey,
  request: { url, method, body: exactRequestBytes },
  challenge: { status: 402, bodyText, paymentRequired }
}, async verified => {
  // Reserve the buyer's durable payment identity and budget.
  // Validate the transaction against verified.accepted.
  // Then invoke the buyer's existing wallet flow once.
});

This is integration scaffolding, not complete wallet code. The reference Base buyer shows the complete supported composition, including the signer and planning mode. It requires Node 24 and private POSIX storage. Start with planning before loading keys.

4. Treat a refusal as a stop

Changed terms, expired evidence or an invalid proof must not trigger an unguarded fallback. The default observation window is 60 seconds; inspect the returned expiry. Your wallet still checks transaction effects, reserves budgets and prevents duplicate seller sends. A matching proof does not guarantee delivery or output quality.

The ordinary hosted profile covers GET and a narrowly justified empty-object POST fallback. It is not an arbitrary POST proxy. The separate bounded Parallel profile has its own dated compatibility notes, including recipient changes that led the fixed-offer guard to refuse. Do not replace a recipient pin to force a purchase.

Build the request · Handle billing and recovery · Exact request contract

Give this task to your coding agent
Add a supported exact-x402 offer check to the existing buyer. Start with the offline fixture. Read https://402signal.com/developers/check-offer and the matching released guard/client contract. Retain raw request/response evidence and an independently trusted key. Put withVerifiedRoute before the existing signing path. Keep durable budgets and transaction validation in trusted application code. Do not request funds or retry an uncertain payment without existing operator authorization.