Skip to main content
A seller runs a stock x402 resource server and names Rail402 as its facilitator. Nothing Rail402-specific is installed: the facilitator is just a URL. This page uses the hosted testnet facilitator.
Requires Node.js 24, which runs the .ts file below directly. The upstream x402 e2e suite also passes through Rail402 with the stock Hono, Fastify and Next.js servers; see Conformance evidence.

1. Install

2. A receiving account

payTo must be able to hold the asset. For a G… account that means a USDC trustline. Without one, payments to it are refused with invalid_exact_stellar_payload_recipient_trustline_missing. The create-account.ts script from the buyer quickstart creates a testnet account with the trustline:
The seller never needs XLM for fees and never signs anything during a payment.

3. The seller

seller.ts
  • price: "$0.01" is converted by the stock Stellar server scheme into Circle testnet USDC: amount: "100000" (7 decimals) of contract CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA.
  • x402ResourceServer reads /supported from the facilitator, so the payment requirements carry extra: { areFeesSponsored: true }.
  • bazaarResourceServerExtension and declareDiscoveryExtension publish the route’s discovery metadata: the query parameters it takes, their JSON Schema, and an example output.
An unpaid request gets 402 with a PAYMENT-REQUIRED header. Decoded, it looks like this (illustrative and abridged; payTo is your account):
Pay it with the buyer quickstart.

4. Get listed

When a payment that carries the bazaar extension settles, Rail402 catalogs the resource and tells the seller the outcome in the EXTENSION-RESPONSES header of its /verify and /settle responses. The stock HTTPFacilitatorClient logs both:
The first settlement of a new HTTP resource reports awaiting_origin_verification: Rail402 then requests the resource without payment, and lists it once the 402 your server answers with confirms the payment options and metadata. Later settlements report recorded, or awaiting_origin_verification when the payment carries changed metadata. The full outcome also carries listingId and version; see Cataloging.
Only resources on public hosts are cataloged. The seller above, on localhost, is paid normally but its listing is refused:
Deploy the seller on a public host name to be listed. Behind a TLS-terminating proxy, call app.set("trust proxy", 1) so Express reports the https URL the buyer used: the resource URL comes from the request, and Rail402 fetches it later, without payment, to confirm the listing.
Once listed, the resource appears in discovery, bound to your payTo:
Shortly after the first settlement, Rail402 requests the resource without payment. If the 402 it gets back names the same payTo and a matching bazaar extension, the listing’s trust becomes origin_verified and a new version is recorded. To have your domain vouch for the listing as well, publish a SEP-1 stellar.toml at https://<your host>/.well-known/stellar.toml that lists your payTo account:
Within minutes the listing’s trust becomes domain_verified.

Changing price or metadata

Change the route config and redeploy. The next settlement reports the change as proposed (awaiting_origin_verification); Rail402 then requests the resource and publishes what its own 402 response declares. Every published change is a new entry in the listing’s public version history. A different payTo settling for the same resource cannot take the listing over unless the resource’s own 402 names that payTo.

Self-facilitation

To verify and settle inside the seller process instead of calling a facilitator over HTTP, see In-process facilitator.