Before you start
You’ll need Node.js and two testnet accounts (a buyer and a seller), each with a USDC trustline. The buyer’s account also needs some testnet USDC. The quickstart walks through setting these up. The commands below were tested with Node.js 24 and@x402/* 2.30.0.
Networks, assets, and trustlines
A dollar price such as
"$0.01" is converted to USDC on whichever network you register. On stellar:testnet, that’s amount: "100000" of the testnet USDC contract; on stellar:pubnet, it’s the same amount of the mainnet contract. To charge in a different SEP-41 token, set the price as { asset: "<contract id>", amount: "<base units>" } instead (the facilitator must support that asset).
A classic G… account needs a USDC trustline before it can hold USDC. That goes for both the buyer (who sends USDC) and the seller’s payTo account (which receives it). If payTo doesn’t have a trustline, the payment fails. Contract addresses (C…, such as a smart wallet) don’t need trustlines.
Every facilitator publishes what it supports at /supported. Look for "scheme": "exact" on your network with "extra": {"areFeesSponsored": true}. A facilitator that catalogs resources for discovery also lists "bazaar" in its top-level extensions.
Make an endpoint discoverable
ThedeclareDiscoveryExtension function describes a route’s input and output. A Bazaar-enabled facilitator uses that description to catalog the route, and agents use it to call the route without needing to read your docs.
seller.js
bazaar extension settles through a Bazaar-enabled facilitator, that facilitator may add the resource to its catalog. Facilitators validate the metadata first, and some refuse resources on non-public hosts (like localhost). The result comes back in the EXTENSION-RESPONSES header as success, processing, or rejected (with a reason), and the stock HTTPFacilitatorClient logs it. Either way, the payment still settles. To get listed, deploy your seller on a public hostname.
Build an agent that discovers and pays
Facilitators that implement the x402 Bazaar extension can serve their catalog atGET /discovery/resources and GET /discovery/search:
withBazaar helper from @x402/extensions/bazaar adds those same discovery calls to the stock facilitator client. The agent below searches the catalog, keeps only results it can pay for on testnet at 0.05 USDC or less, fills in the listing’s example input, and then pays. As a backstop, spendControls refuses any payment above the cap before anything gets signed.
agent.js
DISCOVERY_URL to any facilitator whose /supported endpoint lists the bazaar extension. The community facilitators list notes which ones catalog resources.
The receipt’s transaction field is the settlement transaction hash. Look it up on a block explorer to see the buyer’s USDC move to payTo, with the fee paid by the facilitator.
What the payer signs
The buyer signs a Soroban authorization entry for exactly one call:transfer(from = buyer, to = payTo, amount) on the asset contract named in the payment requirements. Changing the recipient, the amount, or the asset invalidates the signature. The entry expires after roughly maxTimeoutSeconds (its expiration ledger is the current ledger plus maxTimeoutSeconds divided by the ledger close time), so an unsettled payment can’t be settled later. And since the buyer isn’t the transaction source, paying doesn’t consume the buyer’s sequence number.
Fee sponsorship
Whenextra.areFeesSponsored is true, the facilitator pays the network fee for the settlement transaction, so the buyer doesn’t need any XLM to cover it. This is fee sponsorship only, not sponsored reserves. A classic account still needs its own base reserve plus the reserve for its USDC trustline (see Lumens).
Moving to mainnet
- Network. Use
stellar:pubneton both sides. A"$0.01"price then resolves to mainnet USDC. - Facilitator. Choose one whose
/supportedendpoint listsexactonstellar:pubnet. Some require an API key, which the seller sends using thecreateAuthHeadersoption onHTTPFacilitatorClient. - RPC. On mainnet, the stock client has no default RPC endpoint and throws an error if you don’t provide one. Pick one from the RPC providers list and pass it in:
new ExactStellarScheme(signer, { url: "<mainnet RPC URL>" }). - Accounts. The buyer and any
G…payToaccount need a trustline to mainnet USDC (issuerGA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN), plus enough XLM for their reserves. - Keys and limits. Keep secret keys out of your code, give agents a separate low-balance account, and set
spendControlsto the most you’re willing to lose on a single payment.
Troubleshooting
Learn more
- x402 on Stellar: wallets, assets, facilitators, and examples
- x402
exactscheme on Stellar: what facilitators must check - Bazaar extension: discovery metadata and endpoints
- Signing Soroban invocations: authorization entries in depth