# x402vps Agent Integration Guide

Docker containers for AI agents. Pay with USDC on Base. No signup, no API keys.

## Quick Start

```javascript
import { x402Client, x402HTTPClient } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";

const SERVER = "https://x402vps.com";

const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");

const client = new x402Client();
registerExactEvmScheme(client, {
  signer: account,
  networks: ["eip155:8453"]
});
const httpClient = new x402HTTPClient(client);

// 1. Request container (gets 402)
const body = JSON.stringify({ plan: "atom", leaseHours: 1, image: "alpine:3.19" });
const resp1 = await fetch(`${SERVER}/api/create`, {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-Wallet": account.address },
  body
});

// 2. Parse payment requirements
const paymentRequired = JSON.parse(
  Buffer.from(resp1.headers.get("payment-required"), "base64").toString()
);

// 3. Sign payment (EIP-3009 USDC transferWithAuthorization)
const paymentPayload = await client.createPaymentPayload(paymentRequired);

// 4. Send request with payment
const headers = httpClient.encodePaymentSignatureHeader(paymentPayload);
const resp2 = await fetch(`${SERVER}/api/create`, {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-Wallet": account.address, ...headers },
  body
});

const container = await resp2.json();
// { id: "ctr_xxx", status: "running", plan: "atom", priceCharged: "$0.01" }

// 5. Exec commands (FREE)
const execResp = await fetch(`${SERVER}/api/exec`, {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-Wallet": account.address },
  body: JSON.stringify({ id: container.id, command: "echo hello world" })
});
const execResult = await execResp.json();
// { id: "ctr_xxx", exitCode: 0, output: "hello world" }
```

## How Payment Works

x402 uses HTTP 402 Payment Required. The flow:

1. Agent sends a request to a paid endpoint
2. Server returns `402` with a `PAYMENT-REQUIRED` header (base64-encoded JSON)
3. The header contains `accepts[]` with payment requirements:
   - `scheme: "exact"`
   - `network: "eip155:8453"` (Base mainnet)
   - `asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"` (USDC)
   - `amount: "10000"` (0.01 USDC = 10000 micro-USDC for atom/1hr)
   - `payTo: "0x1Ca2C4459B4a9E3Ab15A15f500568d28997ccccf"`
   - `extra.name: "USD Coin"`, `extra.version: "2"` (EIP-712 domain)
4. Agent signs an EIP-3009 `transferWithAuthorization` using their wallet
5. Agent retries the request with `PAYMENT-SIGNATURE` header
6. Server verifies via Dexter facilitator, settles onchain, returns the resource
7. Response includes `PAYMENT-RESPONSE` header with settlement details

