{"id":50563985,"url":"https://github.com/rbkunnela/paybot-sdk","last_synced_at":"2026-06-08T01:05:58.088Z","repository":{"id":341026794,"uuid":"1165225231","full_name":"RBKunnela/paybot-sdk","owner":"RBKunnela","description":"TypeScript SDK for PayBot – Let your AI agent pay for things","archived":false,"fork":false,"pushed_at":"2026-05-30T00:02:22.000Z","size":10566,"stargazers_count":0,"open_issues_count":5,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T00:19:04.730Z","etag":null,"topics":["agent-payments","agentic-payments","ai-agents","autonomous-agents","base","crypto-payments","eip-3009","ethereum","mcp","payments","stablecoins","typescript-sdk","usdc","web3","x402"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/paybot-sdk","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RBKunnela.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-24T00:22:42.000Z","updated_at":"2026-05-29T23:46:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/RBKunnela/paybot-sdk","commit_stats":null,"previous_names":["rbkunnela/paybot-sdk"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/RBKunnela/paybot-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RBKunnela%2Fpaybot-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RBKunnela%2Fpaybot-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RBKunnela%2Fpaybot-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RBKunnela%2Fpaybot-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RBKunnela","download_url":"https://codeload.github.com/RBKunnela/paybot-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RBKunnela%2Fpaybot-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33905359,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-payments","agentic-payments","ai-agents","autonomous-agents","base","crypto-payments","eip-3009","ethereum","mcp","payments","stablecoins","typescript-sdk","usdc","web3","x402"],"created_at":"2026-06-04T13:00:28.132Z","updated_at":"2026-06-04T13:00:28.787Z","avatar_url":"https://github.com/RBKunnela.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# paybot-sdk\r\n\r\nUSDC and EURC payments for bots via the [x402 protocol](https://www.x402.org/). One dependency (`viem`), typed everything.\r\n\r\n## Key Features\r\n\r\n- **One dependency** (`viem`), fully typed\r\n- **Simple API** — register your bot and make payments in 2 lines of code\r\n- **Network support** — Base, Optimism, Arbitrum One, Polygon PoS mainnets + Base Sepolia testnet (EIP155)\r\n- **Mock mode** for testing without real transactions\r\n- **MCP integration** — works with AI agent frameworks via [`paybot-mcp`](https://github.com/RBKunnela/paybot-mcp)\r\n- **Self-hostable** facilitator service\r\n\r\n## Architecture\r\n\r\n```\r\nPayBotClient → Facilitator (x402) → On-chain USDC (EIP-3009)\r\n```\r\n\r\nThe SDK wraps payment logic for bots, handling registration, payment execution, and network configuration. Developers can use the hosted facilitator at `api.paybotcore.com` or run their own.\r\n\r\n## Install\r\n\r\n```bash\r\nnpm install paybot-sdk\r\n```\r\n\r\n## Quick Start\r\n\r\n```typescript\r\nimport { PayBotClient } from 'paybot-sdk';\r\n\r\nconst client = new PayBotClient({\r\n  apiKey: 'pb_test_...',\r\n  botId: 'my-bot',\r\n  facilitatorUrl: 'https://api.paybotcore.com',\r\n});\r\n\r\n// Register your bot\r\nawait client.register();\r\n\r\n// Make a payment\r\nconst result = await client.pay({\r\n  resource: 'https://api.example.com/data',\r\n  amount: '0.01',\r\n  payTo: '0x1234...abcd',\r\n});\r\n\r\nconsole.log(result.success, result.txHash);\r\n```\r\n\r\n## x402 Auto-Handler\r\n\r\nAutomatically pay for HTTP 402 responses:\r\n\r\n```typescript\r\nimport { createX402Handler } from 'paybot-sdk';\r\n\r\nconst handler = createX402Handler({\r\n  apiKey: 'pb_test_...',\r\n  botId: 'my-bot',\r\n  maxAutoPay: '1.00', // Max USD per auto-payment\r\n});\r\n\r\n// If the server returns 402, PayBot pays and retries automatically\r\nconst response = await handler.fetch('https://api.example.com/paid-endpoint');\r\nconst data = await response.json();\r\n```\r\n\r\n## Real Payments (EIP-3009)\r\n\r\nPass a wallet private key to sign actual on-chain USDC transfers:\r\n\r\n```typescript\r\nconst client = new PayBotClient({\r\n  apiKey: 'pb_...',\r\n  botId: 'my-bot',\r\n  walletPrivateKey: '0x...', // Signs EIP-3009 TransferWithAuthorization\r\n});\r\n```\r\n\r\n## Trust Levels\r\n\r\nPayBot enforces progressive trust levels that govern what your bot can do:\r\n\r\n| Level | Name | Per-Tx Limit | Daily Limit |\r\n|-------|------|-------------|-------------|\r\n| 0 | Suspended | $0 | $0 |\r\n| 1 | New | $1 | $10 |\r\n| 2 | Basic | $10 | $100 |\r\n| 3 | Verified | $100 | $1,000 |\r\n| 4 | Trusted | $1,000 | $10,000 |\r\n| 5 | Premium | $10,000 | $100,000 |\r\n\r\n## SDK Methods\r\n\r\n| Method | Description |\r\n|--------|-------------|\r\n| `client.pay(request)` | Execute a payment (verify + settle) |\r\n| `client.register(trustLevel?)` | Register bot with facilitator |\r\n| `client.balance()` | Get trust status and remaining budget |\r\n| `client.history(limit?)` | Get transaction history |\r\n| `client.setLimits(limits)` | Update spending limits |\r\n| `client.health()` | Check facilitator health |\r\n\r\n## CLI\r\n\r\nThe package ships a `paybot` command — a thin wrapper over `PayBotClient`. No\r\ninstall needed beyond `npx`:\r\n\r\n```bash\r\nnpx paybot --help\r\n```\r\n\r\n(Or install globally / as a dependency: `npm i -g paybot-sdk` then `paybot ...`.)\r\n\r\n### Configuration\r\n\r\nEvery command resolves config with precedence **flags \u003e environment \u003e error**:\r\n\r\n| Setting | Flag | Environment variable |\r\n|---------|------|----------------------|\r\n| API key | `--api-key \u003ckey\u003e` | `PAYBOT_API_KEY` |\r\n| Bot id | `--bot-id \u003cid\u003e` | `PAYBOT_BOT_ID` |\r\n| Wallet key (for real payments) | _(env only)_ | `WALLET_PRIVATE_KEY` |\r\n| Facilitator URL | `--facilitator-url \u003curl\u003e` | `PAYBOT_FACILITATOR_URL` |\r\n\r\nSecrets (API keys, wallet keys) are **never printed in full** — any echoed value\r\nis masked as `prefix…suffix`.\r\n\r\n```bash\r\nexport PAYBOT_API_KEY=\"pb_test_...\"\r\nexport PAYBOT_BOT_ID=\"my-bot\"\r\n```\r\n\r\n### Commands\r\n\r\n```bash\r\n# Register this bot (optional initial trust level 0-5)\r\npaybot register --bot-id my-bot --trust-level 2\r\n\r\n# Show trust status + remaining budget\r\npaybot balance\r\n\r\n# Pay for a resource (amount is human-readable, e.g. 0.05)\r\npaybot pay \\\r\n  --resource https://api.example.com/data \\\r\n  --amount 0.05 \\\r\n  --pay-to 0xRecipient... \\\r\n  --token USDC \\\r\n  --idempotency-key order-123\r\n\r\n# Check facilitator health\r\npaybot health\r\n\r\n# List supported networks (CAIP-2 + name)\r\npaybot networks\r\n\r\n# List supported tokens (optionally for one network)\r\npaybot tokens\r\npaybot tokens --network eip155:10\r\n```\r\n\r\n| Command | Wraps |\r\n|---------|-------|\r\n| `paybot register [--trust-level \u003cn\u003e]` | `client.register()` |\r\n| `paybot balance` | `client.balance()` |\r\n| `paybot pay --resource \u003curl\u003e --amount \u003chuman\u003e --pay-to \u003c0x\u003e [--token \u003cSYM\u003e] [--network \u003ccaip2\u003e] [--idempotency-key \u003ck\u003e]` | `client.pay()` |\r\n| `paybot health` | `client.health()` |\r\n| `paybot networks` | `getSupportedNetworks()` |\r\n| `paybot tokens [--network \u003ccaip2\u003e]` | `getSupportedTokens()` |\r\n\r\n## Error Handling\r\n\r\nNon-`pay()` methods throw `PayBotApiError` on failure:\r\n\r\n```typescript\r\nimport { PayBotApiError } from 'paybot-sdk';\r\n\r\ntry {\r\n  await client.balance();\r\n} catch (err) {\r\n  if (err instanceof PayBotApiError) {\r\n    console.log(err.code);       // 'NOT_FOUND'\r\n    console.log(err.statusCode); // 404\r\n    console.log(err.details);    // { botId: 'unknown-bot' }\r\n  }\r\n}\r\n```\r\n\r\n`pay()` returns `PaymentResult` with `success: false` instead of throwing:\r\n\r\n```typescript\r\nconst result = await client.pay({ ... });\r\nif (!result.success) {\r\n  console.log(result.error);        // Human-readable message\r\n  console.log(result.errorCode);    // 'TRUST_VIOLATION'\r\n  console.log(result.errorDetails); // { gate: 'SPENDING_ENVELOPE', ... }\r\n}\r\n```\r\n\r\n## Network Configuration\r\n\r\n```typescript\r\nimport { NETWORKS, getNetwork, getSupportedNetworks } from 'paybot-sdk';\r\n\r\n// Available networks\r\nconsole.log(getSupportedNetworks());\r\n// ['eip155:8453', 'eip155:84532', 'eip155:10', 'eip155:42161', 'eip155:137']\r\n\r\n// Get network details\r\nconst baseSepolia = getNetwork('eip155:84532');\r\nconsole.log(baseSepolia?.name); // 'Base Sepolia'\r\n```\r\n\r\n### Networks supported\r\n\r\n| Network | CAIP-2 | Chain ID | Type |\r\n|---|---|---|---|\r\n| Base Mainnet | `eip155:8453` | 8453 | mainnet |\r\n| Base Sepolia | `eip155:84532` | 84532 | testnet |\r\n| Optimism | `eip155:10` | 10 | mainnet |\r\n| Arbitrum One | `eip155:42161` | 42161 | mainnet |\r\n| Polygon PoS | `eip155:137` | 137 | mainnet |\r\n\r\nRPC URLs default to public endpoints (`mainnet.optimism.io`, `arb1.arbitrum.io/rpc`, `polygon-rpc.com`, …); override per network for production use.\r\n\r\n## Webhook Signature Verification\r\n\r\nVerify inbound webhooks from the facilitator (HMAC-SHA256, constant-time compare, replay-window guard). No extra dependency — uses Node's built-in `crypto`.\r\n\r\n```typescript\r\nimport { verifyWebhookSignature } from 'paybot-sdk';\r\n\r\napp.post('/paybot/webhook', (req, res) =\u003e {\r\n  const valid = verifyWebhookSignature({\r\n    payload: req.rawBody,                       // raw string/Buffer, exactly as received\r\n    signature: req.headers['paybot-signature'], // 't=\u003cunix_ts\u003e,v1=\u003chmac_hex\u003e'\r\n    secret: process.env.PAYBOT_WEBHOOK_SECRET,\r\n    tolerance: 300,                             // optional replay window in seconds (default 300)\r\n  });\r\n  if (!valid) return res.status(400).send('invalid signature');\r\n  // ...handle event\r\n  res.sendStatus(200);\r\n});\r\n```\r\n\r\nThe signing string is `` `${t}.${payload}` ``; the same algorithm is implemented identically in the Python SDK, so a server-signed webhook verifies byte-for-byte in either runtime. `signWebhookPayload({ payload, secret })` produces a header value for TS-based senders and tests.\r\n\r\n## OpenTelemetry (opt-in)\r\n\r\nPass any OpenTelemetry-compatible tracer to emit spans around the payment lifecycle. When no tracer is supplied, telemetry is a zero-overhead no-op — `@opentelemetry/api` is **not** a dependency of this SDK.\r\n\r\n```typescript\r\nimport { trace } from '@opentelemetry/api';\r\n\r\nconst client = new PayBotClient({\r\n  apiKey: 'pb_...',\r\n  botId: 'my-bot',\r\n  walletPrivateKey: '0x...',\r\n  telemetry: { tracer: trace.getTracer('my-bot'), prefix: 'paybot.' },\r\n});\r\n```\r\n\r\nSpans emitted per `pay()`: `paybot.client.pay`, `paybot.x402.sign`, `paybot.x402.challenge`, `paybot.x402.settle` — with `network`, `amount`, `bot_id`, `tx_hash`, and `success` attributes. A returned payment failure is an OK span with `success=false`; only thrown errors become span ERROR + `recordException`.\r\n\r\n## x402 v2 conformance\r\n\r\nTracks the [x402-foundation](https://github.com/x402-foundation/x402) spec: v2 `PAYMENT-REQUIRED` / `PAYMENT-SIGNATURE` / `PAYMENT-RESPONSE` headers (the legacy `Payment-Intent` path still works), CAIP-2 network identifiers, and the `upto` (metered/usage) scheme alongside `exact`.\r\n\r\n```typescript\r\nimport { parseCaip2, isSupportedCaip2 } from 'paybot-sdk';\r\n\r\nparseCaip2('eip155:8453');        // { namespace: 'eip155', reference: '8453' }\r\nisSupportedCaip2('eip155:8453');  // true\r\n\r\n// 'upto' authorizes a capture ceiling; the facilitator settles the actual usage \u003c= max.\r\n// X402Handler.validateUptoCapture(authorizedMax, captured) throws UPTO_OVERCHARGE if exceeded.\r\n```\r\n\r\n## Tokens (USDC + EURC + DAI)\r\n\r\nPay in USDC (default), EURC, or DAI. The signing domain is resolved per-token, so each\r\ntoken signs against its own contract. USDC defaults everywhere; the public surface is\r\nunchanged for existing USDC callers.\r\n\r\n```typescript\r\nimport { getToken, getSupportedTokens } from 'paybot-sdk';\r\n\r\ngetSupportedTokens();      // ['USDC', 'EURC', 'DAI']\r\ngetToken('EURC')?.symbol;  // 'EURC'\r\ngetToken('DAI')?.decimals; // 18\r\n\r\nawait client.pay({\r\n  resource: 'https://api.example.com/data',\r\n  amount: '0.50',\r\n  payTo: '0x....',\r\n  token: 'EURC',           // defaults to 'USDC'; unknown token → UNSUPPORTED_TOKEN\r\n  network: 'eip155:84532', // EURC testnet ships in the public registry\r\n});\r\n```\r\n\r\n### Token coverage\r\n\r\nOnly `(token, network)` pairs verifiable against an **official issuer source** are\r\nshipped in the public registry. A wrong contract address routes real funds to the\r\nwrong contract, so unverifiable pairs are deliberately omitted rather than guessed.\r\nThe public registry carries only addresses that are safe to ship open-core — mainnet\r\naddresses for regulated tokens (e.g. EURC mainnet) are operator-supplied at runtime\r\n(see below), not hardcoded here.\r\n\r\n| Token | Decimals | Base | Base Sepolia | Optimism | Arbitrum | Polygon | Issuer source |\r\n|---|---|---|---|---|---|---|---|\r\n| USDC | 6 | ✓ | ✓ | ✓ | ✓ | ✓ | [Circle USDC addresses](https://developers.circle.com/stablecoins/usdc-contract-addresses) |\r\n| EURC | 6 | override | ✓ | — | — | — | [Circle EURC addresses](https://developers.circle.com/stablecoins/eurc-contract-addresses) |\r\n| DAI | 18 | — | — | ✓ | ✓ | ✓ | [MakerDAO / Sky](https://docs.makerdao.com/) |\r\n\r\n`override` = the address is not shipped in the public registry; supply it at runtime\r\nvia `tokenAddressOverrides` (see below).\r\n\r\n**Not currently supported:** PYUSD (Paxos — Ethereum + Solana only) and RLUSD (Ripple —\r\nEthereum + XRPL only) are not deployed on any network in this registry, so they are not\r\nregistered.\r\n\r\n\u003e Token contract addresses ship with their official issuer source cited inline in\r\n\u003e `src/networks.ts`. Re-verify each address against the cited source before mainnet use.\r\n\r\n### Mainnet token addresses (operator-supplied)\r\n\r\nThe public registry ships only addresses that are safe to distribute open-core\r\n(e.g. testnet deployments). Mainnet addresses for regulated tokens are **not**\r\nhardcoded in the SDK — inject them at runtime via `tokenAddressOverrides`\r\n(`symbol → caip2Network → address`):\r\n\r\n```typescript\r\nconst client = new PayBotClient({\r\n  apiKey: 'pb_...',\r\n  botId: 'my-bot',\r\n  tokenAddressOverrides: {\r\n    EURC: { 'eip155:8453': '0x...' }, // your EURC mainnet contract address\r\n  },\r\n});\r\n```\r\n\r\nAddress resolution precedence: explicit `PaymentRequest.tokenContract` →\r\n`tokenAddressOverrides[symbol][network]` → the public registry → otherwise a\r\n`PaymentResult` failure with code `TOKEN_ADDRESS_NOT_CONFIGURED`. This keeps the\r\nSDK from signing against a wrong or absent address when a mainnet token is not\r\nconfigured.\r\n\r\n## Error Taxonomy\r\n\r\n`pay()` still returns `PaymentResult` (never throws). The other methods throw a typed hierarchy you can `instanceof`-switch on — all subclasses remain `instanceof PayBotApiError` for backward compatibility.\r\n\r\n```typescript\r\nimport {\r\n  PayBotError,            // abstract root\r\n  PayBotApiError,         // HTTP-level (unchanged)\r\n  PayBotNetworkError, PayBotTimeoutError, PayBotAuthError,\r\n  PayBotPolicyError,      // trust/AML/daily-limit\r\n  PayBotSignatureError, PayBotSettlementError,\r\n} from 'paybot-sdk';\r\n\r\ntry {\r\n  await client.balance();\r\n} catch (err) {\r\n  if (err instanceof PayBotPolicyError) { /* trust/limit gate */ }\r\n  else if (err instanceof PayBotAuthError) { /* re-auth */ }\r\n}\r\n```\r\n\r\n## Idempotency Keys\r\n\r\nPass an `idempotencyKey` to `pay()` / `register()` — sent as `X-Idempotency-Key` and deduped in a per-client LRU so a retried call doesn't double-bill.\r\n\r\n```typescript\r\nawait client.pay({ resource, amount: '0.01', payTo, idempotencyKey: 'order_42_attempt_1' });\r\n// A second call with the same key returns the cached result with no network round-trip.\r\n```\r\n\r\n## Multi-Bot Pool + Spend Treasury\r\n\r\nRun many bots in one process from shared operator/transport config, each with its own signing key, under an optional shared daily spend ceiling.\r\n\r\n```typescript\r\nimport { PayBotClientPool } from 'paybot-sdk';\r\n\r\nconst pool = new PayBotClientPool({\r\n  apiKey: 'pb_...',\r\n  operatorId: 'op_1',\r\n  sharedDailyLimitUsd: 500,         // optional treasury across all bots\r\n});\r\npool.addBot({ botId: 'bot-1', walletPrivateKey: '0x...' });\r\npool.addBot({ botId: 'bot-2', walletPrivateKey: '0x...' });\r\n\r\n// payAs() blocks over-treasury BEFORE any network call (errorCode 'TREASURY_EXCEEDED')\r\nconst result = await pool.payAs('bot-1', { resource, amount: '12.00', payTo });\r\npool.remainingTreasuryUsd();        // 488 after a successful $12 spend\r\n```\r\n\r\n## Micropayment Batching\r\n\r\n`MicropaymentEngine` queues many sub-cent payments and settles them as one signed batch, so per-payment gas is amortized across the group. Auto-settle fires when the batch window closes or the count/total thresholds are reached.\r\n\r\n```typescript\r\nimport { MicropaymentEngine } from 'paybot-sdk';\r\n\r\nconst engine = new MicropaymentEngine({\r\n  walletPrivateKey: '0x...',\r\n  batchWindowMs: 60_000,   // default 60s window\r\n  minPaymentCount: 100,    // auto-settle thresholds\r\n  minTotalUsd: 1.0,\r\n});\r\n\r\nconst id = await engine.queuePayment('0xRecipient...', '0.001');  // returns paymentId\r\nconst batch = await engine.batchPayments([id]);                   // signed BatchedSettlement\r\nengine.getQueueStatistics();                                      // BatchStatistics\r\n```\r\n\r\n## AP2 + MPP\r\n\r\npaybot is a clean x402 settlement engine, so a Google **AP2** (A2A x402-extension) mandate can settle through it directly. **MPP** (Stripe/Tempo) is still preview — the SDK ships only a detect-and-route capability seam, not a full client.\r\n\r\n```typescript\r\nimport { Ap2Adapter, detectMppCapability } from 'paybot-sdk';\r\n\r\nconst ap2 = new Ap2Adapter(handler);              // handler: X402Handler\r\nif (ap2.validateMandate(mandate).valid) {\r\n  const receipt = await ap2.settle(mandate);      // signs + submits via x402\r\n}\r\n\r\ndetectMppCapability(responseHeaders);             // { supported, mode: 'detect-only'|'none', specVersion? }\r\n// createMppSeam().settle(...) throws MPP_NOT_IMPLEMENTED (501) — full MPP deferred until GA\r\n```\r\n\r\n\u003e The AP2 adapter settles the payment; it does **not** verify the AP2 verifiable-credential signature — that stays in the mandate issuer's trust domain.\r\n\r\n## Python SDK\r\n\r\nA Python port lives in [`packages/python`](./packages/python) (`paybot-sdk` on PyPI, `\u003e=3.10`). Mirrors the TS client surface, real EIP-3009 signing via `eth-account`, and the identical webhook verification contract.\r\n\r\n```python\r\nfrom paybot_sdk import PayBotClient, PayBotConfig, PaymentRequest, verify_webhook_signature\r\n\r\nclient = PayBotClient(PayBotConfig(api_key=\"pb_...\", bot_id=\"my-bot\", wallet_private_key=\"0x...\"))\r\nresult = await client.pay(PaymentRequest(resource=\"https://api.example.com/data\",\r\n                                         amount=\"0.01\", pay_to=\"0x....\"))\r\n```\r\n\r\n## MCP Integration\r\n\r\nFor AI agent frameworks, use [paybot-mcp](https://github.com/RBKunnela/paybot-mcp) which wraps this SDK as an MCP server.\r\n\r\n## Roadmap \u0026 Status\r\n\r\n\u003e **Legend:** ✅ shipped · 🟡 partial · 🔭 deferred (intentional) · ⬜ gap\r\n\r\n**Capability map** — what the SDK can do today:\r\n\r\n![paybot-sdk capability map](./.github/assets/paybot-sdk-capability-map.png)\r\n\r\n**Roadmap ahead** — the phased plan:\r\n\r\n![paybot-sdk roadmap](./.github/assets/paybot-sdk-roadmap-timeline.png)\r\n\r\n### What we've built\r\n\r\n**Core rail (hardened):** `PayBotClient` (pay/balance/history/setLimits/register/health/commission/API-keys) · x402 auto-handler · EIP-3009 signing · `MicropaymentEngine` · trust levels 0–5 · commission accounting · `paybot402()` middleware · self-hostable facilitator · CI hardening (CodeQL, OSV, 80% coverage gate, SHA-pinned actions).\r\n\r\n| Shipped | Gap ID |\r\n|---------|--------|\r\n| ✅ x402 **v2 conformance** — `upto` scheme, `PAYMENT-*` headers, CAIP-2 helpers | T1.1 + new |\r\n| ✅ **Webhook signature verification** (TS + Python, byte-identical HMAC) | T1.2 |\r\n| ✅ **Idempotency keys** (`X-Idempotency-Key` + LRU dedupe) | T1.3 |\r\n| ✅ **Error taxonomy** (`PayBotError` + 6 typed subclasses) | T1.4 |\r\n| ✅ **OpenTelemetry hooks** (opt-in, zero new deps) | T1.5 |\r\n| ✅ **Multi-bot pool + spend treasury** | T1.6 |\r\n| ✅ **EURC + token registry** (per-token EIP-712 domains) | T2.2 |\r\n| ✅ **AP2 settlement adapter** · 🔭 thin **MPP capability seam** (deferred to GA) | T2.3 |\r\n| ✅ **Python SDK 0.1.0** (real EIP-3009 signing) | T3.2 (partial) |\r\n\r\n**Tier 1 (credibility blockers) is 100% complete** (T1.1–T1.6). Test posture: 331 TS tests / 98.66% coverage · 52 Python tests.\r\n\r\n### Current gaps\r\n\r\n- ⬜ **Network expansion (T2.1)** — still **Base + Base Sepolia only**; add Optimism / Arbitrum / Polygon.\r\n- ⬜ **CCTP V2 cross-chain receive** — ⏰ *time-sensitive: Circle CCTP V1 deprecates 2026-07-31.*\r\n- ⬜ **Refund + reversal helpers (T2.4)** · ⬜ **Streaming subscriptions (T2.5)** · ⬜ **Wallet-connect bridge (T2.6)**\r\n- 🟡 **Token breadth** — USDC + EURC done; PYUSD / RLUSD / DAI not added (operator-gated).\r\n- 🟡 **Language ports (T3.2)** — Python runtime shipped (middleware/x402-handler unported); Go / Rust not started.\r\n- ⬜ **Framework ports (T3.1)** (Hono/Next/NestJS/FastAPI/Django) · ⬜ **CLI (T3.4)** · ⬜ **Examples + tutorial site (T3.5)** · ⬜ **More MCP tools (T3.3)** · ⬜ **L402 shim (T3.6)**\r\n- 🔭 **Full MPP (T2.3)** — deliberately deferred; Stripe/Tempo MPP is still preview and shares no signing code with EIP-3009. Detect-only seam ships now.\r\n\r\n### Roadmap ahead\r\n\r\nPrioritized by internal gap severity × external leverage (EU-bank credibility, live distribution channels, hard deadlines).\r\n\r\n**Phase A — Near-term (rail credibility):**\r\n1. Network expansion (Optimism + Arbitrum + Polygon) — closes the biggest surface gap vs. Coinbase/Circle/Crossmint.\r\n2. CCTP V2 cross-chain receive — ⏰ hard deadline (CCTP V1 dies 2026-07-31).\r\n3. Refund + reversal helpers — table-stakes for real commerce.\r\n4. Token breadth (PYUSD/RLUSD/DAI, operator-gated).\r\n\r\n**Phase B — Mid-term (agent-economy surface):** streaming subscriptions · CLI · framework ports (Hono/Next/FastAPI first) · examples + tutorial site · wallet-connect bridge.\r\n\r\n**Phase C — Strategic / opportunistic:** full MPP (on GA) · more language ports (Go/Rust) · L402/Lightning shim · more MCP tools.\r\n\r\n**Strategic posture:** the moat is *self-hosted, non-custodial, MIT, trust-layer-in-the-SDK* — which custodial/portal-locked rivals (Coinbase Agentic Wallets, Circle, Crossmint, Payman) structurally cannot copy. Being a clean x402 settlement engine makes paybot AP2-pluggable and AgentCore-compatible today — so MPP can wait for GA.\r\n\r\n## Deployment Options\r\n\r\n### Option 1: Hosted (Recommended)\r\n\r\nUse the hosted facilitator at `api.paybotcore.com` — no setup needed, ready to go:\r\n\r\n```typescript\r\nconst client = new PayBotClient({\r\n  apiKey: 'pb_test_...',\r\n  botId: 'my-bot',\r\n  facilitatorUrl: 'https://api.paybotcore.com',  // ← Hosted\r\n});\r\n```\r\n\r\n### Option 2: Self-Hosted with Docker\r\n\r\nFor enterprise bots or custom networks, deploy your own PayBot facilitator with Docker (5 minutes):\r\n\r\n```bash\r\ngit clone https://github.com/RBKunnela/paybot-core.git\r\ncd paybot-core\r\ndocker compose up -d\r\n```\r\n\r\nThen configure your bot:\r\n\r\n```typescript\r\nconst client = new PayBotClient({\r\n  apiKey: 'pb_dev_...',\r\n  botId: 'my-bot',\r\n  facilitatorUrl: 'http://localhost:3000',  // ← Self-hosted\r\n});\r\n```\r\n\r\n**Quick start guide**: See [SELF_HOSTING.md](./SELF_HOSTING.md) in this repository.\r\n\r\n**Full deployment guide**: See [DEPLOYMENT.md](https://github.com/RBKunnela/paybot-core/blob/main/DEPLOYMENT.md) in paybot-core repository.\r\n\r\n## Contributing\r\n\r\nWe take security seriously. **All PRs are reviewed by an army of AI agents** from different specializations (@dev, @qa, @architect, @security, @devops) before acceptance. This ensures code quality, correctness, security validation, and architectural alignment.\r\n\r\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for details.\r\n\r\n## License\r\n\r\n[MIT](LICENSE)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frbkunnela%2Fpaybot-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frbkunnela%2Fpaybot-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frbkunnela%2Fpaybot-sdk/lists"}