> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xmeta.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting Started

> Complete setup guide for merchants accepting x402 payments

## Overview

This guide walks you through setting up your merchant account to accept x402 payments via 0xmeta facilitator with pre-settlement fee collection.

<Note>
  **Trust-Minimized:** Customer payments go directly to your address. The facilitator collects a \$0.01 fee from your pre-approved USDC balance after each settlement.
</Note>

## Prerequisites

<Steps>
  <Step title="Merchant Wallet">
    An Ethereum wallet address where you'll receive customer payments
  </Step>

  <Step title="Private Key Access">
    Access to the wallet's private key (for one-time USDC approval)
  </Step>

  <Step title="Base Network Assets">
    * **ETH**: \~0.001 ETH for approval transaction gas
    * **USDC**: \~100 USDC for fees (covers \~10,000 settlements)
  </Step>

  <Step title="Network Selection">
    Choose Base Mainnet (production) or Base Sepolia (testing)
  </Step>
</Steps>

***

## Step 1: Get Testnet Assets (For Testing)

If testing on Base Sepolia first (recommended):

### Get Base Sepolia ETH

Visit the Coinbase faucet:

```
https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet
```

* Connect your merchant wallet
* Request 0.05 ETH (free, once per 24 hours)
* Wait \~30 seconds for confirmation

### Get Base Sepolia USDC

Visit the Circle faucet:

```
https://faucet.circle.com/
```

* Select "Base Sepolia"
* Enter your merchant address
* Request 10 USDC
* Wait \~1 minute for confirmation

