The payment loop
1
The seller asks for payment
The buyer requests a paid route. The seller answers
402 Payment Required with a PAYMENT-REQUIRED
header that lists what it accepts: scheme exact, network stellar:testnet, the asset’s contract
address, the payTo address, the amount in the asset’s base units, maxTimeoutSeconds, and
extra.areFeesSponsored: true, which the seller’s scheme reads from Rail402’s /supported.2
The buyer signs an authorization
The buyer’s x402 client builds a Soroban invocation of the asset contract’s
transfer(from, to, amount)
and signs its authorization entry with the buyer’s key. The signature fixes the asset, the recipient and
the amount. The client sends the payment as payload: {transaction} in the PAYMENT-SIGNATURE header.3
The seller calls /verify
Rail402 runs its own checks first, before any simulation: protocol, operator policy, transaction shape,
accounts, authorization and expiry. It then runs the unmodified
@x402/stellar verifier, which simulates
the transaction against the current ledger. When simulation fails, Rail402 names the on-chain cause, for
example a missing trustline or a spent nonce.4
The seller calls /settle
Rail402 runs its own checks again, claims the payer’s authorization and leases one of its channel
accounts. Upstream
@x402/stellar then runs its verifier again and rebuilds the transaction around the
buyer’s signed authorization with the channel account as the source, and Rail402’s sponsor account wraps
it in a fee bump and pays the fee. Rail402 records the signed envelope before broadcasting it, then waits
for the ledger.5
The seller serves the resource
The settle response carries the transaction hash. The seller returns it to the buyer in the
PAYMENT-RESPONSE header together with the resource.What the facilitator can and cannot do
Rail402 is non-custodial. It holds one secret per network, the sponsor seed, and derives its channel accounts from it.- The sponsor pays every settlement fee and the base reserves of the channel accounts. It needs only XLM.
- Channel accounts are the source accounts of settlement transactions, one settlement at a time each, so concurrent settlements never compete for a sequence number. They hold no balance.
- Verification refuses any payment in which a facilitator account is the payer, a transaction or operation source, or a party to an authorization.
- The payer’s signature covers the asset, recipient and amount. Changing any of them after signing fails signature verification.
Settlement is idempotent and crash-safe
Each settlement is keyed by the payer’s authorization (network, payer, nonce).- A repeated
/settlefor the same payment returns the original result, and funds move once. - A different envelope for an authorization that was already settled is refused
(
settle_exact_stellar_idempotency_conflict). - If the transaction is not final within the confirmation window,
/settleanswerssettlement_pendingwith the transaction hash, and a background reconciler finishes it from the recorded bytes. - After a crash or restart, only the recorded bytes are ever resubmitted, so there is never a second transaction for the same authorization.
The Bazaar
A payment can carry the x402bazaar extension, which describes the paid resource: its input and output
schema, method or tool name, and service metadata. When a payment with that extension settles, Rail402 adds
the resource to its catalog, provided the metadata is valid and, for an http or https resource URL, the
host is public. A payment without the extension is settled normally and not cataloged.
- Settlement-gated. Nothing is listed without a settled payment to it.
/verifyonly previews the outcome. - Bound to the payee. The listing belongs to the
payTothe settlement paid. Another seller cannot change it. - Confirmed at the origin. An HTTP resource is listed, and any change to it published, only after the
resource’s own
402response confirms it. - Off the payment path. Cataloging never changes the payment result and adds no transaction. The seller
learns the outcome from the
EXTENSION-RESPONSESheader of the facilitator’s response.
GET /discovery/resources and
GET /discovery/search. The catalog lives in Postgres, not on-chain.
Networks
Rail402 knows the CAIP-2 networksstellar:testnet and stellar:pubnet. Which ones an instance serves is
configuration (NETWORKS). The hosted instance serves stellar:testnet
only. The tests and conformance runs exercise testnet. Pubnet can be configured, with stricter rules that
the service checks at startup (see Configuration), but it has not been exercised end to
end.
Components
Rail402 is one service backed by Postgres, built from workspace packages that can also be used on their own.
Without Postgres (
STORE=memory) the same service runs in one process with no durable state, which suits
local development and tests. See Configuration.