# AgentSmith > Self-hostable, non-custodial Stellar x402 Facilitator and payment SDK for Sellers, Buyers and agents. Sellers verify and settle through the Facilitator; Buyers call the Seller only and sign locally. Bazaar discovery is coming soon and is not part of the payment SDK. - [Documentation](https://agentsmith.xyz/docs.html) - [SDK quick start](https://agentsmith.xyz/docs.html#sdk) - [Endpoints reference](https://agentsmith.xyz/docs.html#endpoints) - [SDK package (npm)](https://www.npmjs.com/package/agentsmith-x402-sdk) - [Reference integration (weather-x402)](https://github.com/57blocks/weather-x402) ## Non-custodial by design The Facilitator never holds or sources the buyer's funds. The buyer's signature binds the asset, recipient and amount, so the Facilitator can build and submit the transaction and sponsor the XLM network fee, but it cannot redirect a payment or change what was authorized. For metered upto, the on-chain settlement Kernel moves the token directly from buyer to recipient and enforces the buyer's signed ceiling and validity window. The Kernel is intentionally minimal - no owner, upgrade, pause, withdrawal, or arbitrary-call interface - so it can neither divert nor custody funds. It is experimental and has not yet been audited. ## Facilitator environments | Environment | Base URL | x402 network | API key | | --- | --- | --- | --- | | Testnet | https://testnet.agentsmith.xyz/facilitator | stellar:testnet | Not required | | Mainnet | https://mainnet.agentsmith.xyz/facilitator | stellar:pubnet | Required | On mainnet every request carries Authorization: Bearer . The key authenticates the Seller to the Facilitator; never expose it in browser code. Deployment addresses do not establish current availability: check the selected service with GET /supported. Use the matching network, SEP-41 token contract and recipient. Prices are atomic integer strings; token precision is contract-specific. USDC uses seven decimals, but arbitrary SEP-41 tokens need not. Do not infer an asset allowlist from the USDC examples. ## Getting an API key (mainnet) Register a Resource Server through POST /credentials/register with a name, domain and email. The domain must be unique; a repeat registration is rejected. The response returns a resourceServerId and the API key, shown only once - store it in backend secret storage immediately. Rotate with POST /credentials/keys/rotate (the previous key keeps working for ten minutes); revoke with DELETE /credentials/keys/current. Rotation and revocation authenticate with the current key. Keys are per environment; testnet does not require one. ## Endpoints The resource server calls these endpoints; the buyer never calls the Facilitator directly. Bodies follow the x402 v2 specification. - GET /health - returns ok, service, version and network. - GET /supported - advertises kinds (x402Version, scheme, network, extra), extensions and signers, including fee sponsorship. - POST /verify - validates a payment without moving funds. Body: x402Version, paymentPayload, paymentRequirements. Returns isValid, payer, invalidReason, invalidMessage. - POST /settle - submits and confirms a payment on the selected Stellar network. Same body. Returns success, transaction, network, payer, amount, errorReason, errorMessage. paymentRequirements fields: scheme, network (CAIP-2), amount (atomic digit string), asset (SEP-41 contract), payTo, maxTimeoutSeconds (1-300), optional extra. The Facilitator sponsors XLM network fees subject to its configured cap. ## Schemes exact is the default and the only upstream-standard scheme: a fixed amount, where the buyer authorizes one SEP-41 transfer(from, to, amount) and the Facilitator cannot change its asset, recipient or amount without invalidating the authorization. Available on both testnet and mainnet. upto is an experimental AgentSmith extension for metered or usage-based pricing: the buyer signs an authorization for a maximum amount against a Soroban settlement Kernel, and after the handler runs the resource server settles the actual amount (positive, no greater than the maximum). Zero, missing, malformed or over-cap usage rejects settlement. It is advertised only when the Facilitator is configured with the Kernel contract for that network, and is not yet an upstream x402 scheme - we plan to contribute it upstream to x402 soon. upto Kernel contracts: - stellar:testnet - CBB7WCIQOBOJ4G7JUPVOA3RI553HBSYQ3GLBJ25X7W7S7MRJIGVCXRE3 - stellar:pubnet - CCV4RALFBEE2QLKPK6H5ZX24CYMKIFN3723J5J4TMDEFWAFLELGYODNI ## SDK setup Requires Node.js 24+ and ES modules ("type": "module"). ```sh npm install agentsmith-x402-sdk # Sellers using Express (including NestJS with the Express adapter): npm install express @x402/express@2.23.0 ``` ### Seller: Express or NestJS with the Express adapter ```ts import express, { type Request, type Response } from 'express'; import { createPaymentMiddleware } from 'agentsmith-x402-sdk/seller/express'; const asset = process.env.TOKEN_CONTRACT; const payTo = process.env.SELLER_ADDRESS; if (!asset || !payTo) throw new Error('Set TOKEN_CONTRACT and SELLER_ADDRESS'); const app = express(); app.use(await createPaymentMiddleware({ network: 'stellar:testnet', facilitator: { url: 'https://testnet.agentsmith.xyz/facilitator' }, routes: { 'GET /price': { accepts: { scheme: 'exact', payTo, price: { asset, amount: '40000' }, }, }, }, })); app.get('/price', (_req: Request, res: Response) => res.json({ result: 'data' })); app.listen(3000); ``` For mainnet replace the network and Facilitator fields: ```ts network: 'stellar:pubnet', facilitator: { url: 'https://mainnet.agentsmith.xyz/facilitator', apiKey: process.env.FACILITATOR_API_KEY, }, ``` Configure the mainnet token and recipient too. createPaymentMiddleware initializes native x402 components and rejects unsupported capabilities. Unpaid requests get 402 before business execution; verified requests execute the handler, then settle. Handlers do not call verify/settle manually. Nest route patterns include any global prefix. Custom adapters compose createResourceServer from agentsmith-x402-sdk/seller. ### Experimental upto Set scheme: 'upto' and the maximum atomic price on the route. The SDK supplies the server adapter; do not copy it from another application. Every successful metered handler must report positive actual usage within the authorized maximum before responding: ```ts import { setSettlementOverrides } from 'agentsmith-x402-sdk/seller/express'; import type { Request, Response } from 'express'; // Configure the metered route with scheme: 'upto' and its maximum price. app.get('/metered', (_req: Request, res: Response) => { setSettlementOverrides(res, { amount: '20000' }); res.json({ result: 'data' }); }); ``` Zero, missing, malformed or over-cap usage rejects settlement. upto is local and experimental, requires a compatible Kernel, and is not yet an upstream x402 scheme. ### Node Buyer / agent ```ts import { createBuyerFetch } from 'agentsmith-x402-sdk/buyer'; const secret = process.env.STELLAR_SECRET; if (!secret) throw new Error('Set STELLAR_SECRET'); const paidFetch = createBuyerFetch({ secret, network: 'stellar:testnet', schemes: ['exact'], }); const response = await paidFetch('http://localhost:3000/price'); if (!response.ok) throw new Error(`Paid request failed: ${response.status}`); const data = await response.json(); ``` The native paid fetch handles the challenge, signing and paid resend. Buyer secrets stay in application-owned storage. The Seller's Facilitator key is not needed by the Buyer. Omission of onBeforePaymentCreation permits automatic signing. Add the optional hook to apply application approval: ```ts onBeforePaymentCreation: async ({ selectedRequirements }) => { const approved: boolean = await approvePayment(selectedRequirements); // your application policy/UI if (!approved) return { abort: true, reason: 'Payment declined' }; }, ``` For mainnet use stellar:pubnet and an explicit mainnet rpcConfig.url. schemes defaults to both exact and upto; to enable upto signing, provide settlementContract from an independently trusted deployment, never from an untrusted Seller challenge. The SDK checks the authorization tree and trusted Kernel before signing. A transport failure or missing receipt after a paid request does not prove no charge occurred. Applications own idempotency, handler deadlines, CORS and recovery. Native hooks can explicitly recover by creating another payment and repeating business execution; choose that behavior deliberately. ## Reference integration For a complete end-to-end example, see the weather-x402 reference (https://github.com/57blocks/weather-x402): an x402-gated weather service settled through the Facilitator, including a browser wallet flow.