<Check>
  Verify you received the tokens on [BaseScan
  Sepolia](https://sepolia.basescan.org)
</Check>

***

## Step 2: Approve USDC Spending

This is the **only required setup step**. You must approve 0xmeta's treasury to collect the \$0.01 fee per settlement from your USDC balance.

### Why Approval Is Required

The facilitator uses standard ERC-20 `transferFrom` to collect fees:

```solidity theme={null}
// You approve facilitator (one-time)
USDC.approve(treasury, 100 * 10^6); // 100 USDC

// Later, facilitator collects fee per settlement
USDC.transferFrom(merchant, treasury, 0.01 * 10^6); // $0.01
```

This is how the facilitator maintains x402 trust-minimization:

* ✅ Customers pay YOU directly
* ✅ Facilitator collects fee from YOUR approved balance
* ✅ No facilitator custody of customer funds

### Option A: Using Our Setup Script (Recommended)

**1. Install dependencies:**

```bash theme={null}
npm install ethers dotenv
```

**2. Configure environment:**

```bash theme={null}
# Create .env file
cat > .env << EOF
EVM_PRIVATE_KEY=0x...  # Your merchant private key
NETWORK=sepolia        # or mainnet
EOF
```

**3. Run approval:**

```bash theme={null}
node approve-facilitator.mjs
```

**Expected output:**

```
📍 Base Sepolia
   Merchant: 0xA821f428Ef8cC9f54A9915336A82220853059090
   Treasury: 0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B

💰 Approving 100 USDC for fee collection...
   Transaction: 0x123...
✅ Approval successful!
   Allowance: 100.0 USDC
   Settlements: ~10000
```

**Script source:** See [approve-facilitator.mjs](#approval-script-reference)

### Option B: Manual Approval (via Etherscan)

**1. Visit Base USDC contract:**

**Sepolia:**

```
https://sepolia.basescan.org/address/0x036CbD53842c5426634e7929541eC2318f3dCF7e#writeContract
```

**Mainnet:**

```
https://basescan.org/address/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913#writeContract
```

**2. Connect your wallet**

**3. Call `approve` function:**

* **spender:** `0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B` (Treasury)
* **amount:** `100000000` (100 USDC with 6 decimals)

**4. Confirm transaction**

<Warning>
  **Approval amount = settlements × \$0.01**

  Example: 100 USDC approval = 10,000 settlements
</Warning>

***

## Step 3: Verify Setup

Check that approval was successful:

```bash theme={null}
node check-allowance.mjs
```

**Expected output:**

```
============================================================
0xmeta Facilitator Fee Allowance Check
============================================================

👤 Merchant: 0xA821f428Ef8cC9f54A9915336A82220853059090
🏦 Treasury: 0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B

📍 Base Sepolia
   USDC Balance: 500.00 USDC
   Fee Allowance: 100.00 USDC
   Settlements Remaining: 10000
   ✅ Good

============================================================
```

**Script source:** See [check-allowance.mjs](#monitoring-script-reference)

***

## Step 4: Integrate x402 Middleware

Now you're ready to accept payments! Choose your x402 version:

### Option A: x402 v2 (Recommended)

<CodeGroup>
  ```typescript server.ts theme={null}
  import { config } from "dotenv";
  import express from "express";
  import { paymentMiddleware, x402ResourceServer } from "@x402/express";
  import { ExactEvmScheme } from "@x402/evm/exact/server";
  import { HTTPFacilitatorClient } from "@x402/core/server";

  config();

  const evmAddress = process.env.EVM_ADDRESS as `0x${string}`;
  const facilitatorUrl = "https://facilitator.0xmeta.ai/v1";

  const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl });
  const app = express();

  app.use(
    paymentMiddleware(
      {
        "GET /premium-content": {
          accepts: [{
            scheme: "exact",
            price: "$0.02",           // Your price + fee
            network: "eip155:84532",  // Base Sepolia
            payTo: evmAddress,        // YOUR address
          }],
          description: "Premium content access"
        }
      },
      new x402ResourceServer(facilitatorClient)
        .register("eip155:84532", new ExactEvmScheme())
    )
  );

  app.get("/premium-content", (req, res) => {
    res.json({ content: "This is premium content" });
  });

  app.listen(4021, () => {
    console.log("Server ready at http://localhost:4021");
  });
  ```

  ```env .env theme={null}
  # YOUR merchant address (receives customer payments)
  EVM_ADDRESS=0xA821f428Ef8cC9f54A9915336A82220853059090

  # Facilitator URL
  FACILITATOR_URL=https://facilitator.0xmeta.ai/v1
  ```

  ```bash Install theme={null}
  npm install @x402/express @x402/evm @x402/core express dotenv
  ```
</CodeGroup>

### Option B: x402 v1 (Legacy)

<CodeGroup>
  ```typescript server-v1.ts theme={null}
  import { config } from "dotenv";
  import express from "express";
  import { paymentMiddleware } from "x402-express";

  config();

  const evmAddress = process.env.EVM_ADDRESS as `0x${string}`;
  const facilitatorUrl = "https://facilitator.0xmeta.ai/v1";

  const app = express();

  app.use(
    paymentMiddleware(
      evmAddress,  // YOUR address
      {
        "GET /premium-content": {
          price: "$0.02",
          network: "base-sepolia",
        }
      },
      { url: facilitatorUrl }
    )
  );

  app.get("/premium-content", (req, res) => {
    res.json({ content: "This is premium content" });
  });

  app.listen(4021);
  ```

  ```bash Install theme={null}
  npm install x402-express express dotenv
  ```
</CodeGroup>

***

## Step 5: Test Payment Flow

### 1. Start Your Server

```bash theme={null}
npm start
```

### 2. Test with x402 Client

Create a test client (or use our example):

```typescript theme={null}
import { x402Client, wrapAxiosWithPayment } from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import axios from "axios";

const clientPrivateKey = process.env.CLIENT_PRIVATE_KEY as `0x${string}`;
const evmSigner = privateKeyToAccount(clientPrivateKey);

const client = new x402Client();
registerExactEvmScheme(client, { signer: evmSigner });

const api = wrapAxiosWithPayment(axios.create(), client);

// Make request
const response = await api.get("http://localhost:4021/premium-content");
console.log(response.data); // { content: "This is premium content" }
```

### 3. Expected Flow

```
1. ✅ Client requests /premium-content
2. ✅ Server returns 402 Payment Required
   Headers: payTo = YOUR_MERCHANT_ADDRESS
3. ✅ Client creates authorization to YOUR address
4. ✅ Client sends to facilitator
5. ✅ Facilitator verifies authorization
6. ✅ Facilitator collects $0.01 from YOUR approved balance
7. ✅ Facilitator executes: Customer → YOU ($0.02)
8. ✅ Server returns 200 OK + premium content
```

<Check>
  **Success!** If you see the premium content, your integration is working.
</Check>

***

## Step 6: Monitor Allowance

Set up regular monitoring to ensure you don't run out of approved funds:

### Manual Check

```bash theme={null}
node check-allowance.mjs
```

### Automated Monitoring

**Option 1: Cron job**

```bash theme={null}
# Check allowance daily at 9 AM
0 9 * * * cd /path/to/project && node check-allowance.mjs
```

**Option 2: Application monitoring**

```typescript theme={null}
import { ethers } from "ethers";

async function checkAllowance() {
  const provider = new ethers.JsonRpcProvider("https://mainnet.base.org");
  const usdc = new ethers.Contract(USDC_ADDRESS, USDC_ABI, provider);
  
  const allowance = await usdc.allowance(merchantAddress, treasuryAddress);
  const settlements = Math.floor(Number(ethers.formatUnits(allowance, 6)) / 0.01);
  
  if (settlements < 100) {
    alert("Low allowance! Top up soon.");
  }
  
  return settlements;
}

// Check every hour
setInterval(checkAllowance, 3600000);
```

***

## Step 7: Production Deployment

When ready for production:

### Switch to Base Mainnet

**1. Update configuration:**

```typescript theme={null}
// v2
network: "eip155:8453"  // Base Mainnet

// v1
network: "base"
```

**2. Run approval on mainnet:**

```bash theme={null}
# Get real USDC and ETH first!
NETWORK=mainnet node approve-facilitator.mjs
```

**3. Update environment:**

```env theme={null}
EVM_ADDRESS=0x...  # Your mainnet address
NETWORK=mainnet
```

### Production Checklist

<Steps>
  <Step title="Approval Confirmed">
    * [ ] Approved ≥ 100 USDC on mainnet
    * [ ] Verified via check-allowance.mjs
  </Step>

  <Step title="Testing Complete">
    * [ ] Tested full payment flow on Sepolia
    * [ ] Verified customer payments received
    * [ ] Confirmed fee collection working
  </Step>

  <Step title="Monitoring Setup">
    * [ ] Automated allowance checks configured
    * [ ] Alerts for low balance set up
    * [ ] Settlement logging in place
  </Step>

  <Step title="Security">
    * [ ] Private keys secured (not in code)
    * [ ] .env file in .gitignore
    * [ ] Reasonable approval amount (not infinite)
  </Step>
</Steps>

***

## Network Information

### Base Sepolia (Testnet)

| Resource     | Value                                                                                                                          |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| **Chain ID** | `84532`                                                                                                                        |
| **USDC**     | `0x036CbD53842c5426634e7929541eC2318f3dCF7e`                                                                                   |
| **Treasury** | `0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B`                                                                                   |
| **RPC**      | `https://sepolia.base.org`                                                                                                     |
| **Explorer** | `https://sepolia.basescan.org`                                                                                                 |
| **Faucet**   | [https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet](https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet) |

### Base Mainnet (Production)

| Resource     | Value                                        |
| ------------ | -------------------------------------------- |
| **Chain ID** | `8453`                                       |
| **USDC**     | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| **Treasury** | `0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B` |
| **RPC**      | `https://mainnet.base.org`                   |
| **Explorer** | `https://basescan.org`                       |

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Approval transaction fails">
    **Causes:**

    * Insufficient ETH for gas
    * Wrong network selected
    * Invalid treasury address

    **Solution:**

    * Check ETH balance: Must have \~0.001 ETH
    * Verify you're on correct network
    * Double-check treasury address: `0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B`
  </Accordion>

  <Accordion title="Settlement fails with 'insufficient_allowance'">
    **Cause:** Approval wasn't successful or depleted

    **Solution:**

    ```bash theme={null}
    # Check current allowance
    node check-allowance.mjs

    # If zero, run approval again
    node approve-facilitator.mjs
    ```
  </Accordion>

  <Accordion title="Can't connect to RPC">
    **Cause:** Network issues or RPC rate limiting

    **Solution:**

    * Wait a few minutes and try again
    * Use custom RPC (Alchemy, Infura, QuickNode)
    * Check Base network status
  </Accordion>

  <Accordion title="Customer payments not arriving">
    **Cause:** Wrong address in payTo

    **Solution:**
    Verify `payTo` uses YOUR merchant address (not treasury):

    ```typescript theme={null}
    // ✅ Correct
    payTo: process.env.EVM_ADDRESS  // Your address

    // ❌ Wrong
    payTo: "0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B"  // Treasury
    ```
  </Accordion>
</AccordionGroup>

***

## Script References

### Approval Script Reference

Save as `approve-facilitator.mjs`:

```javascript theme={null}
import { ethers } from "ethers";
import dotenv from "dotenv";
dotenv.config();

const NETWORKS = {
  sepolia: {
    name: "Base Sepolia",
    rpc: "https://sepolia.base.org",
    chainId: 84532,
    usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
  },
  mainnet: {
    name: "Base Mainnet",
    rpc: "https://mainnet.base.org",
    chainId: 8453,
    usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  },
};

const OXMETA_TREASURY = "0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B";
const USDC_ABI = [
  "function approve(address spender, uint256 amount) external returns (bool)",
  "function allowance(address owner, address spender) external view returns (uint256)",
];

async function main() {
  const networkKey = process.env.NETWORK || "sepolia";
  const network = NETWORKS[networkKey];
  
  const privateKey = process.env.EVM_PRIVATE_KEY;
  if (!privateKey) {
    console.error("❌ EVM_PRIVATE_KEY required");
    process.exit(1);
  }
  
  const provider = new ethers.JsonRpcProvider(network.rpc);
  const merchant = new ethers.Wallet(privateKey, provider);
  const usdc = new ethers.Contract(network.usdc, USDC_ABI, merchant);
  
  console.log(`\n📍 ${network.name}`);
  console.log(`   Merchant: ${merchant.address}`);
  console.log(`   Treasury: ${OXMETA_TREASURY}`);
  
  const approvalAmount = ethers.parseUnits("100", 6); // 100 USDC
  
  console.log(`\n💰 Approving 100 USDC...`);
  const tx = await usdc.approve(OXMETA_TREASURY, approvalAmount);
  console.log(`   Transaction: ${tx.hash}`);
  
  await tx.wait();
  console.log(`✅ Approval successful!`);
  
  const allowance = await usdc.allowance(merchant.address, OXMETA_TREASURY);
  console.log(`   Allowance: ${ethers.formatUnits(allowance, 6)} USDC`);
  console.log(`   Settlements: ~${Math.floor(Number(ethers.formatUnits(allowance, 6)) / 0.01)}`);
}

main().catch(console.error);
```

### Monitoring Script Reference

Save as `check-allowance.mjs`:

```javascript theme={null}
import { ethers } from "ethers";
import dotenv from "dotenv";
dotenv.config();

const NETWORKS = {
  sepolia: {
    name: "Base Sepolia",
    rpc: "https://sepolia.base.org",
    usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
  },
  mainnet: {
    name: "Base Mainnet",
    rpc: "https://mainnet.base.org",
    usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  },
};

const OXMETA_TREASURY = "0x5D791e3554D0e83f171126905Bda1640Bf6f9A8B";
const USDC_ABI = [
  "function allowance(address owner, address spender) external view returns (uint256)",
  "function balanceOf(address account) external view returns (uint256)",
];

async function checkNetwork(networkKey, merchantAddress) {
  const network = NETWORKS[networkKey];
  const provider = new ethers.JsonRpcProvider(network.rpc);
  const usdc = new ethers.Contract(network.usdc, USDC_ABI, provider);
  
  const [allowance, balance] = await Promise.all([
    usdc.allowance(merchantAddress, OXMETA_TREASURY),
    usdc.balanceOf(merchantAddress),
  ]);
  
  const allowanceFormatted = ethers.formatUnits(allowance, 6);
  const balanceFormatted = ethers.formatUnits(balance, 6);
  const settlements = Math.floor(Number(allowanceFormatted) / 0.01);
  
  console.log(`\n📍 ${network.name}`);
  console.log(`   USDC Balance: ${balanceFormatted} USDC`);
  console.log(`   Fee Allowance: ${allowanceFormatted} USDC`);
  console.log(`   Settlements Remaining: ${settlements}`);
  
  if (settlements < 10) {
    console.log(`   ⚠️  Low - run: NETWORK=${networkKey} node approve-facilitator.mjs`);
  } else if (settlements < 50) {
    console.log(`   ⚠️  Getting low`);
  } else {
    console.log(`   ✅ Good`);
  }
}

async function main() {
  const merchantAddress = process.env.EVM_ADDRESS;
  if (!merchantAddress) {
    console.error("❌ Set EVM_ADDRESS in .env");
    process.exit(1);
  }
  
  console.log("============================================================");
  console.log("0xmeta Facilitator Fee Allowance Check");
  console.log("============================================================");
  console.log(`\n👤 Merchant: ${merchantAddress}`);
  console.log(`🏦 Treasury: ${OXMETA_TREASURY}`);
  
  const networkArg = process.argv[2] || "both";
  
  if (networkArg === "both") {
    await checkNetwork("sepolia", merchantAddress);
    await checkNetwork("mainnet", merchantAddress);
  } else {
    await checkNetwork(networkArg, merchantAddress);
  }
  
  console.log("\n============================================================");
}

main().catch(console.error);
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="x402 Integration" icon="book" href="/x402-integration">
    Complete integration guide
  </Card>

  <Card title="Architecture" icon="diagram-project" href="/architecture">
    Understand payment flow
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Explore endpoints
  </Card>

  <Card title="FAQ" icon="question" href="/faq">
    Common questions
  </Card>
</CardGroup>

<Check>
  **You're all set!** Start accepting x402 payments with pre-settlement fee collection.
</Check>
