diff --git a/contracts/conditions.mdx b/contracts/conditions.mdx
index 1abf2dc..fa60d6a 100644
--- a/contracts/conditions.mdx
+++ b/contracts/conditions.mdx
@@ -670,7 +670,7 @@ config.releaseCondition = businessHours.address;
Deploy operators with conditions using the SDK.
-
+
Interact with freeze and escrow conditions via the Client SDK.
diff --git a/docs.json b/docs.json
index 3140914..9ab727f 100644
--- a/docs.json
+++ b/docs.json
@@ -55,45 +55,24 @@
]
},
{
- "group": "Client SDK",
+ "group": "Merchant",
"pages": [
- "sdk/client/quickstart",
- "sdk/client/payment-queries",
- "sdk/client/refund-operations",
- "sdk/client/escrow-management",
- "sdk/client/subscriptions"
- ]
- },
- {
- "group": "Merchant SDK",
- "pages": [
- "sdk/merchant/quickstart",
- "sdk/merchant/payment-operations",
- "sdk/merchant/refund-handling",
- "sdk/merchant/subscriptions"
- ]
- },
- {
- "group": "Arbiter SDK",
- "pages": [
- "sdk/arbiter/quickstart",
- "sdk/arbiter/decision-submission",
- "sdk/arbiter/registry",
- "sdk/arbiter/batch-operations",
- "sdk/arbiter/ai-integration",
- "sdk/arbiter/subscriptions"
+ "sdk/merchant/getting-started",
+ "sdk/helpers/refundable"
]
},
{
- "group": "Resource Server",
+ "group": "Facilitator",
"pages": [
- "sdk/helpers/refundable"
+ "sdk/facilitator/getting-started"
]
},
{
- "group": "Reference",
+ "group": "Coming Soon",
"pages": [
- "sdk/limitations"
+ "sdk/merchant/quickstart",
+ "sdk/client/quickstart",
+ "sdk/arbiter/quickstart"
]
}
]
diff --git a/index.mdx b/index.mdx
index d08f29b..dd471df 100644
--- a/index.mdx
+++ b/index.mdx
@@ -44,11 +44,11 @@ sequenceDiagram
Request refunds, freeze suspicious payments, and track payment state.
-
+
Release funds, process refunds, and manage escrow periods.
- Resolve disputes, approve/deny refund requests, and integrate AI decision-making.
+ Resolve disputes and approve/deny refund requests.
diff --git a/roadmap.mdx b/roadmap.mdx
index 7264c5b..3da3270 100644
--- a/roadmap.mdx
+++ b/roadmap.mdx
@@ -53,7 +53,7 @@ icon: "map"
### Phase 1: MVP Examples (Completed)
-- 7 examples (deploy-operator, merchant-server, merchant-cli, client-cli, arbiter-cli *(in progress)*, e2e-dispute, shared)
+- 8 examples (deploy-operator, facilitator, server-express, server-hono, merchant-cli, client-cli, arbiter-cli, shared)
- Full e2e dispute resolution flow
### Phase 2: Core SDK (Completed)
diff --git a/sdk/arbiter/quickstart.mdx b/sdk/arbiter/quickstart.mdx
index c58dd72..e4656f7 100644
--- a/sdk/arbiter/quickstart.mdx
+++ b/sdk/arbiter/quickstart.mdx
@@ -1,21 +1,21 @@
---
-title: "Arbiter Quickstart"
-description: "Get started with the X402r Arbiter SDK for dispute resolution"
+title: "Arbiter SDK"
+description: "Dispute resolution SDK for reviewing cases and making decisions (experimental)"
icon: "rocket"
---
-The `@x402r/arbiter` package provides everything arbiters need to resolve disputes: reviewing cases, making decisions, executing refunds, and integrating AI for automated resolution.
+
+The Arbiter SDK is experimental. The dispute resolution system design is actively evolving.
+
-## Installation
+
+The `@x402r/arbiter` package is not yet published on npm. Install directly from the [GitHub repository](https://github.com/BackTrackCo/x402r-sdk).
+
-```bash
-npm install @x402r/arbiter @x402r/core viem
-```
+The `@x402r/arbiter` package provides methods for arbiters to resolve disputes: reviewing refund requests, approving or denying them, and executing refunds.
## Setup
-Create viem clients as described in [Installation](/sdk/installation), then:
-
```typescript
import { X402rArbiter } from '@x402r/arbiter';
import { getNetworkConfig } from '@x402r/core';
@@ -31,119 +31,33 @@ const arbiter = new X402rArbiter({
});
```
-## Review Pending Cases
-
-Get refund requests awaiting your decision:
-
-```typescript
-// Get paginated refund requests for a receiver
-const { keys, total } = await arbiter.getPendingRefundRequests(
- 0n, // offset
- 10n, // count
- '0xReceiverAddress...' // optional: defaults to wallet account
-);
-console.log(`${total} cases to review, showing first ${keys.length}`);
-
-// Review each case
-for (const key of keys) {
- const request = await arbiter.getRefundRequestByKey(key);
- console.log(`Amount: ${request.amount}, Status: ${request.status}`);
-}
-```
-
-## Make a Decision
+## Available Methods
-Approve or deny refund requests:
+The Arbiter SDK currently supports:
-```typescript
-// Approve a refund request
-const { txHash: approveTx } = await arbiter.approveRefundRequest(paymentInfo, 0n);
-console.log('Approved:', approveTx);
+- **`approveRefundRequest()`** — Approve a pending refund request
+- **`denyRefundRequest()`** — Deny a pending refund request
+- **`executeRefundInEscrow()`** — Execute an approved refund to transfer funds back
+- **`getPendingRefundRequests()`** — List refund requests awaiting decision
+- **`getRefundRequestByKey()`** — Get details of a specific refund request
+- **`registerArbiter()`** — Register in the on-chain ArbiterRegistry
+- **`isArbiterRegistered()`** — Check registration status
-// Deny a refund request
-const { txHash: denyTx } = await arbiter.denyRefundRequest(paymentInfo, 0n);
-console.log('Denied:', denyTx);
-```
+## Try It Now
-## Execute Approved Refunds
+The easiest way to try arbiter features is with the **arbiter-cli** example, which provides a command-line interface for all arbiter operations:
-After approving, execute the refund to transfer funds back to the payer:
-
-```typescript
-// Approve the request first
-await arbiter.approveRefundRequest(paymentInfo, 0n);
-
-// Execute the refund (defaults to paymentInfo.maxAmount if no amount specified)
-const { txHash } = await arbiter.executeRefundInEscrow(paymentInfo);
-console.log('Refund executed:', txHash);
-
-// Or specify a partial refund amount
-const { txHash: partialTx } = await arbiter.executeRefundInEscrow(
- paymentInfo,
- BigInt('500000') // partial amount
-);
-```
-
-## Batch Operations
-
-Process multiple cases efficiently:
-
-```typescript
-// Approve multiple refunds
-const results = await arbiter.batchApprove([
- { paymentInfo: paymentInfo1, nonce: 0n },
- { paymentInfo: paymentInfo2, nonce: 0n },
-]);
-console.log(`Approved ${results.length} refunds`);
-
-// Deny multiple refunds
-const denyResults = await arbiter.batchDeny([
- { paymentInfo: paymentInfo3, nonce: 0n },
-]);
-```
-
-## Register as an Arbiter
-
-Register yourself in the on-chain ArbiterRegistry:
-
-```typescript
-// Register with your API endpoint
-const { txHash } = await arbiter.registerArbiter('https://arbiter.example.com/api/disputes');
-console.log('Registered:', txHash);
-
-// Check registration
-const isRegistered = await arbiter.isArbiterRegistered(account.address);
-console.log('Is registered:', isRegistered);
-```
-
-## Watch for New Cases
-
-Subscribe to incoming refund requests:
-
-```typescript
-const { unsubscribe } = arbiter.watchNewCases((event) => {
- console.log('New case:', event);
-});
-
-// Watch for decisions (status updates)
-const { unsubscribe: unsubDecisions } = arbiter.watchDecisions((event) => {
- console.log('Decision made:', event);
-});
-```
+
+ CLI tool for arbiters to review cases, make decisions, and manage registry.
+
## Next Steps
-
- Learn all decision methods including executeRefundInEscrow.
-
-
- Manage your arbiter registration and discover other arbiters.
-
-
- Process multiple cases efficiently.
+
+ See all working examples including the full payment flow.
-
- Automate with AI hooks.
+
+ Deploy a PaymentOperator with arbiter support.
diff --git a/sdk/client/quickstart.mdx b/sdk/client/quickstart.mdx
index 635029a..fba6594 100644
--- a/sdk/client/quickstart.mdx
+++ b/sdk/client/quickstart.mdx
@@ -1,21 +1,21 @@
---
-title: "Client Quickstart"
-description: "Get started with the X402r Client SDK for payer integrations"
+title: "Client SDK"
+description: "Payer-side SDK for refunds, freezes, and escrow management (experimental)"
icon: "rocket"
---
-The `@x402r/client` package provides everything payers need to interact with X402r payments: requesting refunds, freezing payments, and managing escrow.
+
+The Client SDK is experimental. APIs will change as the refund and dispute system design evolves.
+
-## Installation
+
+The `@x402r/client` package is not yet published on npm. Install directly from the [GitHub repository](https://github.com/BackTrackCo/x402r-sdk).
+
-```bash
-npm install @x402r/client @x402r/core viem
-```
+The `@x402r/client` package provides payer-side methods for interacting with X402r payments: requesting refunds, freezing payments, and querying escrow state.
## Setup
-Create viem clients as described in [Installation](/sdk/installation), then:
-
```typescript
import { X402rClient } from '@x402r/client';
import { getNetworkConfig } from '@x402r/core';
@@ -31,97 +31,32 @@ const client = new X402rClient({
});
```
-## Request a Refund
-
-Submit a refund request for a payment that is in escrow:
-
-```typescript
-// Request refund for the first charge (nonce = 0n)
-const { txHash } = await client.requestRefund(
- paymentInfo,
- BigInt('1000000'), // amount to refund (e.g., 1 USDC)
- 0n // nonce: identifies which charge
-);
-console.log(`Refund requested: ${txHash}`);
-
-// Check refund status
-const status = await client.getRefundStatus(paymentInfo, 0n);
-console.log(`Refund status: ${status}`);
-// 0 = Pending, 1 = Approved, 2 = Denied, 3 = Cancelled
-```
-
-## Check Escrow Period
-
-Query whether the payment is still within its escrow period:
-
-```typescript
-const escrowPeriodAddress = '0x...'; // EscrowPeriod contract address
-
-// Check if still within escrow period
-const inEscrow = await client.isDuringEscrowPeriod(paymentInfo, escrowPeriodAddress);
-if (inEscrow) {
- console.log('Still in escrow period - can request refund');
-} else {
- console.log('Escrow period passed - funds can be released');
-}
-
-// Get when the payment was authorized
-const authTime = await client.getAuthorizationTime(paymentInfo, escrowPeriodAddress);
-console.log(`Authorized at: ${new Date(Number(authTime) * 1000)}`);
-```
-
-## Freeze a Payment
+## Available Methods
-Freeze a payment to prevent release while a dispute is resolved:
+The Client SDK currently supports:
-```typescript
-const freezeAddress = '0x...'; // Freeze contract address
+- **`requestRefund()`** — Submit a refund request for a payment in escrow
+- **`getRefundStatus()`** — Check the status of a refund request
+- **`freezePayment()`** — Freeze a payment to prevent release during a dispute
+- **`isFrozen()`** — Check if a payment is frozen
+- **`isDuringEscrowPeriod()`** — Check if a payment is still in its escrow window
+- **`getAuthorizationTime()`** — Get when a payment was authorized
-// Freeze the payment (only payer can do this)
-const { txHash } = await client.freezePayment(paymentInfo, freezeAddress);
-console.log(`Payment frozen: ${txHash}`);
+## Try It Now
-// Check if payment is frozen
-const frozen = await client.isFrozen(paymentInfo, freezeAddress);
-console.log(`Frozen: ${frozen}`);
-```
+The easiest way to try client features is with the **client-cli** example, which provides a command-line interface for all client operations:
-## Watch for Updates
-
-Subscribe to real-time events:
-
-```typescript
-// Watch payment state changes (releases, refunds)
-const { unsubscribe } = client.watchPaymentState(
- paymentInfoHash,
- (event) => {
- console.log('Payment event:', event.eventName);
- }
-);
-
-// Watch for refund request updates
-const { unsubscribe: unsubRefunds } = client.watchRefundRequests((event) => {
- console.log('Refund event:', event.eventName);
-});
-
-// Later: stop watching
-unsubscribe();
-unsubRefunds();
-```
+
+ CLI tool for payers to `pay`, `preview-fee`, request refunds, freeze payments, and check status.
+
## Next Steps
-
- Learn about payment query methods (including stubbed methods pending subgraph).
-
-
- Deep dive into refund workflows.
-
-
- Manage freeze and escrow timing.
+
+ See all working examples including the full payment flow.
-
- Real-time event watching.
+
+ Deploy a PaymentOperator to test client operations against.
diff --git a/sdk/concepts.mdx b/sdk/concepts.mdx
index 712fd21..3b66c61 100644
--- a/sdk/concepts.mdx
+++ b/sdk/concepts.mdx
@@ -197,11 +197,8 @@ flowchart TB
Deploy your own PaymentOperator with all supporting contracts.
-
- Build payer-side integrations.
-
-
- Add refund support to your server.
+
+ Working examples for merchants, clients, and arbiters.
Understand the underlying contract architecture.
diff --git a/sdk/deploy-operator.mdx b/sdk/deploy-operator.mdx
index 91c9374..b02996f 100644
--- a/sdk/deploy-operator.mdx
+++ b/sdk/deploy-operator.mdx
@@ -144,11 +144,8 @@ Deployment requires gas fees. Ensure your wallet has ETH on the target network.
## Next Steps
-
- Use the operator address with the Client SDK.
-
-
- Release funds and handle refunds.
+
+ See working merchant and client examples.
Mark payment options as refundable with your operator.
diff --git a/sdk/examples.mdx b/sdk/examples.mdx
index 1cc76ba..44df86f 100644
--- a/sdk/examples.mdx
+++ b/sdk/examples.mdx
@@ -9,26 +9,29 @@ The SDK includes working examples in the `x402r-sdk/` repository. Each is a stan
## Examples
-
- HTTP service implementing x402's facilitator protocol for escrow payments. Handles signature verification and on-chain settlement.
+
+ Operator-agnostic HTTP service implementing x402's facilitator protocol for escrow payments. Handles signature verification and on-chain settlement.
Deploy a complete marketplace operator with escrow, freeze, and arbiter support.
-
- HTTP server that accepts escrow payments via x402's standard `paymentMiddleware`. Delegates verify/settle to the facilitator service.
+
+ Express merchant server using `EscrowServerScheme`, `HTTPFacilitatorClient`, and `refundable()` to accept escrow payments via x402 middleware.
-
- CLI tool for merchants to release payments, approve/deny refunds, and query state.
+
+ Hono merchant server using `EscrowServerScheme`, `HTTPFacilitatorClient`, and `refundable()` to accept escrow payments via x402 middleware.
-
- CLI tool for payers to request refunds, freeze payments, and check status.
+
+ CLI tool for merchants to release payments, approve/deny refunds, and query escrow state.
-
- CLI tool for arbiters to review cases, make decisions, and manage registry. This example is under active development.
+
+ CLI tool for payers to `pay`, `preview-fee`, request refunds, freeze payments, and check status.
-
- Shared utilities used by the CLI examples (display helpers, PaymentInfo formatting).
+
+ CLI tool for arbiters to review cases, make decisions, and manage registry.
+
+
+ Shared utilities used by the CLI examples: `parsePaymentInfo`, `shortAddress`, `formatUSDC`.
@@ -41,24 +44,28 @@ All examples require a private key with Base Sepolia ETH and USDC. See [Base net
The full payment flow requires the facilitator to be running before the merchant server:
```bash
-# 1. Start the facilitator service
-cd x402r-sdk/examples/facilitator
-cp .env.example .env # Set PRIVATE_KEY + OPERATOR_ADDRESS
-pnpm dev
-
-# 2. Start the merchant server (new terminal)
-cd x402r-sdk/examples/merchant-server
-cp .env.example .env # Set PRIVATE_KEY, OPERATOR_ADDRESS, FACILITATOR_URL
-pnpm dev
-
-# 3. Make a payment (new terminal)
-cd x402r-sdk/examples/client-cli
-cp .env.example .env # Set PRIVATE_KEY
-pnpm start pay --url http://localhost:3000/weather
+# All commands run from the x402r-sdk/ root directory
+
+# 1. Set up environment files
+cp examples/facilitator/basic/.env-local examples/facilitator/basic/.env
+# Edit .env — set PRIVATE_KEY
+
+cp examples/servers/express/.env-local examples/servers/express/.env
+# Edit .env — set ADDRESS, OPERATOR_ADDRESS, FACILITATOR_URL
+
+# 2. Start the facilitator (port 4022)
+pnpm example:facilitator
+
+# 3. Start the merchant server (new terminal, port 4021)
+pnpm example:server:express
+# Or: pnpm example:server:hono
+
+# 4. Make a payment (new terminal)
+pnpm example:client-cli pay --url http://localhost:4021/weather
```
-The facilitator must be running before the merchant server starts, as the merchant delegates payment verification and settlement to it.
+The facilitator must be running before the merchant server (Express or Hono) starts, as the merchant delegates payment verification and settlement to it.
## deploy-operator
@@ -83,9 +90,9 @@ const result = await deployMarketplaceOperator(
See [Deploy an Operator](/sdk/deploy-operator) for the full guide.
-## merchant-server
+## Server Examples
-Demonstrates a minimal HTTP server that uses x402's standard middleware:
+Demonstrates minimal merchant servers (Express and Hono variants) that use `EscrowServerScheme`, `HTTPFacilitatorClient`, and `refundable()` via x402's standard middleware:
1. Returns 402 with `refundable()` payment options
2. Delegates payment verification to the facilitator via `HTTPFacilitatorClient`
@@ -95,14 +102,14 @@ Demonstrates a minimal HTTP server that uses x402's standard middleware:
## Next Steps
-
- Build a payer integration.
+
+ Deploy a PaymentOperator with escrow and freeze support.
-
- Build a merchant integration.
+
+ Mark payment options as refundable with escrow configuration.
-
- Build an arbiter integration.
+
+ Understand the payment lifecycle and key concepts.
Browse all examples on GitHub.
diff --git a/sdk/facilitator/getting-started.mdx b/sdk/facilitator/getting-started.mdx
new file mode 100644
index 0000000..e30d702
--- /dev/null
+++ b/sdk/facilitator/getting-started.mdx
@@ -0,0 +1,174 @@
+---
+title: "Facilitator Quickstart"
+description: "Run your own x402r facilitator service to verify and settle escrow payments"
+icon: "server"
+---
+
+
+The X402r SDK packages are not yet published on npm. Install directly from the [GitHub repository](https://github.com/BackTrackCo/x402r-sdk). See [Installation](/sdk/installation) for details.
+
+
+A facilitator is a service that verifies payment signatures and settles escrow transactions on-chain. This guide walks you through running your own facilitator on Base Sepolia.
+
+
+The full source code for this example is available on [GitHub](https://github.com/BackTrackCo/x402r-sdk/tree/main/examples/facilitator/basic).
+
+
+## Prerequisites
+
+- Node.js 20+
+- A wallet private key with Base Sepolia ETH
+
+
+Never commit private keys to source control. Use environment variables or a secrets manager.
+
+
+## Setup
+
+
+
+ ```bash
+ mkdir facilitator && cd facilitator
+ npm init -y
+ npm install @x402/core @x402/evm @x402r/evm express dotenv viem
+ ```
+
+
+
+ Create a `.env` file in the project root:
+
+ ```bash
+ PRIVATE_KEY=0xYourPrivateKey
+ PORT=4022
+ ```
+
+
+
+ Create `index.ts`:
+
+ ```typescript
+ import "dotenv/config";
+ import express from "express";
+ import { x402Facilitator } from "@x402/core/facilitator";
+ import { PaymentPayload, PaymentRequirements } from "@x402/core/types";
+ import { toFacilitatorEvmSigner } from "@x402/evm";
+ import { registerEscrowScheme } from "@x402r/evm/escrow/facilitator";
+ import { createWalletClient, http, publicActions } from "viem";
+ import { privateKeyToAccount } from "viem/accounts";
+ import { baseSepolia } from "viem/chains";
+
+ if (!process.env.PRIVATE_KEY) {
+ console.error("PRIVATE_KEY environment variable is required");
+ process.exit(1);
+ }
+
+ const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
+ console.info(`Facilitator account: ${account.address}`);
+
+ const viemClient = createWalletClient({
+ account,
+ chain: baseSepolia,
+ transport: http(),
+ }).extend(publicActions);
+
+ const evmSigner = toFacilitatorEvmSigner({
+ address: account.address,
+ getCode: (args) => viemClient.getCode(args),
+ readContract: (args) => viemClient.readContract({ ...args, args: args.args || [] }),
+ verifyTypedData: (args) => viemClient.verifyTypedData(args as any),
+ writeContract: (args) => viemClient.writeContract({ ...args, args: args.args || [] }),
+ sendTransaction: (args) => viemClient.sendTransaction(args),
+ waitForTransactionReceipt: (args) => viemClient.waitForTransactionReceipt(args),
+ });
+
+ const facilitator = new x402Facilitator();
+
+ registerEscrowScheme(facilitator, {
+ signer: evmSigner,
+ networks: "eip155:84532",
+ });
+
+ const app = express();
+ app.use(express.json());
+
+ app.post("/verify", async (req, res) => {
+ const { paymentPayload, paymentRequirements } = req.body as {
+ paymentPayload: PaymentPayload;
+ paymentRequirements: PaymentRequirements;
+ };
+ const response = await facilitator.verify(paymentPayload, paymentRequirements);
+ res.json(response);
+ });
+
+ app.post("/settle", async (req, res) => {
+ const { paymentPayload, paymentRequirements } = req.body;
+ const response = await facilitator.settle(
+ paymentPayload as PaymentPayload,
+ paymentRequirements as PaymentRequirements,
+ );
+ res.json(response);
+ });
+
+ app.get("/supported", async (req, res) => {
+ const response = facilitator.getSupported();
+ res.json(response);
+ });
+
+ const PORT = process.env.PORT || "4022";
+ app.listen(parseInt(PORT), () => {
+ console.log(`Facilitator listening on http://localhost:${PORT}`);
+ });
+ ```
+
+
+
+ ```bash
+ npx tsx index.ts
+ ```
+
+ You should see:
+ ```
+ Facilitator account: 0x...
+ Facilitator listening on http://localhost:4022
+ ```
+
+
+
+ ```bash
+ curl http://localhost:4022/supported
+ ```
+
+ The response lists supported payment schemes and networks:
+
+ ```json
+ {
+ "supportedSchemes": {
+ "escrow": {
+ "networks": ["eip155:84532"]
+ }
+ }
+ }
+ ```
+
+
+
+## How it works
+
+- **`x402Facilitator`** is the core facilitator class from `@x402/core` that routes verify and settle requests to registered scheme handlers.
+- **`registerEscrowScheme`** adds x402r escrow support to the facilitator, enabling it to verify escrow payment signatures and settle them on-chain.
+- **`toFacilitatorEvmSigner`** adapts a viem wallet client into the signer interface the facilitator expects for on-chain interactions.
+- The three endpoints (`/verify`, `/settle`, `/supported`) match the interface that `HTTPFacilitatorClient` on the merchant side expects.
+
+## Next Steps
+
+
+
+ Set up a merchant server that uses your facilitator.
+
+
+ Understand the payment lifecycle and escrow flow.
+
+
+ Deploy a PaymentOperator contract for your merchant.
+
+
diff --git a/sdk/helpers/refundable.mdx b/sdk/helpers/refundable.mdx
index d75a539..16839b9 100644
--- a/sdk/helpers/refundable.mdx
+++ b/sdk/helpers/refundable.mdx
@@ -4,6 +4,10 @@ description: "Configure HTTP 402 responses with escrow-backed refundable payment
icon: "wrench"
---
+
+The X402r SDK packages are not yet published on npm. Install directly from the [GitHub repository](https://github.com/BackTrackCo/x402r-sdk). See [Installation](/sdk/installation) for details.
+
+
The `@x402r/helpers` package provides the `refundable()` function — a framework-agnostic helper that adds escrow configuration to x402 payment options.
@@ -161,13 +165,10 @@ app.get('/api/resource', (req, res) => {
Deploy a PaymentOperator to use with refundable().
-
- Full merchant integration guide.
+
+ See merchant server examples using refundable().
Understand the escrow scheme.
-
- Current SDK constraints.
-
diff --git a/sdk/installation.mdx b/sdk/installation.mdx
index 230bc15..f63fbb3 100644
--- a/sdk/installation.mdx
+++ b/sdk/installation.mdx
@@ -4,6 +4,10 @@ description: "Install and configure the X402r SDK packages"
icon: "download"
---
+
+The X402r SDK packages are not yet published on npm. Install directly from the [GitHub repository](https://github.com/BackTrackCo/x402r-sdk) using your package manager's Git URL support, or clone the repo and link locally.
+
+
## Install Packages
Install only the packages you need for your use case:
@@ -29,11 +33,6 @@ Install only the packages you need for your use case:
npm install @x402r/helpers @x402r/core viem
```
-
- ```bash
- npm install @x402r/client @x402r/merchant @x402r/arbiter @x402r/helpers @x402r/core viem
- ```
-
## Setup viem Clients
@@ -63,37 +62,13 @@ Network identifiers use the [EIP-155](https://eips.ethereum.org/EIPS/eip-155) fo
Never commit private keys to version control. Use environment variables or a secrets manager.
-## Quick Verification
-
-Verify your setup by querying refund status for a payment:
-
-```typescript
-import { X402rClient } from '@x402r/client';
-
-const client = new X402rClient({
- publicClient,
- operatorAddress: '0x...', // Your PaymentOperator address
- refundRequestAddress: config.refundRequest,
-});
-
-// Check if a refund request exists for a payment
-const hasRequest = await client.hasRefundRequest(paymentInfo, 0n);
-console.log('Has refund request:', hasRequest);
-```
-
## Next Steps
Learn about payment states, escrow, and the refund lifecycle.
-
- Start building as a payer/client.
-
-
- Integrate refunds into your server.
-
-
- Build a dispute resolution system.
+
+ Working examples for merchants, clients, and arbiters.
diff --git a/sdk/merchant/getting-started.mdx b/sdk/merchant/getting-started.mdx
new file mode 100644
index 0000000..a622666
--- /dev/null
+++ b/sdk/merchant/getting-started.mdx
@@ -0,0 +1,171 @@
+---
+title: "Merchant Server Quickstart"
+description: "Accept escrow-backed refundable payments on your Express server in 5 minutes"
+icon: "store"
+---
+
+
+The X402r SDK packages are not yet published on npm. Install directly from the [GitHub repository](https://github.com/BackTrackCo/x402r-sdk). See [Installation](/sdk/installation) for details.
+
+
+This guide walks you through setting up an Express server that accepts x402r escrow-backed payments. By the end, you'll have a paid API endpoint protected by the x402 payment middleware with refundable escrow support.
+
+
+The full source code for this example is available on [GitHub](https://github.com/BackTrackCo/x402r-sdk/tree/main/examples/servers/express).
+
+
+## Prerequisites
+
+- Node.js 20+
+- A deployed PaymentOperator contract ([Deploy Operator](/sdk/deploy-operator))
+- A running facilitator service ([Facilitator Quickstart](/sdk/facilitator/getting-started))
+- Base Sepolia ETH for testing
+
+## Setup
+
+
+
+ ```bash
+ mkdir merchant-server && cd merchant-server
+ npm init -y
+ npm install express @x402/core @x402/express @x402r/evm @x402r/helpers dotenv
+ ```
+
+
+
+ Create a `.env` file in the project root:
+
+ ```bash
+ ADDRESS=0xYourMerchantAddress
+ OPERATOR_ADDRESS=0xYourPaymentOperatorAddress
+ FACILITATOR_URL=http://localhost:4022
+ ```
+
+
+
+ Create `index.ts`:
+
+ ```typescript
+ import "dotenv/config";
+ import express from "express";
+ import { paymentMiddleware, x402ResourceServer } from "@x402/express";
+ import { EscrowServerScheme } from "@x402r/evm/escrow/server";
+ import { refundable } from "@x402r/helpers";
+ import { HTTPFacilitatorClient } from "@x402/core/server";
+
+ const address = process.env.ADDRESS as `0x${string}`;
+ const operatorAddress = process.env.OPERATOR_ADDRESS as `0x${string}`;
+ if (!address || !operatorAddress) {
+ console.error("Missing required environment variables: ADDRESS, OPERATOR_ADDRESS");
+ process.exit(1);
+ }
+
+ const facilitatorUrl = process.env.FACILITATOR_URL;
+ if (!facilitatorUrl) {
+ console.error("FACILITATOR_URL environment variable is required");
+ process.exit(1);
+ }
+ const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl });
+
+ const app = express();
+
+ app.use(
+ paymentMiddleware(
+ {
+ "GET /weather": {
+ accepts: [
+ refundable(
+ {
+ scheme: "escrow",
+ price: "$0.01",
+ network: "eip155:84532",
+ payTo: address,
+ },
+ operatorAddress,
+ ),
+ ],
+ description: "Weather data",
+ mimeType: "application/json",
+ },
+ },
+ new x402ResourceServer(facilitatorClient).register(
+ "eip155:84532",
+ new EscrowServerScheme() as never,
+ ),
+ ),
+ );
+
+ app.get("/weather", (req, res) => {
+ res.send({
+ report: { weather: "sunny", temperature: 70 },
+ });
+ });
+
+ app.listen(4021, () => {
+ console.log("Server listening at http://localhost:4021");
+ });
+ ```
+
+
+
+ ```bash
+ npx tsx index.ts
+ ```
+
+ You should see:
+ ```
+ Server listening at http://localhost:4021
+ ```
+
+
+
+ ```bash
+ curl http://localhost:4021/weather
+ ```
+
+ Without a valid payment header, the server responds with HTTP 402 and the escrow payment requirements:
+
+ ```json
+ {
+ "x402Version": 2,
+ "accepts": [{
+ "scheme": "escrow",
+ "price": "$0.01",
+ "network": "eip155:84532",
+ "payTo": "0x...",
+ "extra": {
+ "escrowAddress": "0x...",
+ "operatorAddress": "0x...",
+ "tokenCollector": "0x...",
+ "minFeeBps": 0,
+ "maxFeeBps": 1000
+ }
+ }]
+ }
+ ```
+
+
+
+## How it works
+
+- **`refundable()`** wraps a standard x402 payment option with escrow configuration (contract addresses, fee bounds) from the network config.
+- **`EscrowServerScheme`** registers the escrow payment scheme with the x402 resource server so it can validate escrow-backed payments.
+- **`paymentMiddleware`** intercepts requests, checks for a valid payment header, and returns 402 if no payment is provided.
+- **`HTTPFacilitatorClient`** connects to the facilitator service that verifies and settles payments on-chain.
+
+## Next Steps
+
+
+
+ Configure escrow options and fee bounds.
+
+
+ Release payments, handle refunds, and manage escrow.
+
+
+ Deploy your own PaymentOperator contract.
+
+
+ Run your own facilitator service.
+
+
diff --git a/sdk/merchant/quickstart.mdx b/sdk/merchant/quickstart.mdx
index fe672d7..8c3ac70 100644
--- a/sdk/merchant/quickstart.mdx
+++ b/sdk/merchant/quickstart.mdx
@@ -1,5 +1,5 @@
---
-title: "Merchant Quickstart"
+title: "Merchant SDK"
description: "Get started with the X402r Merchant SDK for server integrations"
icon: "rocket"
---
@@ -7,7 +7,7 @@ icon: "rocket"
The `@x402r/merchant` package provides everything merchants need to handle X402r payments: releasing funds, charging, processing refunds, and managing escrow.
-**Most merchants start here:** The [merchant-server example](/sdk/examples#merchant-server) shows how to accept escrow payments via HTTP middleware. This SDK (`@x402r/merchant`) is for post-payment lifecycle -- releasing funds, handling refund requests, and managing escrow.
+**Most merchants start here:** The [server examples](/sdk/examples#server-examples) show how to accept escrow payments via HTTP middleware. This SDK (`@x402r/merchant`) is for post-payment lifecycle -- releasing funds, handling refund requests, and managing escrow.
## Installation
diff --git a/sdk/overview.mdx b/sdk/overview.mdx
index 83dcbba..83157a8 100644
--- a/sdk/overview.mdx
+++ b/sdk/overview.mdx
@@ -12,9 +12,9 @@ The X402r SDK provides a complete TypeScript implementation for integrating with
## Packages
-The SDK is organized into five packages, each designed for a specific role in the payment ecosystem:
+The SDK is organized into packages designed for specific roles in the payment ecosystem:
-
+
Shared types, ABIs, network config, deploy utilities, and condition builders.
@@ -24,35 +24,14 @@ The SDK is organized into five packages, each designed for a specific role in th
SDK for merchants to release payments, charge, and handle refunds.
-
- SDK for arbiters to resolve disputes, manage registry, and automate decisions with AI.
+
+ SDK for arbiters to resolve disputes and manage refund decisions.
+
+
+ Framework-agnostic helper to mark x402 payment options as refundable with escrow configuration.
-
- Framework-agnostic helper to mark x402 payment options as refundable with escrow configuration.
-
-
-## Key Features
-
-
-
- Built on [viem](https://viem.sh) for fully typed interactions with X402r smart contracts. All ABIs are exported with complete TypeScript types.
-
-
- Real-time event watching for payment state changes, refund requests, and freeze events across all packages.
-
-
- Built-in hooks for integrating AI models into dispute resolution workflows with structured evaluation contexts.
-
-
- `deployMarketplaceOperator()` deploys all necessary contracts (operator, escrow period, freeze, conditions) in a single call.
-
-
- On-chain registry for arbiters to register, update metadata, and be discovered by merchants and clients.
-
-
-
## Network Support
| Network | Chain ID | Status |
@@ -72,7 +51,7 @@ The SDK is organized into five packages, each designed for a specific role in th
Deploy a PaymentOperator with one function call.
-
- Source code and examples.
+
+ Working examples for merchants, clients, and arbiters.