{"_id":"@apitoll/facilitator","name":"@apitoll/facilitator","dist-tags":{"beta":"0.1.0-beta.4","latest":"0.1.0-beta.4"},"versions":{"0.1.0-beta.4":{"name":"@apitoll/facilitator","version":"0.1.0-beta.4","description":"x402 facilitator service - handles HTTP 402 payment flows for agent-to-tool micropayments","type":"module","main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"homepage":"https://apitoll.com","bugs":{"url":"https://github.com/TasnidChain/APITOLL/issues"},"repository":{"type":"git","url":"git+https://github.com/TasnidChain/APITOLL.git","directory":"packages/facilitator"},"publishConfig":{"access":"public"},"scripts":{"build":"tsc","dev":"tsx watch src/server.ts","start":"node dist/server.js","test":"vitest"},"keywords":["x402","facilitator","payments","micropayments","http-402","agent-commerce"],"dependencies":{"@apitoll/shared":"0.1.0-beta.4","@sentry/node":"^10.38.0","@solana/spl-token":"^0.4.14","@solana/web3.js":"^1.98.4","convex":"^1.17.0","dotenv":"^16.3.1","ethers":"^6.10.0","express":"^4.18.2","pino":"^8.17.0","uuid":"^9.0.0","zod":"^3.22.0"},"devDependencies":{"@types/express":"^4.17.17","@types/node":"^20.0.0","@types/supertest":"^6.0.2","@types/uuid":"^9.0.0","supertest":"^6.3.4","tsx":"^4.7.0","typescript":"^5.4.0","vitest":"^1.6.0"},"gitHead":"afed4969029317b5a5d356041f5c8ee016ad66cb","_id":"@apitoll/facilitator@0.1.0-beta.4","_nodeVersion":"25.5.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-wbVdSf+Pm/ef6PCnxulQG1E/6ErLMP2/tlJq6K1eMH6IwoHns/y8cSmdD33+DIEtdcTPo2B4M+OPganfmtjpPQ==","shasum":"65cdaa6292fcef088b4f9a58b3caa7d2e5d84efb","tarball":"https://registry.npmjs.org/@apitoll/facilitator/-/facilitator-0.1.0-beta.4.tgz","fileCount":11,"unpackedSize":62620,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDYpSEIL8vZQw1vfgry45VUSjXuy0hs0oQ1IvZJXfmmywIhAKQ8kUkYOPcywKkUP69SmvGa5xWQ8Zr7duqZSR1n9D1W"}]},"_npmUser":{"name":"texbeneche","email":"RizqClawd@gmail.com"},"directories":{},"maintainers":[{"name":"texbeneche","email":"RizqClawd@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/facilitator_0.1.0-beta.4_1770824756229_0.6131444791509548"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-11T15:45:56.123Z","0.1.0-beta.4":"2026-02-11T15:45:56.378Z","modified":"2026-02-11T15:45:56.607Z"},"maintainers":[{"name":"texbeneche","email":"RizqClawd@gmail.com"}],"description":"x402 facilitator service - handles HTTP 402 payment flows for agent-to-tool micropayments","homepage":"https://apitoll.com","keywords":["x402","facilitator","payments","micropayments","http-402","agent-commerce"],"repository":{"type":"git","url":"git+https://github.com/TasnidChain/APITOLL.git","directory":"packages/facilitator"},"bugs":{"url":"https://github.com/TasnidChain/APITOLL/issues"},"readme":"# @apitoll/facilitator\n\nx402 facilitator service — handles HTTP 402 payment flows for AI agents making micropayments to services.\n\n## What It Does\n\nWhen an agent receives an HTTP 402 \"Payment Required\" response from a tool/API:\n\n1. **Receives the 402 response** with payment requirements\n2. **Initiates payment** (POST /pay) — sends USDC to the seller via custodial wallet\n3. **Tracks payment status** (GET /pay/:id) — polls blockchain for confirmation\n4. **Forwards to seller** (POST /forward/:id) — retries original request with payment receipt\n\n## Installation\n\n```bash\nnpm install @apitoll/facilitator\n```\n\n## Quick Start\n\n### 1. Set Environment Variables\n\n```bash\n# Required\nFACILITATOR_PRIVATE_KEY=0x...           # Custodial hot wallet private key\nBASE_RPC_URL=https://mainnet.base.org   # or Alchemy/Infura endpoint\n\n# Security (required in production)\nFACILITATOR_API_KEYS=key1,key2,key3     # Comma-separated API keys for auth\nALLOWED_ORIGINS=https://apitoll.com     # CORS whitelist\n\n# Optional\nPORT=3000\n```\n\n### 2. Start the Facilitator Service\n\n```bash\nnpm start\n# Listens on http://localhost:3000\n```\n\n### 3. Initiate a Payment\n\n```bash\ncurl -X POST http://localhost:3000/pay \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Authorization: Bearer your-api-key\" \\\n  -d '{\n    \"original_url\": \"https://api.example.com/weather?location=nyc\",\n    \"original_method\": \"GET\",\n    \"payment_required\": {\n      \"amount\": \"0.005\",\n      \"currency\": \"USDC\",\n      \"recipient\": \"0x123...\",\n      \"chain\": \"base\"\n    },\n    \"agent_wallet\": \"0x456...\"\n  }'\n```\n\nResponse:\n```json\n{\n  \"payment_id\": \"uuid-here\",\n  \"status\": \"processing\",\n  \"check_url\": \"/pay/uuid-here\"\n}\n```\n\n### 4. Check Payment Status\n\n```bash\ncurl http://localhost:3000/pay/uuid-here \\\n  -H \"Authorization: Bearer your-api-key\"\n```\n\n### 5. Forward to Seller\n\n```bash\ncurl -X POST http://localhost:3000/forward/uuid-here \\\n  -H \"Authorization: Bearer your-api-key\"\n```\n\nThe facilitator forwards the original request to the seller with `X-PAYMENT` and `X-PAYMENT-TX-HASH` headers containing the payment receipt, and returns the seller's response.\n\n## How It Works\n\n### Payment Flow\n\n```\nAgent receives HTTP 402 from seller\n         |\nAgent -> Facilitator (POST /pay with Authorization header)\n         |\n    Validates request with Zod schemas\n    Checks amount safety cap ($100 max)\n    Executes USDC transfer from custodial wallet\n    Waits for 2 block confirmations on Base L2\n         |\nAgent <- Status endpoint (GET /pay/:id)\n         |\nAgent -> Facilitator (POST /forward/:id)\n         |\nFacilitator -> Seller (original request + X-PAYMENT receipt header)\n         |\nAgent <- Seller response (proxied through facilitator)\n```\n\n### Payment Modes\n\n1. **Custodial (default)**: The facilitator holds a hot wallet (`FACILITATOR_PRIVATE_KEY`) that agents pre-fund. Agents never send private keys.\n\n2. **Self-custody**: Agents can provide a pre-signed transaction in `signed_tx` field. The facilitator just broadcasts it.\n\n## Architecture\n\n### Endpoints\n\n**GET /health** (no auth)\n- Health check with pending payment count\n\n**POST /pay** (auth required)\n- Initiates payment via Zod-validated request\n- Returns: payment_id + status (202 Accepted)\n- Safety cap: $100 max per payment\n\n**GET /pay/:paymentId** (auth required)\n- Check payment status\n- Returns: status, tx_hash, error (if failed)\n\n**POST /forward/:paymentId** (auth required)\n- Forward original request to seller with receipt\n- Only works after payment confirmed\n- Returns: seller response + receipt\n\n### Security\n\n- **API key authentication** on all payment endpoints (Bearer token)\n- **No private keys in requests** — uses custodial wallet or pre-signed transactions\n- **Zod validation** on all request bodies\n- **Amount safety cap** — $100 max per payment (configurable)\n- **Rate limiting** — 30 requests/minute per API key\n- **CORS** — configurable allowed origins\n- **Security headers** — X-Content-Type-Options, X-Frame-Options, HSTS, etc.\n- **Error sanitization** — internal errors never leak to clients\n- **Graceful shutdown** — SIGTERM/SIGINT handling\n\n### State Management\n\n- **In-memory store** (development) — auto-cleans stale entries after 24h\n- **Redis** (recommended for production) — TODO: persistent across restarts\n\n## Integration with Agents\n\n### Using with Buyer SDK\n\n```typescript\nimport { createAgentWallet } from '@apitoll/buyer-sdk';\n\nconst agent = createAgentWallet({\n  name: 'ResearchBot',\n  chain: 'base',\n  policies: [{ type: 'budget', dailyCap: 50, maxPerRequest: 0.10 }],\n});\n\n// When receiving 402 response, call the facilitator:\nconst payRes = await fetch('http://facilitator:3000/pay', {\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json',\n    'Authorization': 'Bearer your-api-key',\n  },\n  body: JSON.stringify({\n    original_url: 'https://api.weather.pro/forecast',\n    original_method: 'GET',\n    payment_required: { amount: '0.005', recipient: '0x...', chain: 'base' },\n    agent_wallet: agent.address,\n  }),\n});\n\nconst { payment_id } = await payRes.json();\n\n// Poll for completion, then forward\nconst forwardRes = await fetch(`http://facilitator:3000/forward/${payment_id}`, {\n  method: 'POST',\n  headers: { 'Authorization': 'Bearer your-api-key' },\n});\nconst { seller_response } = await forwardRes.json();\n```\n\n## Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `FACILITATOR_PRIVATE_KEY` | Yes | — | Custodial hot wallet private key |\n| `BASE_RPC_URL` | No | `https://mainnet.base.org` | Base L2 RPC endpoint |\n| `FACILITATOR_API_KEYS` | Prod | — | Comma-separated API keys |\n| `ALLOWED_ORIGINS` | Prod | `*` (dev) | CORS whitelist |\n| `PORT` | No | `3000` | Server port |\n\n## Testing\n\n```bash\nnpm test\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-02d4a261d4c658abba85aaf93a75ad9d"}