# PaySentry — Full API Reference > Payment control plane for AI agents — spending limits, circuit breakers, and audit trails for x402, MCP, and autonomous agent payments. npm: @paysentry/core | GitHub: mkmkkkkk/paysentry | License: MIT --- ## The Problem AI agents are spending real money with zero governance: - x402 settlement failures drain wallets silently — facilitator takes payment, service returns 500 - No spending limits — one prompt injection = unlimited spend - No audit trail — "which agent spent $2,400 last Tuesday?" - Retry storms cause duplicate payments — failed settlements trigger retries with no dedup - No circuit breakers — one flaky facilitator cascades into system-wide failures --- ## Packages | Package | Description | |---------|-------------| | `@paysentry/core` | Core types, utilities, transaction factory, ID generation | | `@paysentry/control` | Policy engine — rules, budgets, approval chains, middleware | | `@paysentry/observe` | Spend tracking, analytics, budget alerts, anomaly detection | | `@paysentry/protect` | Dispute resolution — provenance, disputes, automated recovery | | `@paysentry/sandbox` | Mock payment environment — x402, ACP, AP2 with 9 test scenarios | | `@paysentry/x402` | x402 protocol adapter — lifecycle hooks, circuit breakers | | `@paysentry/wallet` | Wallet-agnostic adapter — Coinbase, local signer, or custom. 5-line setup via `createWallet()` | | `@paysentry/shield` | Anti-injection security — 6-layer defense, tested against 18 real-world attack scenarios | | `@paysentry/mcp` | MCP server — 10 tools for AI agent payment control | | `@paysentry/a2a` | Agent-to-agent payments — intents, mandates, escrow | | `@paysentry/dashboard` | JSON API + SSE event stream for monitoring | Install all: ```bash npm install @paysentry/core @paysentry/control @paysentry/observe @paysentry/protect @paysentry/sandbox @paysentry/x402 @paysentry/mcp @paysentry/a2a @paysentry/dashboard ``` --- ## @paysentry/core Shared types, ID generation, and transaction factory. ### createTransaction(input) → AgentTransaction Creates a fully-formed transaction with auto-generated ID and timestamp. Parameters: - `agentId` (AgentId, required) — The agent making the payment - `amount` (number, required) — Payment amount - `currency` (string, required) — Currency code (e.g., 'USDC', 'USD') - `recipient` (string, required) — Payment recipient (address, domain, etc.) - `protocol` ('x402' | 'acp' | 'ap2' | 'visa_tap' | 'other', required) — Payment protocol - `purpose` (string, optional) — Human-readable purpose - `service` (string, optional) — Service identifier - `description` (string, optional) — Description ### Key Types - `AgentTransaction` — Core transaction record: id, agentId, amount, currency, recipient, protocol, status, timestamps - `SpendPolicy` — Policy definition with rules and budget limits - `PolicyRule` — Single rule within a policy (condition + action) - `PolicyEvaluation` — Result of evaluating a transaction: { allowed, action, reason } - `BudgetLimit` — Time-windowed spending cap: { window: 'daily'|'weekly'|'monthly', maxAmount, currency } - `DisputeCase` — Dispute record with evidence and resolution - `SpendAlert` — Alert fired by the observability layer - `PaymentProtocol` — 'x402' | 'acp' | 'ap2' | 'visa_tap' | 'other' - `AgentId` — Branded string type for agent identifiers - `PolicyId` — Branded string type for policy identifiers --- ## @paysentry/control Deterministic policy engine. No LLM, no AI, no probabilistic reasoning. ### PolicyEngine ```typescript import { PolicyEngine } from '@paysentry/control'; const engine = new PolicyEngine({ logger: console }); ``` Methods: - `loadPolicy(policy: SpendPolicy)` — Load a policy into the engine - `evaluate(tx: AgentTransaction) → PolicyEvaluation` — Evaluate transaction against all policies - `recordSpend(tx: AgentTransaction)` — Update spend tracking after successful payment ### Rule Builders ```typescript import { blockAbove, requireApprovalAbove, blockRecipient, allowOnlyRecipients, allowAll, denyAll, } from '@paysentry/control'; ``` | Builder | Action | Description | |---------|--------|-------------| | `blockAbove(amount, currency)` | block | Block any transaction above the amount | | `requireApprovalAbove(amount, currency)` | require_approval | Require human approval above amount | | `blockRecipient(pattern)` | block | Block payments to matching recipients (glob) | | `allowOnlyRecipients(patterns[])` | block | Block payments to non-matching recipients | | `allowAll()` | allow | Allow everything (catch-all) | | `denyAll()` | block | Block everything (catch-all) | ### Policy Example ```typescript engine.loadPolicy({ id: 'production' as PolicyId, name: 'Production Controls', enabled: true, rules: [ blockAbove(1000, 'USDC'), requireApprovalAbove(100, 'USDC'), blockRecipient('malicious-service.com'), allowOnlyRecipients(['api.openai.com', '*.anthropic.com']), allowAll(), ], budgets: [ { window: 'daily', maxAmount: 500, currency: 'USDC' }, { window: 'weekly', maxAmount: 2000, currency: 'USDC' }, { window: 'monthly', maxAmount: 5000, currency: 'USDC' }, ], }); const result = engine.evaluate(tx); // { allowed: boolean, action: 'allow'|'deny'|'require_approval'|'flag', reason?: string } ``` ### Middleware (Express/Fastify) ```typescript import { createPolicyMiddleware } from '@paysentry/control'; app.use('/pay', createPolicyMiddleware({ engine, approvalHandler: async (tx) => { return await slack.requestApproval(tx); }, })); ``` --- ## @paysentry/observe Transaction tracking, spend analytics, and alert system. ### SpendTracker ```typescript import { SpendTracker } from '@paysentry/observe'; const tracker = new SpendTracker(); tracker.record(transaction); const txns = tracker.query({ agentId: 'agent-001', protocol: 'x402', after: '2026-02-01T00:00:00Z', minAmount: 10, limit: 50, }); const tx = tracker.get(transactionId); ``` ### SpendAnalytics ```typescript import { SpendAnalytics } from '@paysentry/observe'; const analytics = new SpendAnalytics(tracker); const summary = analytics.getSummary('agent-001', { period: '24h', // '1h' | '24h' | '7d' | '30d' currency: 'USDC', }); // { totalSpend, txCount, avgAmount, topRecipients, byProtocol } const report = analytics.getAgentAnalytics('agent-001' as AgentId); // report.spendByCurrency, report.topRecipients, report.anomalies ``` ### SpendAlerts ```typescript import { SpendAlerts } from '@paysentry/observe'; const alerts = new SpendAlerts(tracker); alerts.addRule({ id: 'daily-budget', name: 'Daily Budget Alert', type: 'budget_threshold', severity: 'warning', enabled: true, config: { type: 'budget_threshold', threshold: 500, currency: 'USDC', windowMs: 86_400_000, alertAtPercent: 0.8, }, }); alerts.addRule({ id: 'large-tx', name: 'Large Transaction Alert', type: 'large_transaction', severity: 'critical', enabled: true, config: { type: 'large_transaction', threshold: 200, currency: 'USDC', }, }); alerts.addRule({ id: 'rate-spike', name: 'Rate Spike Alert', type: 'rate_spike', severity: 'critical', enabled: true, config: { type: 'rate_spike', windowMs: 60_000, maxTransactions: 5, }, }); alerts.onAlert((alert) => { console.log(`[${alert.severity}] ${alert.message}`); }); ``` ### Alert Types | Type | Config | Description | |------|--------|-------------| | `budget_threshold` | threshold, currency, windowMs, alertAtPercent | Fires when cumulative spend reaches % of threshold | | `large_transaction` | threshold, currency | Fires on any single transaction above threshold | | `rate_spike` | windowMs, maxTransactions | Fires when transaction rate exceeds limit | | `new_recipient` | agentId | Fires when agent pays a never-before-seen recipient | | `anomaly` | sensitivity | Statistical anomaly detection on amount/frequency | --- ## @paysentry/protect Transaction provenance, dispute resolution, and automated recovery. ### TransactionProvenance ```typescript import { TransactionProvenance } from '@paysentry/protect'; const provenance = new TransactionProvenance(); provenance.record(transaction, { prompt: 'User asked to purchase API credits', policyId: 'production', approvedBy: 'policy-engine', }); const chain = provenance.getChain(transactionId); ``` ### DisputeManager ```typescript import { DisputeManager } from '@paysentry/protect'; const disputes = new DisputeManager(); const dispute = disputes.file({ transactionId: tx.id, reason: 'duplicate_charge', description: 'Payment retried after timeout — charged twice', evidence: [{ type: 'transaction_log', data: tx }], }); const open = disputes.query({ status: 'open' }); ``` ### RecoveryEngine ```typescript import { RecoveryEngine } from '@paysentry/protect'; const recovery = new RecoveryEngine({ refundExecutor: async (tx) => { return { success: true, refundId: '...' }; }, }); const result = await recovery.execute(dispute); // { status: 'completed', action: 'refund', ... } ``` --- ## @paysentry/sandbox Mock payment environment for testing. No real money. ### MockX402 ```typescript import { MockX402 } from '@paysentry/sandbox'; const mock = new MockX402({ latencyMs: 50, failureRate: 0, balances: { 'agent-001': 1000 }, }); const result = await mock.processPayment({ from: 'agent-001', to: 'api.openai.com', amount: 25, currency: 'USDC', }); ``` ### MockACP / MockAP2 ```typescript import { MockACP, MockAP2 } from '@paysentry/sandbox'; const acp = new MockACP({ latencyMs: 30 }); const ap2 = new MockAP2({ latencyMs: 30 }); ``` ### Test Scenarios ```typescript import { SCENARIO_BASIC_PAYMENT, SCENARIO_OVERSPEND, SCENARIO_APPROVAL_REQUIRED, SCENARIO_BLOCKED_RECIPIENT, SCENARIO_MULTI_PROTOCOL, SCENARIO_DISPUTE, SCENARIO_RATE_SPIKE, SCENARIO_TIMEOUT, SCENARIO_MULTI_AGENT, ALL_SCENARIOS, } from '@paysentry/sandbox'; ``` | Scenario | What It Tests | |----------|---------------| | `SCENARIO_BASIC_PAYMENT` | Simple successful payment flow | | `SCENARIO_OVERSPEND` | Agent exceeding budget limits | | `SCENARIO_APPROVAL_REQUIRED` | Human-in-the-loop approval flow | | `SCENARIO_BLOCKED_RECIPIENT` | Payment to blocklisted recipient | | `SCENARIO_MULTI_PROTOCOL` | Agent using x402 + ACP simultaneously | | `SCENARIO_DISPUTE` | Filing and resolving a dispute | | `SCENARIO_RATE_SPIKE` | Rapid payment burst triggering circuit breaker | | `SCENARIO_TIMEOUT` | Payment timeout and retry handling | | `SCENARIO_MULTI_AGENT` | Multiple agents with independent policies | --- ## @paysentry/x402 x402 protocol adapter with lifecycle hooks and circuit breakers. ```typescript import { PaySentryX402Adapter } from '@paysentry/x402'; import { PolicyEngine } from '@paysentry/control'; import { SpendTracker } from '@paysentry/observe'; const adapter = new PaySentryX402Adapter( { policyEngine: new PolicyEngine(), spendTracker: new SpendTracker() }, { circuitBreaker: { failureThreshold: 5, recoveryTimeoutMs: 30_000 } }, ); // Registers all 6 lifecycle hooks: // onBeforeVerify, onAfterVerify, onVerifyFailure, // onBeforeSettle, onAfterSettle, onSettleFailure adapter.withLifecycleHooks(yourX402Server); ``` --- ## @paysentry/wallet Wallet-agnostic adapter layer. Plug any wallet backend behind PaySentry policy controls. ### Quick Start (5 lines) ```typescript import { createWallet, presets } from '@paysentry/wallet'; const wallet = createWallet({ adapter: { type: 'coinbase', apiKey: '...', walletId: '...' }, limits: presets.standard, // $100/tx, $500/day, approval above $50 }); const result = await wallet.pay(25, '0xRecipient', 'API credits'); // { status: 'completed', txHash: '0x...', network: 'base' } ``` ### Adapters | Adapter | Custody | Key Management | |---------|---------|----------------| | `CoinbaseAdapter` | Managed (TEE) | Private keys never leave Coinbase | | `LocalSignerAdapter` | Self-custody | AES-256-GCM encrypted keystore, scrypt KDF | | Custom | Any | Implement `WalletAdapter` interface | ### Spend Limit Presets | Preset | Per-TX | Daily | Approval Above | |--------|--------|-------|----------------| | `presets.conservative` | $25 | $100 | — | | `presets.standard` | $100 | $500 | $50 | | `presets.generous` | $1,000 | $5,000 | $500 | | `presets.unlimited` | — | — | — | ### Advanced Usage For full control, wire engines directly: ```typescript import { PaySentryWallet, CoinbaseAdapter } from '@paysentry/wallet'; import { PolicyEngine } from '@paysentry/control'; import { SpendTracker } from '@paysentry/observe'; const wallet = new PaySentryWallet({ policyEngine: new PolicyEngine(), walletAdapter: new CoinbaseAdapter({ apiKey, walletId }), spendTracker: new SpendTracker(), }); ``` ### WalletAdapter Interface ```typescript interface WalletAdapter { readonly name: string; getBalance(currency: string): Promise; signAndSend(tx: AgentTransaction): Promise; getTransactionStatus(txHash: string): Promise; getAddresses(): Promise; } ``` --- ## @paysentry/shield Anti-injection security layer. 6-layer defense pipeline tested against 18 real-world attack scenarios from Freysa ($47K), AIXBT ($106K), Lobstar ($441K), EchoLeak (CVSS 9.3), and more. ### Defense Layers | Layer | Name | What It Blocks | |-------|------|----------------| | 0 | Immutable tool semantics | MCP tool poisoning — logic is compiled TypeScript, not prompt | | 1 | Session Manifests | Payment scope locked at creation — recipient, amount, count, currency, TTL | | 2 | Auth Scope | Control/data plane separation — agent tokens can't modify policies | | 3 | Rate Limiting | Flooding + auto-freeze after repeated violations | | 4 | Anomaly Detection | Behavioral fingerprinting — flags unusual amounts, new recipients | | 5 | Stateless Pipeline | All 4 runtime checks run on every payment, none skippable | ### Usage ```typescript import { SecurityGate } from '@paysentry/shield'; const gate = new SecurityGate({ rateLimit: { maxTransactions: 5, windowMs: 60_000, freezeAfterViolations: 3 }, anomalyThreshold: 0.7, blockOnAnomaly: true, }); // User creates a manifest (locked scope for this task) const manifest = gate.manifests.create({ userIntent: 'Buy API key from OpenAI, budget $30', agentId: 'my-agent' as AgentId, allowedRecipients: ['https://*.openai.com/*'], maxPerPayment: 30, maxTotalSpend: 50, maxPaymentCount: 2, allowedCurrencies: ['USD'], ttlMs: 3_600_000, }); // Agent gets a scoped token const scope = gate.auth.createScope('my-agent' as AgentId, AGENT_PERMISSIONS); // Every payment goes through all 6 layers const result = gate.validatePayment(scope.token, manifest.id, 'https://api.openai.com/v1/keys', 25, 'USD'); // { allowed: true, checks: [{ layer: 'auth', allowed: true }, { layer: 'manifest', allowed: true }, ...] } ``` ### Tested Attack Scenarios (18) | # | Attack | Real-World Case | Defense | |---|--------|-----------------|---------| | 1 | Function redefinition | Freysa ($47K) | Manifest locks recipient | | 2 | Control plane compromise | AIXBT ($106K) | Auth scope separation | | 3 | State amnesia | Lobstar ($441K) | Manifest persists independently | | 4 | Indirect injection via content | EchoLeak (CVSS 9.3) | Manifest recipient whitelist | | 5 | Unrestricted tool abuse | Devin AI | Auth token validation | | 6 | Supply chain / plugin attack | OpenClaw (42K instances) | Per-plugin manifest + budget | | 7 | Verification bypass | Bank AI ($250K) | Unskippable 4-layer pipeline | | 8 | Small-amount flooding | — | maxPaymentCount + rate limiter + auto-freeze | | 9 | Recipient substitution | — | Glob matching blocks typosquatting + subdomain spoofing | | 10 | Expired token replay | — | Auth TTL + token revocation | | 11 | Manifest tampering | — | Object.freeze, no update API | | 12 | Cross-agent escalation | Embrace The Red | Agent-scoped manifests | | 13 | Anomaly evasion | — | Behavioral fingerprinting (mean + std dev) | | 14 | Memory poisoning | MemoryGraft, Unit42 | Manifest from user input, not agent memory | | 15 | Multi-step kill chain | Promptware (5-stage) | Each step blocked by different layer | | 16 | MCP tool poisoning | MCPTox (72.8%) | Compiled TypeScript, not prompt | | 17 | Race condition | — | Sequential manifest counter tracking | | 18 | Document poisoning | GeminiJack | Manifest scope immutable after creation | ### Auth Permissions ```typescript import { AGENT_PERMISSIONS, ADMIN_PERMISSIONS, READ_ONLY_PERMISSIONS } from '@paysentry/shield'; // AGENT_PERMISSIONS: payment:execute, balance:read, history:read // ADMIN_PERMISSIONS: + policy:write, manifest:create, admin:freeze // READ_ONLY_PERMISSIONS: balance:read, history:read only ``` --- ## @paysentry/mcp MCP server exposing 10 tools for AI agent payment control. Primary interface for agents. ### Setup ```bash npm install @paysentry/mcp npx paysentry-mcp # Start standalone MCP server ``` Claude Desktop config: ```json { "mcpServers": { "paysentry": { "command": "npx", "args": ["paysentry-mcp"] } } } ``` ### Programmatic Usage ```typescript import { createPaySentryMcpServer } from '@paysentry/mcp'; const { server } = createPaySentryMcpServer({ agentId: 'my-agent', dailyBudget: 500, perTransactionLimit: 100, }); ``` ### Tools | Tool | Description | |------|-------------| | `pay` | Execute a payment through the control plane | | `check_balance` | Check wallet balance and budget utilization | | `transaction_history` | Query transaction history with filters | | `discover_capabilities` | Returns full capability manifest (tools, policies, budgets, protocols) | | `list_policies` | List all active spending policies | | `create_policy` | Create a new spending policy | | `evaluate_payment` | Dry-run payment evaluation against policies (no execution) | | `file_dispute` | File a dispute for a transaction | | `get_audit_trail` | Get provenance chain for a transaction | | `get_alerts` | Get recent alerts | --- ## @paysentry/a2a Agent-to-agent payment primitives — intents, mandates, escrow, and agent registry. ### PaymentIntentManager ```typescript import { PaymentIntentManager } from '@paysentry/a2a'; import { MemoryStorage } from '@paysentry/core'; const intents = new PaymentIntentManager(new MemoryStorage()); // Agent A proposes payment to Agent B const intent = intents.propose({ fromAgent: 'agent-a' as AgentId, toAgent: 'agent-b' as AgentId, amount: 50, currency: 'USDC', purpose: 'data analysis', }); intents.accept(intent.id, 'agent-b' as AgentId); // Accept intents.reject(intent.id, 'agent-b' as AgentId); // Reject intents.counter(intent.id, 'agent-b' as AgentId, 40); // Counter-offer ``` ### MandateManager — Standing Payment Authorizations ```typescript import { MandateManager } from '@paysentry/a2a'; const mandates = new MandateManager(new MemoryStorage()); const mandate = mandates.create({ grantorAgent: 'agent-a' as AgentId, granteeAgent: 'agent-b' as AgentId, maxAmount: 100, currency: 'USDC', maxFrequency: 10, windowMs: 86400000, expiresAt: new Date(Date.now() + 30 * 86400000).toISOString(), }); mandates.validate(mandate.id, 25); // Check if amount is within mandate mandates.recordSpend(mandate.id, 25); // Record actual spend against mandate ``` ### EscrowManager — Conditional Payments ```typescript import { EscrowManager } from '@paysentry/a2a'; const escrow = new EscrowManager(new MemoryStorage()); const contract = escrow.create({ payerAgent: 'agent-a' as AgentId, payeeAgent: 'agent-b' as AgentId, amount: 200, currency: 'USDC', conditions: [ { id: 'cond-1', description: 'Data delivered', type: 'manual', satisfied: false }, { id: 'cond-2', description: 'Quality verified', type: 'manual', satisfied: false }, ], expiresAt: new Date(Date.now() + 7 * 86400000).toISOString(), }); escrow.satisfyCondition(contract.id, 'cond-1'); // Mark condition met escrow.release(contract.id); // Release funds (all conditions must be met) escrow.refund(contract.id); // Refund to payer ``` ### AgentRegistry ```typescript import { AgentRegistry } from '@paysentry/a2a'; const registry = new AgentRegistry(new MemoryStorage()); registry.register({ agentId: 'agent-a' as AgentId, name: 'Research Agent', capabilities: ['web-search', 'analysis'], protocols: ['x402', 'a2a'], trustScore: 1.0, }); registry.updateTrustScore('agent-a' as AgentId, 0.95); registry.hasCapability('agent-a' as AgentId, 'web-search'); // true ``` --- ## @paysentry/dashboard JSON API + SSE event stream for real-time monitoring. No HTML UI — designed for agent consumption. ```typescript import { createDashboardServer } from '@paysentry/dashboard'; const server = createDashboardServer({ tracker, engine, alerts, disputes, provenance, eventBus, registry, port: 3001, }); ``` ### Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/status` | GET | System status, uptime, transaction count | | `/transactions` | GET | Transaction list (supports ?agent, ?limit filters) | | `/policies` | GET | Active policies | | `/alerts` | GET | Recent alerts | | `/disputes` | GET | Open disputes | | `/agents` | GET | Registered agents | | `/events` | GET | SSE stream of real-time events | --- ## Architecture ``` ┌──────────────────────────────────────────┐ │ Your AI Agent │ └──────────────────┬───────────────────────┘ │ ┌──────────────────v───────────────────────┐ │ MCP Server (10 tools) │ │ pay · balance · history · discover │ │ policies · evaluate · disputes · alerts │ └──────────────────┬───────────────────────┘ │ ┌──────────────────v───────────────────────┐ │ PaySentry Control Plane │ │ │ │ OBSERVE CONTROL PROTECT A2A │ │ tracking policies provenance intents │ │ alerts budgets disputes mandate │ │ analytics approval recovery escrow │ └────┬──────────┬──────────┬──────────┬────┘ │ │ │ │ ┌────v───┐ ┌───v────┐ ┌───v────┐ ┌───v────┐ │ x402 │ │ ACP │ │ AP2 │ │Dashboard│ │HTTP 402│ │Stripe/ │ │Agent- │ │JSON API │ │Protocol│ │Commrc │ │to-Agent│ │SSE Feed │ └────────┘ └────────┘ └────────┘ └────────┘ ``` --- ## Demo ```bash npx paysentry-demo ``` Output: ``` PaySentry Demo — AI Agent Payment Controls ══════════════════════════════════════════════════ Policy: Max $100/tx | Approval above $40 | Daily $500 | 5 tx/min Agent: agent-research-01 | Balance: $10000.00 [1/5] $25.00 → api.openai.com ✅ ALLOWED [2/5] $45.00 → anthropic.com ⚠️ REQUIRES APPROVAL [3/5] $150.00 → sketchy-api.xyz ❌ BLOCKED (above $100 limit) [4/5] $30.00 → api.openai.com ✅ ALLOWED + repeat recipient alert [5/5] 6 rapid payments ❌ RATE LIMITED (5 tx/min) ``` --- ## Roadmap - [x] Core spending policies and budget enforcement - [x] Real-time spend tracking and anomaly detection - [x] Dispute resolution and automated recovery - [x] Multi-protocol payment sandbox (x402, ACP, AP2) - [x] x402 protocol adapter with circuit breakers - [x] MCP payment server (10 tools: pay, balance, history, discover, policy CRUD, disputes, provenance, alerts) - [x] Agent-to-agent payment primitives (intents, mandates, escrow, agent registry) - [x] Dashboard API + SSE event stream for real-time monitoring - [x] Wallet-agnostic adapter layer (Coinbase, local signer, custom) with `createWallet()` factory - [ ] AP2 / Visa TAP protocol adapters