Make an x402 API pay its account
Account-mediated settlement, proven payers, facilitator funding and receipt reconciliation.
settle from a source update.Settle through the account
Offer x402 v2 exact payment in the configured EIP-3009 token, with payTo equal to the registered
BondrailAccount. The payer signs transferWithAuthorization; the Bondrail facilitator calls
BondrailAccount.settle(from, value, validAfter, validBefore, nonce, v, r, s).
The account calls the token, checks the received amount, emits Settled(payer, value, nonce), and books
and splits the whole payment as revenue in that same transaction. No later sweep is required.
This proves authorization by the payer; it does not prove customer independence or delivery quality.
A direct token transfer, including an authorization submitted straight to the token, is different:
account.sweep() books the uncredited balance with no proven on-chain payer. Indexer attribution can
recognize token authorization logs, but those do not create an account Settled event. Someone can
submit a signed authorization to the token first; its nonce is then used and account settlement fails.
The money remains at the signed recipient and needs sweeping.
Serve offers and paid work
import { exactUsdcRequirements, handlePaidRequest, httpFacilitator, type DurableStore } from '@bondrail/sdk/x402';
const requirements = exactUsdcRequirements({ chainId: 10143, asset, amount: '10000', payTo: account });
const facilitator = httpFacilitator(process.env.X402_FACILITATOR_URL!, 10143);
async function paid(request: Request, store: DurableStore, work: () => Promise<unknown>) {
return handlePaidRequest({
header: request.headers.get('PAYMENT-SIGNATURE'), resource: 'https://api.example/answer',
description: 'Answer one question', requirements, store, facilitator, work,
});
}Use the actual token domain in requirements.extra.name / .version (the helper defaults to USDC v2).
DurableStore must persist get and atomic compare-and-swap cas across replicas. The handler verifies,
claims a journal entry, runs work, saves the result, then settles. Retries reuse journaled work; a crash
before saving a result can leave a processing entry and is not a general exactly-once execution guarantee.
Keep facilitator credentials and durable stores on the server.
Serve /.well-known/bondrail.json with bondrailManifest / manifestResponse, naming the chain, account
and every paid endpoint. See the SDK examples.
Facilitator and gas budget
The facilitator is an HTTP service,
not a fund-custody contract. GET /supported, POST /verify, POST /settle and GET /health expose its
capabilities, validation, settlement and operational state. It pins the factory and token, discovers the
token domain, verifies the 65-byte EOA signature, authorization bounds, account registration/asset,
nonce and funds, then simulates account.settle. Only a successful receipt proves payment.
Its separate gas wallet pays MON. The current code estimates gas with a 15% margin, defaults to a
500,000 gas ceiling and a 150 gwei fee ceiling, and checks affordability before signing/journaling.
Those defaults cap one commitment at 0.075 MON; actual costs vary. The October 15 warm-call sample
averaged 0.0284941505 MON; budget about 4 MON per 100 warm calls including reserve, then consult
/health. This is a planning estimate, not a fixed price. See the
measured gas report.
Health fields include balanceNative, estimatedSettlementCostWei, settlementsRemaining, reservedWei,
inFlightNonce and blockedReason. A positive balance may still be insufficient. Use one writer/key/store
namespace. Durable signed transactions support bounded rebroadcast and same-nonce fee replacement;
near expiry the service can cancel that nonce. Cancellation is not payment. Low funds or a fee cap
can block recovery until the operator acts. Source behavior does not attest a running server's revision;
check its /health and operator configuration before traffic.
Retry and reconcile
An empty-hash funding/busy/fee-cap refusal produces a retryable agent 503, charged:false, while
preserving the generated result. Fix the reported condition and retry the same signed request.
A 202 settlement_pending means the outcome is unresolved: preserve paymentKey, authorization and
known transaction hash. A timeout is not evidence of nonpayment; do not issue a new charge to retry.
The demo agent's authenticated POST /api/admin/reconcile accepts {paymentKey, transaction}.
It requires a successful receipt plus one additional block and matches the token Transfer,
AuthorizationUsed, account Settled event and authorization state at the receipt block. On success it
atomically marks the existing pending record complete; retry the original oracle request to retrieve
its cached answer and PAYMENT-RESPONSE. Reconciliation sends no transaction and does not rerun work.
It cannot repair a processing record without a saved result. Follow the
reconciliation runbook.
Monitoring and guarded buyers
bondrailGuard in @bondrail/sdk/x402-guard checks offers against the manifest; pinFromBond supplies
an independent account/asset/chain pin. Wrap this guarded fetch with your x402 buyer before signing.
The guard itself does not pay, and an issuer-controlled manifest alone is not an independent pin.
The observer/CRE path checks declared endpoints against the committed policy. BondrailCovenant.onReport
requires the pinned forwarder and observer signature. Two qualifying violations in adjacent 30-second
epochs can default an active bond; continuous Unknown reports with gaps no longer than one hour block
deposits after one hour and can default after 24 hours. No reports alone never establish default.
Report cadence is an operator setting, not a guaranteed detection time. See defaults.