The Dexter facilitator (https://x402.dexter.cash) sponsors gas — the agent only needs USDC, no ETH.

## Authentication

Pass your wallet address in every request:
- Header: `X-Wallet: 0xYourAddress`
- Or query param: `?wallet=0xYourAddress`

Your wallet address is your identity. Only the container owner can exec, status, extend, or destroy their containers.

## Plans

| Plan | CPU | RAM | Disk | Price/hour |
|------|-----|-----|------|------------|
| atom | 0.1 vCPU | 256 MB | 2 GB | $0.01 |
| cell | 0.25 vCPU | 512 MB | 5 GB | $0.02 |
| node | 0.5 vCPU | 1 GB | 10 GB | $0.04 |
| core | 1.0 vCPU | 2 GB | 20 GB | $0.08 |

Price = hourly rate x lease hours. Min payment: $0.01 (atom, 1 hour).

## API Reference

### GET /api
Service info, plans, and endpoint list. Free.

**Response:**
```json
{
  "name": "x402vps",
  "description": "Provision Docker containers on demand. Pay per lease with USDC.",
  "paymentEnabled": true,
  "plans": [...],
  "endpoints": {...},
  "pricing": {...}
}
```

### GET /health
Server health and uptime. Free.

**Response:**
```json
{
  "status": "ok",
  "uptime": 3600,
  "paymentEnabled": true,
  "version": "1.0.0",
  "network": "eip155:8453"
}
```

### GET /api/list
List all your containers. Free. Requires `X-Wallet` header.

### GET /api/status/:id
Get container status and remaining lease time. Free. Owner only.

**Response:**
```json
{
  "id": "ctr_4cb194843f8b",
  "dockerId": "3b41dccd...",
  "name": "x402_ctr_4cb194843f8b",
  "plan": "atom",
  "image": "alpine:3.19",
  "status": "running",
  "owner": "0x8b30...",
  "createdAt": 1784737452801,
  "expiresAt": 1784741052301,
  "leaseHours": 1
}
```

### POST /api/create
Create a Docker container. **Requires USDC payment.**

**Request body:**
```json
{
  "plan": "atom",
  "image": "alpine:3.19",
  "leaseHours": 1
}
```
- `plan`: atom, cell, node, or core (default: atom)
- `image`: any Docker image (default: alpine:3.19)
- `leaseHours`: 1 to 168 (default: 1)

**Without payment:** HTTP 402 with payment requirements in `PAYMENT-REQUIRED` header.

**With payment:** HTTP 200
```json
{
  "id": "ctr_4cb194843f8b",
  "dockerId": "3b41dccd0ebe...",
  "name": "x402_ctr_4cb194843f8b",
  "plan": "atom",
  "image": "alpine:3.19",
  "cpu": 0.1,
  "memoryMB": 256,
  "disk": "2g",
  "owner": "0x8b30...",
  "createdAt": 1784737452801,
  "expiresAt": 1784741052301,
  "leaseHours": 1,
  "status": "running",
  "priceCharged": "$0.01"
}
```

### POST /api/exec
Run a command inside a container. **Free** (rate limited: 60/min). Owner only.

**Request body:**
```json
{
  "id": "ctr_4cb194843f8b",
  "command": "uname -a"
}
```

**Response:**
```json
{
  "id": "ctr_4cb194843f8b",
  "exitCode": 0,
  "output": "Linux 3b41dccd0ebe 6.8.0-45-generic x86_64 Linux"
}
```

Exec is always free. You pay for the container lease, not per command. Run as many commands as you want within your lease.

### POST /api/extend
Extend a container lease. **Requires USDC payment.**

**Request body:**
```json
{
  "id": "ctr_4cb194843f8b",
  "hours": 24
}
```

### POST /api/destroy
Destroy a container. **Free.** Owner only.

**Request body:**
```json
{
  "id": "ctr_4cb194843f8b"
}
```

## Payment Details

| Property | Value |
|----------|-------|
| Network | Base mainnet (eip155:8453) |
| Asset | USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) |
| Decimals | 6 |
| Transfer method | EIP-3009 (transferWithAuthorization) |
| EIP-712 domain | name: "USD Coin", version: "2" |
| Facilitator | https://x402.dexter.cash |
| Fee | Free (no facilitator fees, gas sponsored) |
| x402 version | 2 |

The agent does not need ETH for gas. The Dexter facilitator sponsors gas for settlement. The agent only signs the EIP-3009 authorization (gasless) and pays USDC directly to the server's wallet.

## Rate Limits

| Limit | Value |
|-------|-------|
| Global requests | 100/min |
| Container creation | 10/hour |
| Exec commands | 60/min |
| Max lease | 168 hours (7 days) |
| Request body | 100KB |

## cURL Examples

```bash
# Check service info
curl https://x402vps.com/api

# Health check
curl https://x402vps.com/health

# List your containers
curl -H "X-Wallet: 0xYourWallet" https://x402vps.com/api/list

# Container status
curl -H "X-Wallet: 0xYourWallet" https://x402vps.com/api/status/ctr_xxx

# Exec a command (free)
curl -X POST https://x402vps.com/api/exec \
  -H "Content-Type: application/json" \
  -H "X-Wallet: 0xYourWallet" \
  -d '{"id":"ctr_xxx","command":"echo hello"}'

# Destroy container
curl -X POST https://x402vps.com/api/destroy \
  -H "Content-Type: application/json" \
  -H "X-Wallet: 0xYourWallet" \
  -d '{"id":"ctr_xxx"}'
```

## Available Docker Images

Any public Docker image works. Common choices:
- `alpine:3.19` (default — minimal, fast)
- `python:3.12-slim` (Python scripts)
- `node:22-slim` (JavaScript/Node)
- `ubuntu:24.04` (full Linux)
- `golang:1.23` (Go)

## Security

- Containers run with all Linux capabilities dropped
- Read-only root filesystem (writable /tmp)
- Isolated Docker network (no host network access)
- Banned command scanner (blocks host escalation)
- UFW + fail2ban on host
- Container auto-reaped when lease expires
