# Conto Documentation - Complete Reference > Conto is a control center for agentic payments using stablecoins. ## Quick Reference - Base URL: https://conto.finance - API Base: https://conto.finance/api - OpenAPI Spec: https://conto.finance/api/openapi - SDK Package: @conto_finance/sdk - Dashboard: https://conto.finance --- # Welcome to Conto Conto is a control center for agentic payments using stablecoins, cards, and micropayment protocols (x402 and MPP). ### Quick Start Link: https://conto.finance/docs/quickstart/setup Guided Tempo Testnet setup in about 10 minutes ### SDK Reference Link: https://conto.finance/docs/sdk/installation Full TypeScript SDK documentation ### Developer Tooling Link: https://conto.finance/docs/guides/developer-tooling CLI, setup probes, OpenAPI, MCP, webhooks, and production checks ### API Reference Link: https://conto.finance/api-docs Complete REST API documentation ### Policies Link: https://conto.finance/docs/policies/overview Configure spending rules and limits ## What is Conto? Conto provides controls for agent spending: - **Agent Identity Management** - Register and manage AI agents with unique identities - **Wallet Management** - Create and fund wallets on Base, Solana, or Tempo with configurable spend limits - **Policy Engine** - Define spending rules, limits, and approval workflows - **Payment Protocols** - Support for stablecoins, x402 micropayments, MPP sessions, A2A transfers, and card payments - **Transaction Monitoring** - Real-time visibility into all agent transactions - **Trust Intelligence** - Cross-organization trust scoring for counterparties ## Key Features Every payment request is evaluated against your configured policies before execution. Set spend limits, time windows, approved vendors, and more. Manage multiple AI agents with different permissions, wallets, and spending limits. Perfect for teams with multiple autonomous agents. Full visibility into agent transactions with real-time dashboards, alerts, and audit logs. Benefit from anonymized cross-organization trust data to identify risky counterparties before transacting. ## Integration Surfaces | Surface | Description | | ------------------ | ------------------------------------------------------------------ | | **TypeScript SDK** | Typed client for agent-scoped and admin-scoped integrations | | **REST API** | Lowest-level integration surface and source for generated clients | | **MCP Server** | Tool server for Claude Desktop, Claude Code, and other MCP clients | | **CLI Quickstart** | Guided provisioning flow for an agent, wallet, policy, and SDK key | | **Agent Skills** | Installable policy-enforcement skills for OpenClaw and Hermes | ## Developer Path The quickest path to a working integration is: 1. Run `npx @conto_finance/create-conto-agent` 2. Choose Tempo Testnet. The wizard funds the generated wallet with faucet `pathUSD` automatically 3. Run `npx conto doctor` (or call `GET /api/sdk/setup`) to verify agent status, wallet, scopes, and limits 4. Run `npx tsx example.ts --execute` for a small request and execute flow 5. Add webhooks, audit logs, and generated clients when moving toward production For a compact list of tools and checks, see [Developer Tooling](https://conto.finance/docs/guides/developer-tooling). ## Next Steps ### Create Account Link: https://conto.finance Sign up for Conto and create your organization ### Quick Start Guide Link: https://conto.finance/docs/quickstart/setup Follow our step-by-step setup guide ## Get in Touch Have questions, feedback, or need help? We'd love to hear from you. ### Discord Community Link: https://discord.gg/h7rYrpkrRt Join our Discord to chat with the team and other users ### Contact Support Link: mailto:support@conto.finance Email the team at support@conto.finance --- # Core Concepts Before integrating with Conto, it's helpful to understand the key concepts and terminology. ## Agents An **Agent** represents an AI agent connected to Conto. Each agent has: - **Name** - Human-readable identifier - **Type** - The agent framework (OpenAI, Claude, LangChain, Custom) - **Public Key** - Unique cryptographic identifier - **Status** - Active, Paused, Suspended, or Revoked - **SDK Keys** - API keys for authentication ```typescript // Example agent configuration { name: "Customer Support Agent", agentType: "OPENAI_ASSISTANT", publicKey: "0x1234...", status: "ACTIVE" } ``` ## Wallets A **Wallet** holds stablecoins for agent payments. Wallets can be linked to multiple agents with different spend limits. | Property | Description | | ------------- | --------------------------- | | `address` | Wallet address | | `balance` | Current stablecoin balance | | `chainType` | EVM or SOLANA | | `custodyType` | PRIVY, SPONGE, or EXTERNAL | | `status` | ACTIVE, FROZEN, or ARCHIVED | ### Supported Chains | Chain | Chain ID | Type | Currency | Environment | | -------------- | ---------------- | ------ | -------- | ----------------- | | Tempo Testnet | `42431` | EVM | pathUSD | Testnet (default) | | Tempo Mainnet | `4217` | EVM | USDC.e | Production | | Base | `8453` | EVM | USDC | Production | | Base Sepolia | `84532` | EVM | USDC | Testnet | | Ethereum | `1` | EVM | USDC | Production | | Arbitrum One | `42161` | EVM | USDC | Production | | Polygon | `137` | EVM | USDC | Production | | Solana Mainnet | `solana-mainnet` | Solana | USDC | Production | | Solana Devnet | `solana-devnet` | Solana | USDC | Testnet | Info: Tempo chains require no separate gas token. Tempo Testnet uses `pathUSD`; Tempo Mainnet uses `USDC.e`, making Tempo the easiest option for both testing and production. ## Cards A **Card** is a payment card (virtual or physical) that agents can use for traditional merchant payments. Today, Cards are registered manually for BYOC flows; native issuing through Conto is not yet generally available. | Property | Description | | ----------------- | --------------------------------- | | `provider` | STRIPE_ISSUING, LITHIC, or MANUAL | | `last4` | Last 4 digits of card number | | `cardType` | VIRTUAL or PHYSICAL | | `status` | ACTIVE, PAUSED, or CANCELLED | | `spendLimitDaily` | Card-level daily limit | Cards are assigned to agents via **Agent-Card Links**, similar to wallet links. Each agent gets independent spend limits, time windows, and merchant category controls on the shared card. Policies can also be linked directly to cards for rule engine enforcement. ## Agent-Wallet Links When you link an agent to a wallet, you configure: - **Spend Limits** - Per-transaction, daily, weekly, monthly limits - **Time Windows** - Allowed hours and days for transactions - **Delegation Type** - Full, Limited, View-Only, Preapproved, or Allowlist access ```typescript // Example agent-wallet link (business-hours restriction) { spendLimitPerTx: 500, // Max $500 per transaction spendLimitDaily: 2000, // Max $2,000 per day spendLimitMonthly: 20000, // Max $20,000 per month allowedHoursStart: 9, // 9 AM (default: 0) allowedHoursEnd: 17, // 5 PM (default: 24) allowedDays: ["Mon", "Tue", "Wed", "Thu", "Fri"] // default: all 7 days } ``` ## Policies A **Policy** is a set of rules that determine whether a payment should be approved, denied, or require manual approval. ### Policy Types ### Spend Limit Control maximum amounts per transaction, day, week, or month ### Time Window Restrict transactions to specific hours and days ### Counterparty Control which recipients are allowed based on trust ### Geographic Block transactions to sanctioned countries (OFAC compliance) ### Category Allow or block specific spending categories ### Approval Threshold Require manual approval above certain amounts ### Velocity Limit transaction frequency to prevent rapid drain ### x402 / MPP Controls for micropayment protocols (price ceilings, service allowlists) ### Policy Priority Policies are evaluated in priority order (highest first). This allows you to: 1. Evaluate critical security/compliance policies first (priority 90+) 2. Set default policies (priority 50) for normal operations 3. Add catch-all policies (priority 10) for fallbacks Priority only controls order. Policies still combine with AND logic, so a high-priority allow rule does not override a lower-priority deny or failed allowlist. ## Transactions A **Transaction** represents a stablecoin payment from a wallet to a recipient. ### Transaction Lifecycle ```mermaid stateDiagram-v2 [*] --> Pending: Request Created Pending --> Approved: Policy Passed Pending --> Denied: Policy Failed Pending --> RequiresApproval: Needs Human Review RequiresApproval --> Approved: Approved RequiresApproval --> Denied: Rejected Approved --> Executing: Execute Called Executing --> Completed: Tx Submitted Completed --> Confirmed: Block Confirmed Executing --> Failed: Tx Failed Confirmed --> [*] Denied --> [*] Failed --> [*] ``` ### Transaction Properties | Property | Description | | -------------- | --------------------------- | | `txHash` | Blockchain transaction hash | | `amount` | Payment amount | | `status` | Current transaction status | | `policyResult` | Policy evaluation result | | `purpose` | Reason for payment | | `category` | Spending category | ## Counterparties A **Counterparty** is a recipient of payments (vendor, merchant, agent, service, or platform). ### Trust Levels | Level | Score Range | Description | | ------------ | ----------- | --------------------------------------------- | | **TRUSTED** | 75 - 100 | High confidence, minimal restrictions | | **VERIFIED** | 50 - 74 | Established relationship, standard monitoring | | **UNKNOWN** | 20 - 49 | New or limited history, requires scrutiny | | **BLOCKED** | 0 - 19 | High risk, all transactions blocked | ### Trust Score Factors Trust scores are calculated based on: - **History (30%)** - Transaction count and volume - **Reliability (30%)** - Success rate, failed transactions - **Activity (20%)** - Account age, recency, consistency - **Verification (20%)** - Manual verification, network data, and [external trust providers](https://conto.finance/docs/integrations/trust-providers) (Fairscale for Solana, sanctions screening) Conto maintains both a **per-organization** trust score (your org's own view of a counterparty) and a **network** trust score (the cross-organization view). Policies can reference either via the `TRUST_SCORE` rule type. See [Trust Scoring](https://conto.finance/docs/guides/trust-scoring) for the full breakdown. ## Network Intelligence Conto's **Network Intelligence** provides anonymized cross-organization trust data: - See if other organizations have flagged an address - Benefit from collective fraud detection - Contribute to network safety (opt-in) For **Solana wallets**, trust scores are powered by [Fairscale](https://fairscale.xyz), a composable reputation scoring system that analyzes onchain behavioral signals like transaction patterns, staking activity, and token holdings. Solana addresses with no existing network data are automatically enriched with Fairscale scores, so you get real trust data instead of blank defaults. Conto also integrates with sanctions screening providers (Chainalysis, TRM Labs, and a built-in OFAC list) for compliance. See [Trust & Risk Providers](https://conto.finance/docs/integrations/trust-providers) for full details on all integrated providers. Note: Network Intelligence data is anonymized. Organizations share aggregate trust signals, not transaction details. ## SDK Keys vs API Keys Conto uses two types of authentication: | Credential | Format | Scope | Typical use | | ------------------------ | -------------------- | -------------------------- | ----------------------------------------------------- | | **Standard SDK key** | `conto_agent_xxx...` | One agent | The payment lifecycle and agent-scoped reads | | **Admin SDK key** | `conto_agent_xxx...` | One agent, elevated scopes | Delegated management of agents, wallets, and policies | | **Organization API key** | `conto_xxx...` | Whole organization | Backend/admin automation with `ContoAdmin` | - **Standard SDK keys** cover the payment lifecycle (`payments:request`, `payments:execute`, `payments:approve`, `payments:confirm`) plus read-only agent data. Policies, spend limits, and approvals govern what those payments can do. - **Admin SDK keys** add elevated `agents:write`, `wallets:write`, and `policies:write` scopes but remain tied to a specific agent identity. - **Organization API keys** are the canonical credential for backend provisioning, integrations, and the `ContoAdmin` SDK. ## Next Steps ### Quick Start Link: https://conto.finance/docs/quickstart/setup Set up your first agent ### Policy Guide Link: https://conto.finance/docs/policies/overview Configure spending policies --- # Quickstart End-to-end setup on **Tempo Testnet**. By the end you'll have a Conto organization, an AI agent, a funded testnet wallet, two test policies, and a verified onchain payment. Total time: about 10 minutes. No real funds required. ## What you'll build A Conto organization with your account An AI agent connected in Conto A Tempo Testnet wallet funded with pathUSD Spending policies that approve, require approval, or deny payments A verified test payment on Tempo Testnet ## Why Tempo Testnet? Tempo Testnet pays transaction fees in `pathUSD` itself, so you don't need a separate gas token. Combined with free faucet funds, it's the fastest way to test the full flow. | Property | Value | | -------- | ------------------------------------------------------------------ | | Network | Tempo Testnet | | Chain ID | `42431` | | Currency | `pathUSD` (TIP-20) | | Gas | Paid in `pathUSD`. No separate gas token. | | Explorer | [`explore.moderato.tempo.xyz`](https://explore.moderato.tempo.xyz) | Prefer the command line? The [CLI quickstart](https://conto.finance/docs/cli/quickstart) wraps every step below into one interactive command: ```bash npx @conto_finance/create-conto-agent ``` ## Choose Your Key Up Front Most developers need both of these at different points in the integration: | Use case | Credential | Env var | | ----------------------------------------------------------------------------------- | ---------------------------------- | ------------------- | | Create agents, link wallets, assign policies, or repair ownership from your backend | Organization API key (`conto_...`) | `CONTO_ORG_API_KEY` | | Let the agent call `/api/sdk/*` payment and read endpoints | Agent SDK key (`conto_agent_...`) | `CONTO_API_KEY` | Info: If your app provisions agents for end users, create the agent with an org API key first, then hand the agent its own SDK key for runtime payment calls. ## Step 1. Create your account 1. Visit [conto.finance](https://conto.finance) and sign up with email or Google OAuth. 2. Create your **organization**. This is the top-level container for agents, wallets, and policies. ## Step 2. Create and fund a wallet Sidebar > **Wallets > Create Wallet**. | Field | Value | |---|---| | Name | `Test Operations Wallet` | | Custody Type | `PRIVY` (recommended) | | Chain Type | `EVM` | | Chain | Tempo Testnet (`42431`) | Click **Provision**. Conto assigns an onchain address on Tempo Testnet. On the wallet detail page, click **Faucet**. Free testnet `pathUSD` arrives in seconds. For other custody options (`SPONGE`, `EXTERNAL`, `SMART_CONTRACT`), see [Custody modes](https://conto.finance/docs/guides/custody-modes). ## Step 3. Connect an agent Sidebar > **Agents > Connect Agent**. | Field | Example | |---|---| | Name | `Test Payment Agent` | | Type | `CUSTOM` (or your framework) | | Description | `Quickstart test agent` | Click **Connect Agent**. The agent starts in `ACTIVE` status. Via API: If you create agents through the API, active agents must include an owner. First fetch one stable membership id for your org: ```bash curl https://conto.finance/api/organizations/me/members \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" ``` Pick `members[].id` for the org member or service account that should own the agent, then create the agent: ```bash curl -X POST https://conto.finance/api/agents \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Test Payment Agent", "agentType": "CUSTOM", "description": "Quickstart test agent", "ownerMembershipId": "mem_abc123..." }' ``` Valid `agentType` values: `OPENAI_ASSISTANT`, `ANTHROPIC_CLAUDE`, `LANGCHAIN`, `AUTOGPT`, `CUSTOM`. Agent statuses: `ACTIVE`, `PAUSED`, `SUSPENDED`, `REVOKED`. ## Step 4. Link the wallet to the agent Open the agent detail page. In the **Wallets** section, click **Assign Wallet** and pick the Tempo Testnet wallet. Recommended for the quickstart: | Setting | Value | |---|---| | Per Transaction | `50` | | Daily Limit | `500` | | Weekly Limit | `2000` | | Monthly Limit | `5000` | Don't use Per Transaction `0` as a kill switch. Wallet-level spend limits treat `0` as unlimited. Use a positive limit for a cap, or suspend the agent when you need to block spend. Default limits, time windows, and other agent-wallet link defaults are listed on the [Defaults](https://conto.finance/reference/defaults) page. ## Step 5. Generate an SDK key On the agent detail page, click the **SDK Integration** tab. Click **Generate New Key**. Name it (e.g. `Testnet Key`). Keep the default `expiresInDays`. The default **Standard SDK key** preset covers everything in this guide: it includes `payments:request` for policy evaluation and `payments:execute` for Step 8's `POST /api/sdk/payments/{requestId}/execute` call. Reserve **Admin SDK keys** for agents that also manage agents, wallets, or policies. The full key is shown once. Save it to your environment: ```bash export CONTO_API_KEY="conto_agent_your_key_here" ``` For scopes and key types (`standard` vs `admin`), see [Authentication](https://conto.finance/docs/sdk/authentication). Verify the setup: ```bash curl https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_API_KEY" ``` You should see: - `agent.status` is `"ACTIVE"` - `wallets` contains your Tempo Testnet wallet with a balance - `scopes` includes `payments:request` and `payments:execute` (both are part of the standard preset) ## Step 6. Create two test policies These two policies together produce three different payment outcomes: ### Policy A: spend limit Sidebar > **Policies > New Policy**. | Field | Value | |---|---| | Name | `Test Spend Limit` | | Policy Type | `SPEND_LIMIT` | | Description | Deny transactions over $15 | | Field | Value | |---|---| | Rule Type | `MAX_AMOUNT` | | Operator | `LTE` | | Value | `15` | | Action | `ALLOW` | ### Policy B: approval threshold Sidebar > **Policies > New Policy**. | Field | Value | |---|---| | Name | `Test Approval Threshold` | | Policy Type | `APPROVAL_THRESHOLD` | | Description | Require approval for transactions over $10 | | Field | Value | |---|---| | Rule Type | `REQUIRE_APPROVAL_ABOVE` | | Operator | `GREATER_THAN` | | Value | `10` | | Action | `REQUIRE_APPROVAL` | ### Assign both to the agent Open the agent detail page > **Permissions** tab > assign **Test Spend Limit** and **Test Approval Threshold**. Policies combine with AND logic. The most restrictive outcome wins. Higher priority numbers evaluate first (default priority is `50`). ## Step 7. Run three test transactions With both policies active you should see three different outcomes: | Amount | Expected outcome | Why | | ------ | ------------------- | ---------------------------------------------------------- | | `5` | `APPROVED` | Under both thresholds | | `12` | `REQUIRES_APPROVAL` | Over the $10 approval threshold, under the $15 spend limit | | `20` | `DENIED` | Over the $15 spend limit | ### Test 1. `$5` should be APPROVED ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 5, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Test - under all limits", "category": "TESTING" }' ``` Response: `"status": "APPROVED"`, `"currency": "pathUSD"`. ### Test 2. `$12` should REQUIRE_APPROVAL ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 12, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Test - over approval threshold" }' ``` Response: `"status": "REQUIRES_APPROVAL"` with a violation referencing the approval threshold. ### Test 3. `$20` should be DENIED ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 20, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Test - over max amount" }' ``` Response: `"status": "DENIED"` with a violation referencing the spend limit. ## Step 8. Execute the approved payment This step uses the `payments:execute` scope, which your standard SDK key already includes. Capture the `requestId` from the approved request instead of copy-pasting it. This re-runs Test 1 and saves the id with `jq`: ```bash REQUEST_ID=$(curl -s -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount": 5, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Test - under all limits"}' \ | jq -r '.requestId') ``` Then execute it: ```bash curl -X POST "https://conto.finance/api/sdk/payments/$REQUEST_ID/execute" \ -H "Authorization: Bearer $CONTO_API_KEY" ``` The response includes: - `txHash`. Onchain transaction hash on Tempo Testnet. - `explorerUrl`. Link to view on [`explore.moderato.tempo.xyz`](https://explore.moderato.tempo.xyz). ## Step 9. Same flow via the SDK ```typescript import { Conto } from '@conto_finance/sdk'; const conto = new Conto({ apiKey: process.env.CONTO_API_KEY }); // Test 1 const test1 = await conto.payments.request({ amount: 5, recipientAddress: '0x1234567890abcdef1234567890abcdef12345678', purpose: 'Test - under all limits', }); console.log('Test 1:', test1.status); // APPROVED if (test1.status === 'APPROVED') { const result = await conto.payments.execute(test1.requestId); console.log('TX hash:', result.txHash); console.log('Explorer:', result.explorerUrl); } // Test 2 const test2 = await conto.payments.request({ amount: 12, recipientAddress: '0x1234567890abcdef1234567890abcdef12345678', purpose: 'Test - over approval threshold', }); console.log('Test 2:', test2.status); // REQUIRES_APPROVAL // Test 3 const test3 = await conto.payments.request({ amount: 20, recipientAddress: '0x1234567890abcdef1234567890abcdef12345678', purpose: 'Test - over max amount', }); console.log('Test 3:', test3.status); // DENIED ``` For one-call `request + execute`, set `autoExecute: true` on the request. It works with any key that has `payments:execute`, which the standard preset includes. ## Verify in the dashboard After Step 8: 1. Dashboard > **Transactions**. The transaction shows `Confirmed` with the Tempo Testnet chain. 2. Click the explorer link to verify onchain. 3. Dashboard > **Audit Logs**. See the full policy evaluation trail. You've verified policy enforcement and made a real onchain payment on Tempo Testnet. ## Troubleshooting Wallet-level per-transaction limit `0` means unlimited. Edit the wallet limits on the agent detail page and set a positive cap, or suspend the agent if all payments should stop. Policies combine with AND logic. If one policy denies while another requires approval, the denial wins. Check the **Permissions** tab for every assigned policy. The testnet wallet needs funding. Use the **Faucet** button on the wallet detail page. Invalid or expired SDK key. Generate a new one from the agent detail page. ## Moving to production Once the testnet flow works: 1. Create a production wallet on **Tempo Mainnet** (`USDC.e`), **Base** (`USDC`), or **Solana** (`USDC`). 2. Fund it with real stablecoins. 3. Link the production wallet to your agent with production-sized limits. 4. Update or create production policies. The test policies can remain for reference. Your SDK integration code does not change. Only the wallet and chain change. ## Next steps ### Agent sandbox quickstart Link: https://conto.finance/docs/quickstart/agent-sandbox Let an autonomous agent create a test-mode sandbox without human signup ### Connect your framework Link: https://conto.finance/docs/quickstart/connecting-agents OpenAI, Claude, LangChain, Python integration snippets ### SDK payments reference Link: https://conto.finance/docs/sdk/payments Full method signatures, options, error model ### Policy overview Link: https://conto.finance/docs/policies/overview Every policy type and rule type ### Defaults Link: https://conto.finance/reference/defaults Every default value in one place --- # Agent Sandbox Quickstart This quickstart is for autonomous agents, coding agents, and agent runtimes that need to evaluate Conto before a human creates a production account. The sandbox signup endpoint creates a test-mode organization, one agent, one Tempo Testnet wallet, an agent SDK key, and a sandbox organization API key. No email verification or human approval is required for sandbox creation. The anonymous sandbox is for testing only. Returned credentials are shown once, expire after 7 days, and should not be used for real funds or production automation. ## Discovery Start from the agent manifest: ```bash curl -sS https://conto.finance/.well-known/agent.json ``` Read these fields: | Field | Purpose | | ---------------------------------------- | ---------------------------------------------- | | `machineReadable.agentSandboxQuickstart` | This guide | | `machineReadable.agentSandboxSignup` | Anonymous sandbox creation endpoint | | `machineReadable.agentSandboxClaim` | Human claim endpoint | | `machineReadable.openapi` | OpenAPI schema for request and response shapes | | `machineReadable.llms` | Compact agent-readable docs index | If your runtime skips manifests, use the endpoint directly: ```bash curl -sS https://conto.finance/api/agents/sandbox ``` ## Create A Sandbox One command does the whole thing, including writing `.env.local`, `conto.config.json`, and a runnable `example.ts` to the current directory: ```bash npx @conto_finance/create-conto-agent --sandbox --json ``` Or call the endpoint directly: ```bash curl -sS -X POST https://conto.finance/api/agents/sandbox \ -H "Content-Type: application/json" \ -d '{ "name": "Research Buyer Agent", "agentType": "CUSTOM", "description": "Tests policy-checked payments from an autonomous agent", "metadata": { "runtime": "codex", "reason": "agent-accessibility-test" } }' > conto-sandbox.json ``` The response includes: | Response field | Save it as | Notes | | -------------------- | ----------------------- | ------------------------------------------------- | | `credentials.sdkKey` | `CONTO_API_KEY` | Bearer token for `/api/sdk/*` endpoints | | `credentials.apiKey` | `CONTO_SANDBOX_API_KEY` | Sandbox organization key and claim secret | | `agent.id` | `CONTO_AGENT_ID` | Created agent ID | | `wallet.id` | `CONTO_WALLET_ID` | Created wallet ID | | `wallet.address` | `CONTO_WALLET_ADDRESS` | Sender address for external-wallet approval tests | Example extraction: ```bash export CONTO_API_KEY="$(jq -r '.credentials.sdkKey' conto-sandbox.json)" export CONTO_SANDBOX_API_KEY="$(jq -r '.credentials.apiKey' conto-sandbox.json)" export CONTO_WALLET_ADDRESS="$(jq -r '.wallet.address' conto-sandbox.json)" ``` ## Inspect Capabilities Use the SDK key returned by sandbox signup: ```bash curl -sS https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_API_KEY" ``` This returns the authenticated agent, available wallets, spend limits, scopes, and payment endpoints. Use it as the runtime probe before attempting payment operations. Payment approval accepts `chainId` as either the numeric chain ID or the string value returned by setup. ## Run A Policy-Checked Payment Sandbox payments execute in simulated mode. Policy evaluation, spend tracking, receipts, and audit logs are real; no onchain transfer happens. You do not need a signer or a funded wallet to reach a completed payment. Request a small test payment. The policy engine evaluates it and returns `APPROVED`, `DENIED`, or `REQUIRES_APPROVAL`: ```bash curl -sS -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 3, "recipientAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "recipientName": "Test Vendor", "purpose": "Sandbox API credits", "category": "AI_SERVICES" }' > payment-request.json export REQUEST_ID="$(jq -r '.requestId' payment-request.json)" ``` If the status is `APPROVED`, execute it: ```bash curl -sS -X POST "https://conto.finance/api/sdk/payments/$REQUEST_ID/execute" \ -H "Authorization: Bearer $CONTO_API_KEY" ``` The success state for this quickstart is an execute response with `"status": "COMPLETED"`, `"simulated": true`, and a `txHash` receipt. The transaction appears in `GET /api/sdk/transactions` and counts against the sandbox spend limits. A request for more than the $5 per-transaction limit returns `DENIED` with the violated rule, which is the policy engine working as intended. ## Bring Your Own Signer (Optional) If your agent controls a real wallet key, pass its address as `publicKey` when creating the sandbox and use the external-wallet flow instead: `POST /api/sdk/payments/approve` returns an `approvalToken`, your signer performs the testnet transfer, and `POST /api/sdk/payments/{requestId}/confirm` records the real `txHash`: ```bash curl -sS -X POST "https://conto.finance/api/sdk/payments/$REQUEST_ID/confirm" \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"txHash\": \"$TX_HASH\", \"approvalToken\": \"$APPROVAL_TOKEN\" }" ``` Info: Production integrations with managed wallets use the same `request -> execute` flow with real onchain execution, or `autoExecute` for single-call payments. ## Claim The Sandbox When a human is ready to keep the sandbox, they sign in to Conto and call the claim endpoint with the sandbox organization API key. The sandbox key can be sent in the JSON body: ```bash curl -sS -X POST https://conto.finance/api/agents/sandbox/claim \ -H "Content-Type: application/json" \ -d "{ \"sandboxApiKey\": \"$CONTO_SANDBOX_API_KEY\" }" ``` The claim request must include a signed-in Conto browser or app session. Claiming transfers the sandbox organization and agent ownership to that verified human account. ## Existing Organizations If a human organization owner has already invited an agent, use organization-token registration instead of anonymous sandbox signup: ```bash curl -sS https://conto.finance/api/agents/register ``` With a registration token, the agent can join the existing organization and receive a scoped SDK key: ```bash curl -sS -X POST https://conto.finance/api/agents/register \ -H "Content-Type: application/json" \ -d '{ "registrationToken": "registration_token_from_human_owner", "name": "Research Buyer Agent", "agentType": "CUSTOM" }' ``` ## Agent Checklist 1. Fetch `/.well-known/agent.json`. 2. Read `machineReadable.agentSandboxQuickstart` and `machineReadable.agentSandboxSignup`. 3. `POST /api/agents/sandbox`. 4. Store returned keys securely; they are shown once. 5. Call `GET /api/sdk/setup` with `credentials.sdkKey`. 6. `POST /api/sdk/payments/request`, then `POST /api/sdk/payments/{requestId}/execute`. 7. Verify the execute response shows `status: COMPLETED` and `simulated: true`. 8. Ask a human to claim the sandbox before the credentials expire. ## Next Steps ### Connecting Agents Link: https://conto.finance/docs/quickstart/connecting-agents Wire Conto into OpenAI, Claude, LangChain, Python, and custom runtimes ### Payments API Link: https://conto.finance/docs/sdk/payments Request, approve, execute, confirm, and inspect payment state ### Custody Modes Link: https://conto.finance/docs/guides/custody-modes Choose managed execution or external-wallet approval flows ### OpenAPI Link: https://conto.finance/docs/api/reference Generate clients and inspect endpoint schemas --- # Connecting Agents via API This guide shows how to connect different AI agent frameworks to Conto, enabling them to request, approve, execute, and confirm payments depending on the wallet model you choose. Info: Before integrating, make sure you've [connected your agent, linked a wallet, and generated an SDK key](https://conto.finance/docs/quickstart/setup). If you are an autonomous agent evaluating Conto without a human account, use the [agent sandbox quickstart](https://conto.finance/docs/quickstart/agent-sandbox) first. ## SDK Authentication All SDK endpoints require the agent's SDK key in the `Authorization` header: ``` Authorization: Bearer conto_agent_xxxxx... ``` Set that key as `CONTO_API_KEY`. Do not use `CONTO_ORG_API_KEY` for these `/api/sdk/*` calls. ## Choose Your Wallet Flow First Before wiring up tool calls, decide whether your agent uses a managed wallet or an external wallet. | Wallet model | Who holds the keys | Endpoints | What Conto can stop | | ------------------------------- | ------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------- | | **Managed** (`PRIVY`, `SPONGE`) | The custody provider | `request -> execute` | Conto stays in the execution path and can block the spend | | **External** (`EXTERNAL`) | You, your agent, or your wallet stack | `approve -> transfer -> confirm` | Conto can gate the Conto-routed flow, but cannot block a direct self-signed transfer outside Conto | The framework examples below assume a managed wallet and use `request -> execute`. If your agent holds the signing keys, switch to `approve -> transfer -> confirm` instead. See [Custody Modes](https://conto.finance/docs/guides/custody-modes) for the full breakdown. ## Register The Wallet The Right Way If your integration already has a wallet, register that same wallet in Conto instead of creating a second one. - For an existing **Privy** wallet, create the Conto wallet with `custodyType=PRIVY`, `externalWalletId`, and `address`. Conto will attach or reuse the wallet record instead of minting a new Privy wallet. - For a self-custodied wallet or MPC stack outside Conto, register it as `custodyType=EXTERNAL` with its `address`. - Wallet registration is idempotent per `externalWalletId + chainId` or `address + chainId`, so your backend can safely retry the request. If the signer lives in a different Privy app than the one Conto is configured to use, do not use the managed `PRIVY` attach path. Register that wallet as `EXTERNAL` and use the external `approve -> transfer -> confirm` flow instead. ## The Shared Payment Helper Every framework integration wraps the same two-call flow: request (policy check), then execute. Define it once and reuse it from each framework's tool handler: ```typescript const CONTO_API_KEY = process.env.CONTO_API_KEY; type PaymentInput = { amount: number; recipientAddress: string; recipientName?: string; purpose: string; category?: string; }; async function executeContoPayment(input: PaymentInput) { // Step 1: Request payment authorization (policy check) const request = await fetch('https://conto.finance/api/sdk/payments/request', { method: 'POST', headers: { Authorization: `Bearer ${CONTO_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ category: 'OPERATIONS', ...input }), }).then((r) => r.json()); if (request.status === 'DENIED') { return { success: false, error: request.reasons.join(', ') }; } if (request.status === 'REQUIRES_APPROVAL') { return { success: false, pending: true, requestId: request.requestId, message: 'Payment requires manual approval', }; } // Step 2: Execute the approved payment const result = await fetch( `https://conto.finance/api/sdk/payments/${request.requestId}/execute`, { method: 'POST', headers: { Authorization: `Bearer ${CONTO_API_KEY}` }, } ).then((r) => r.json()); return { success: true, transactionHash: result.txHash, amount: result.amount, explorerUrl: result.explorerUrl, }; } ``` The Python equivalent for Python-based frameworks: ```python import os import requests CONTO_API_KEY = os.environ.get('CONTO_API_KEY') CONTO_API_URL = 'https://conto.finance/api' def make_payment(amount: float, recipient_address: str, purpose: str, recipient_name: str = None): """Make a payment via Conto API""" headers = { 'Authorization': f'Bearer {CONTO_API_KEY}', 'Content-Type': 'application/json' } # Step 1: Request authorization response = requests.post( f'{CONTO_API_URL}/sdk/payments/request', headers=headers, json={ 'amount': amount, 'recipientAddress': recipient_address, 'purpose': purpose, 'recipientName': recipient_name, 'category': 'OPERATIONS' } ) request_data = response.json() if request_data.get('status') == 'DENIED': return {'success': False, 'error': ', '.join(request_data.get('reasons', []))} if request_data.get('status') == 'REQUIRES_APPROVAL': return {'success': False, 'pending': True, 'requestId': request_data['requestId']} # Step 2: Execute the payment result = requests.post( f'{CONTO_API_URL}/sdk/payments/{request_data["requestId"]}/execute', headers=headers ).json() return { 'success': True, 'transactionHash': result.get('txHash'), 'amount': result.get('amount'), 'explorerUrl': result.get('explorerUrl') } ``` ## Framework Integrations With the shared helper in place, each framework only needs its own tool wiring. ### OpenAI Assistants ```typescript import OpenAI from 'openai'; const openai = new OpenAI(); // Define the payment tool for your assistant const tools = [ { type: 'function', function: { name: 'make_payment', description: 'Make a payment to a recipient', parameters: { type: 'object', properties: { amount: { type: 'number', description: 'Payment amount in USD' }, recipientAddress: { type: 'string', description: 'Recipient wallet address' }, recipientName: { type: 'string', description: 'Recipient name' }, purpose: { type: 'string', description: 'Payment purpose' }, }, required: ['amount', 'recipientAddress', 'purpose'], }, }, }, ]; ``` In your OpenAI chat loop, check for `tool_calls` in the response. When the model calls `make_payment`, parse the arguments, pass them to `executeContoPayment`, and send the result back as a tool response message. ### Anthropic Claude (Tool Use) ```typescript import Anthropic from '@anthropic-ai/sdk'; const anthropic = new Anthropic(); const tools = [ { name: 'make_payment', description: 'Make a payment to a recipient using Conto', input_schema: { type: 'object', properties: { amount: { type: 'number', description: 'Payment amount in USD' }, recipientAddress: { type: 'string', description: 'Recipient wallet address' }, recipientName: { type: 'string', description: 'Recipient name' }, purpose: { type: 'string', description: 'Payment purpose' }, }, required: ['amount', 'recipientAddress', 'purpose'], }, }, ]; async function runAgent(userMessage: string) { const response = await anthropic.messages.create({ model: 'claude-opus-4-8', max_tokens: 1024, tools: tools, messages: [{ role: 'user', content: userMessage }], }); for (const block of response.content) { if (block.type === 'tool_use' && block.name === 'make_payment') { const result = await executeContoPayment(block.input as PaymentInput); // Continue conversation with tool result... } } } ``` ### LangChain ```typescript import { Tool } from '@langchain/core/tools'; class ContoPaymentTool extends Tool { name = 'conto_payment'; description = 'Make a payment using Conto. Input should be JSON with amount, recipientAddress, and purpose.'; async _call(input: string): Promise { const params = JSON.parse(input) as PaymentInput; return JSON.stringify(await executeContoPayment(params)); } } ``` ### Python (Any Framework) Register `make_payment` (defined above) as a tool in your framework of choice (CrewAI, AutoGen, or a custom loop) and return its dict result to the model as the tool output. ## Payment Endpoints Reference | Endpoint | Method | Description | | -------------------------------- | ------ | ----------------------------------- | | `/api/sdk/payments/request` | POST | Request payment authorization | | `/api/sdk/payments/approve` | POST | Approve payment for external wallet | | `/api/sdk/payments/{id}/execute` | POST | Execute approved payment | | `/api/sdk/payments/{id}/confirm` | POST | Confirm external wallet payment | | `/api/sdk/payments/{id}` | GET | Get payment status | ## Error Handling | Status | Code | Description | | ------ | ---------------------- | -------------------------------------------------------- | | 400 | `INVALID_INPUT` | Invalid request data | | 401 | `AUTH_FAILED` | Invalid, expired, or suspended-agent SDK key | | 400 | `INSUFFICIENT_BALANCE` | Wallet balance too low (at execution) | | 429 | `RATE_LIMITED` | Too many requests | Policy denials are not HTTP errors. When a payment violates a policy (spend limit, time window, counterparty rule), `/api/sdk/payments/request` returns `200` with `status: "DENIED"` and a `violations` array describing each violation (for example `DAILY_LIMIT` or `TIME_WINDOW`). For full error handling patterns, see [Error Handling](https://conto.finance/docs/sdk/error-handling). ## Next Steps ### Make Your First Payment Link: https://conto.finance/docs/quickstart/setup Detailed payment flow walkthrough ### SDK Reference Link: https://conto.finance/docs/sdk/payments Full SDK documentation ### Examples Link: https://conto.finance/docs/sdk/examples Complete integration examples ### Error Handling Link: https://conto.finance/docs/sdk/error-handling Handle errors gracefully --- # Conto Pay Conto Pay is the hosted way to run agentic payments in Conto. Instead of wiring your own runtime, wallet, and approval flow, Conto provisions a managed payment agent workspace for you and exposes it through the dashboard and assistant. The hosted workspace now behaves like an operator console, not just a payment form. You can share a named Conto Pay profile, create tracked checkout links, check wallet readiness, refresh balances, request Tempo sandbox funds, inspect payment state, retry failed payments, and tune hosted controls directly from chat. Info: Conto Pay is currently available through a guided rollout. Teams start in sandbox, then work with Conto to confirm workspace readiness, launch support ownership, payment controls, and live-funds scope before moving to production use. The Activation card shows the customer launch path across hosted setup, sandbox proof, live review, and live-enabled mode. When the card is ready, operators can copy a launch evidence packet and click **Request live review** to open a Conto support review for live funds. Conto records the support owner, approved funding scope, trust-review owner, alert review cadence, and deployment evidence before enabling live money movement. ## Paying Any Wallet, And The Conto Network Conto Pay agents can pay any wallet address you add as an approved recipient. Every payment follows the same hosted draft, authorization, approval, and send path, whether or not the payee is on Conto Pay. When the payee is another organization's hosted Conto Pay workspace, you get more than an address. The workspace is added as a verified network recipient, so agents resolve it by name, confirm its identity, and get a trust review if its details later change. The target workspace can be resolved by: - a Conto Pay handle such as `@vendor-org` or `@vendor-org/accounts-payable` - the target account display name or public search aliases such as "Vendor AP" - the target organization slug or organization name - the target agent ID, agent slug, or agent name - the target hosted wallet address Once added, the recipient is stored in your normal Conto Pay allowlist as a verified `CONTO_PAY_NETWORK` counterparty. Operators do not need a separate workflow for network payments; they use the same assistant, draft, policies, approvals, and send actions as any other hosted payment. ## Conto Pay vs AI Assistant vs MCP Conto has three natural-language surfaces. They differ by who acts, how you reach them, and whether they move funds onchain: | Surface | Who acts | Reach it via | Auth | Onchain execution | | -------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------- | | **Conto Pay** | A Conto-hosted payment agent | Dashboard chat workspace | Dashboard login | Yes, through the normal request, approval, and execution flow | | **[AI Assistant](https://conto.finance/docs/assistant/overview)** (Conto AI) | You, working in the dashboard | Dashboard chat panel | Dashboard login | No. It configures agents, wallets, and policies. Payments still run through the SDK or agent flow | | **[MCP Server](https://conto.finance/docs/mcp/overview)** | Your own external AI agent (Claude Desktop, Claude Code, other MCP clients) | An MCP client wired to your agent | Agent SDK key (`conto_agent_...`) | Yes, with custody-aware policy checks before execution | ## What Makes It Different | Self Setup | Conto Pay | | -------------------------------------------------------- | ----------------------------------------------------------------------------------- | | You connect and manage your own agent runtime | Conto hosts and operates the payment agent | | You link wallets and configure the workflow yourself | Conto provisions the wallet, policies, approvals, and assistant controls | | Framework installation is part of the primary setup path | Using the hosted workspace is the primary path; framework handoff is optional later | | You inspect payment state across your own tools | Conto Pay keeps draft, approval, and retry state in one hosted workspace | ## What Conto Provisions When you open Conto Pay, the workspace is created with: - a Conto-managed payment agent - a hosted wallet with readiness tracked in the workspace - starter spend policies - recipient allowlist controls - an approval workflow - a hosted profile URL and shareable Conto Pay handle - durable hosted checkout links with status, expiry, open tracking, and cancellation controls - hosted profile trust reports with submitter status pages, profile evidence snapshots, operator review controls, and directory-hide adjudication for reported profiles - editable account names, descriptions, and public search aliases for easier agent discovery - Conto Pay contacts with aliases, favorites, payment defaults, trust review, and payment controls for saved and recent agent payment identities - a unified activity inbox for payments, requests, receipts, and next actions - launch funnel insights for checkout-link opens, request preparation, authorization, send failures, and successful closed-loop sends - launch-readiness evidence that Conto support can review before a customer cohort moves forward - customer-triggered live-review requests that create a support-visible review item - assistant actions for wallet refresh, payment inspection, retry, and cancellation - network-recipient resolution for other hosted Conto Pay workspaces - a pre-minted SDK key for optional later integration The workspace starts in sandbox so teams can verify the experience with the same hosted control surface they will use when moving to approved live money. After sandbox evidence is ready, customers can request live review from the Activation card; Conto support enables live mode only for approved cohorts that pass the live rollout gate. ## Wallet Readiness Conto Pay does not show the workspace as ready just because the page exists. The hosted agent still needs a provisioned wallet and enough balance to operate safely. - the workspace shows whether the hosted wallet is ready to send - if the hosted wallet is not ready, the assistant can explain what is missing - on Tempo testnet, the assistant can request sandbox pathUSD for the hosted wallet - once funded, you can refresh the wallet balance from chat before authorizing a payment The goal is to keep setup, funding, and payment execution inside the same Conto Pay workflow. ## Profiles, Requests, And Receipts Each hosted Conto Pay workspace has a stable profile identity, not just a wallet address. ### Profile Identity - your organization gets a Conto Pay handle such as `@vendor-org` or `@vendor-org/accounts-payable` - operators can edit the public account name, description, and directory listing state from the Conto Pay console, and add public search aliases such as `Vendor AP`, `Accounts Payable`, or a team name so humans and agents can find the profile without knowing the exact handle - the workspace exposes a hosted profile URL that other operators can open or copy directly - the hosted profile shows public `paymentMode`, agent-readiness state, and the safe action status for profile verification, Pay, Request, and live-money presentation - the hosted profile includes **Pay** and **Request** actions that generate copyable deep links with the current amount, memo, and invoice fields; shared profile links can be prefilled with `mode`, `amount`, `purpose`, and `invoiceId`, so a profile page can open directly as a lightweight pay or request checkout - hosted profile pages include a rate-limited report flow for suspicious checkout links, stale profile details, spam, or impersonation concerns; submitters receive a `/pay-report/{reportId}` status page with customer-safe outcomes and next steps, while operators review, resolve, close, or hide reported profiles from broad directory search in the Conto Pay console ### Profile API - the hosted profile exposes a copyable Profile API URL such as `/api/conto-pay/profiles/vendor-org/accounts-payable` for agent-readable identity lookup - the Profile API returns public identity metadata, verification signals, capabilities, settlement details, activation status, public live-review status, customer-safe rollout policy messaging, a compact `agentReadiness` contract, canonical Pay/Request links, structured action fields, and URL templates without exposing dashboard-only relationship state - the Profile API includes a stable `profile.integrity.fingerprint` and cache `ETag`, so agents can compare the current public identity with a saved contact before preparing payment - the Profile API includes `profile.discovery.aliases`, query examples, and an agent instruction so agents can explain how the account should be searched or referenced - when a shared Profile API URL includes `?intent={intentId}` (tracked checkout links embed this in their URLs so opens are recorded), the response includes a public `checkoutIntent` object with the link status, mode, amount, memo, invoice ID, expiry, open count, and cancellation state; tracked Profile API responses use fresh `no-store` responses so agents can see current link state before staging work How agents should consume the Profile API (`actions.pay` / `actions.request` metadata, `agentReadiness` decisions, fingerprint caching, and directory handoffs) is covered in [Sharing Your Hosted Profile](https://conto.finance/docs/conto-pay/assistant-workflow#sharing-your-hosted-profile). ### Requests, Receipts, And Contacts - hosted payment requests open in a review page at `/pay-requests/{requestId}` (see [Hosted Payment Requests](#hosted-payment-requests)) - direct Conto Pay payments expose a hosted status and receipt page at `/pay-status/{paymentRequestId}` - the [activity inbox](#activity-inbox-and-receipts) keeps payments, requests, receipts, and next actions in one timeline, and the Conto Pay contacts list turns saved network recipients and recent request counterparties into reusable agent payment identities with aliases, favorites, defaults, payee-specific limits, and trust-snapshot warnings; unresolved contact trust warnings block saved-contact payment preparation until the operator reviews the current public profile This matters because the hosted workflow no longer starts only from "enter a wallet and send." Teams can share a profile, request payment, review a request, and refer back to the same hosted receipt without leaving Conto Pay. ## How To Use Conto Pay Go to **Conto Pay** in the dashboard. Conto provisions or loads your hosted payment agent and its managed wallet automatically. Ask the assistant whether the hosted wallet is ready. If you are in sandbox, refresh the balance or request Tempo testnet funds before you try to send money. Use the assistant to add approved recipients and keep the allowlist current before you try to send money. If you want to pay another Conto Pay workspace, resolve it by handle, account display name, search alias, organization, agent, or hosted wallet address and add it as a network recipient first. Name the public account, add any search aliases your counterparties use, then copy your hosted profile URL, Profile API URL, Conto Pay handle, or Agent handoff packet when another operator or agent needs to discover, verify, pay, or request from your workspace. Create a pay or request checkout link with amount, memo, and invoice details. Conto stores the link as a tracked intent so you can see opens and cancel stale links without moving money. If another team sent a hosted request or shared a profile URL, prepare that request or staged draft from the hosted link before you authorize anything. Set the recipient, amount, and purpose. The assistant maintains the current payment draft for the hosted agent. Ask Conto Pay to authorize the payment. Conto evaluates the same wallet and agent policies used elsewhere in the platform. Review pending approvals, inspect the payment state, approve or deny the request, then send or retry the payment from the hosted workspace. Follow the Activation card launch path. After hosted setup and closed-loop sandbox evidence are ready, use it to request Conto live review. The request is visible in the workspace support packet and internal launch dashboard. ## How Payments Are Initiated Conto Pay is designed to behave like a hosted agent, so the assistant is the primary control surface. Everything from wallet readiness and recipient management through drafting, authorizing, approving, retrying, and sending happens through natural-language instructions, and Conto turns those operator instructions into the normal request, review, and execution flow rather than bypassing platform controls. For the full catalog of operator tasks with example prompts, see [Common Tasks in Using the Assistant](https://conto.finance/docs/conto-pay/assistant-workflow#common-tasks). ## Hosted Controls Conto Pay uses the normal Conto control model, but the hosted workspace exposes the most important operator controls directly in chat: - recipient allowlists for who the hosted agent can pay - approval thresholds for when human review is required - wallet spend limits for per-transaction and daily controls - payment inspection so operators can see whether a request is ready, waiting, failed, or blocked - profile and checkout-link analytics so operators can see whether a shared checkout link was opened - public Profile API rate limits to reduce scraping and request bursts - trust-report review controls that can hide a reported profile from broad directory search while keeping direct profile links, exact-handle resolution, checkout-link status, and public report status pages available This gives teams a managed surface without creating a separate rules engine or approval path. ## Checkout Links Checkout links are the lightweight handoff layer for humans and agents. They are useful when the recipient, amount, memo, or invoice details are already known, but the payer still needs to review and authorize the payment inside Conto Pay. Each checkout intent stores: - whether it is a Pay link or Request link - amount, currency, memo, and request-only invoice ID - hosted profile URL and direct `/conto-pay` handoff URL - profile API URL for agent-readable verification - expiry and lifecycle status (`ACTIVE`, `USED`, `EXPIRED`, or `CANCELLED`) - open count and last-opened timestamp - cancellation timestamp when the operator cancels the link Checkout links do **not** authorize or send money. Opening a link only preloads the hosted profile or assistant prompt. The payer still has to prepare the draft, authorize it, pass policy checks, and complete any required approval before funds move. ## Hosted Payment Requests Conto Pay is not limited to payer-initiated payments. A hosted workspace can also request payment from another hosted Conto Pay workspace. The normal pattern is: 1. Share your Conto Pay handle or hosted profile URL. 2. The payee creates a hosted request with amount, purpose, and optional invoice details. 3. Conto creates a hosted review page at `/pay-requests/{requestId}` for the payer. 4. The payer prepares that request into their current Conto Pay draft. 5. The payer still authorizes, approves, and sends using the normal hosted controls. Preparing a request never bypasses policy evaluation. It only stages the payer, amount, and purpose inside the hosted draft so the normal approval path can continue. ## Activity Inbox And Receipts The hosted workspace now behaves more like an operator console than a single payment form. - the contacts list shows saved network payees and recent hosted request counterparties with aliases, favorite status, payment defaults, payee limits, handles, profile links, trust status, profile-change warnings, and Pay/Request/Save/Star/Defaults/Limits actions - the checkout links list shows recent pay/request links, open counts, last-opened timestamps, and cancellation controls - the activity inbox shows direct payments, hosted payment requests, and the next likely operator action - receipt and status pages give human users and agents the same shared view of a payment - hosted links can deep-link back into Conto Pay so the assistant can inspect, retry, or explain the current state For teams running organization-to-organization payments, this makes the closed loop visible. The same hosted surfaces cover discovery, request review, authorization, execution, and post-payment receipt lookup. ## Closed-Loop Network Payments When the selected recipient is another hosted Conto Pay workspace on the same chain, Conto Pay can complete the transfer as a hosted closed-loop payment. - the payee is first verified and stored as a network recipient in your allowlist - the payment is still drafted and authorized like any other Conto Pay payment - the same wallet policies, agent policies, approval thresholds, and approval workflows still apply - the managed execution service records the transfer as `A2A` - the payer wallet is debited and the recipient wallet is credited inside Conto's hosted ledger - if later chain confirmation fails, the provisional recipient credit is rolled back with the other ledger effects This matters because network payments keep the hosted operating model intact. You do not switch to a separate protocol, a different assistant, or a weaker policy path just because the payee is also on Conto. ## Policy And Approval Model Conto Pay does **not** use a separate rule engine. The hosted workspace still relies on the normal Conto controls: - wallet policies - agent policies - recipient allowlists - approval thresholds - approval workflows That means sandbox and live money can share the same control model even when the funding and execution environment changes. The Conto Pay workspace exposes an activation status for both users and agents. A workspace can be setup-required, sandbox-ready, ready for live review, or live-enabled. Agents should read the public Profile API and check `activation.livePaymentsEnabled` before presenting a payee as eligible for live money movement. The workspace also exposes `liveReviewRequest`. If live funds are not enabled yet, the operator can submit a live-review request from the Activation card. Conto Pay dedupes that request into one support alert and includes the review status, customer-safe rollout policy, and sanitized `publicRolloutEvidence` summary in the Launch support packet. The customer-safe launch evidence can also be fetched by authenticated agents from `GET /api/conto-pay/launch-evidence` as `{ launchEvidence }`. That packet includes public `paymentMode`, compact `agentReadiness.actions`, and a customer-safe `liveReview.rolloutPolicy` summary so agents can explain no-review-yet, controlled rollout, open rollout, or paused approvals without seeing internal allowlist configuration. When Conto support starts review, enables live mode, or returns the workspace to sandbox, the support packet also includes the latest review action, reviewer, review time, environment transition, saved launch-ops owner fields, and resulting live-payments flag. For guided cohorts, Conto support can export a prefilled alpha signoff Markdown note from the internal launch dashboard. It summarizes workspace readiness, live-review state, rollout gate eligibility, closed-loop evidence, funnel alerts, trust reports, and the remaining go/no-go fields for the launch owner. The same dashboard and signoff show public-rollout prerequisites that require human approval before Conto Pay moves beyond guided alpha, such as legal/compliance review, live rollout scope, funding ownership, support coverage, and customer-facing claims review. Conto support can record the approval evidence in launch ops so it appears in the dashboard, API exports, and signoff packet. ## Typical Sandbox Flow In sandbox, a common first run looks like this: 1. Open Conto Pay and ask whether the hosted wallet is ready. 2. Review the activation card to see whether setup, sandbox evidence, or Conto live review is next. 3. If needed, request Tempo testnet funds for the hosted wallet. 4. Review your hosted profile, handle, and Profile API URL. 5. Create a tracked checkout link if you need to share pay or request details before the payer opens Conto Pay. 6. Add or confirm an allowlisted recipient, or resolve another Conto Pay workspace as a network recipient. 7. Set recipient, amount, and purpose for the draft. 8. Authorize the request. 9. Inspect whether the request is approved, waiting for approval, denied, or ready to retry. 10. Approve, send, or retry from the same assistant thread. ## Example Network Flow If you want to pay another organization already using Conto Pay, see the step-by-step prompts in [Example Network Prompts](https://conto.finance/docs/conto-pay/assistant-workflow#example-network-prompts): resolve the target workspace, add it as a network recipient, set the amount and purpose, authorize, inspect, and send. ## Next Steps ### Use the Assistant Link: https://conto.finance/docs/conto-pay/assistant-workflow Learn the core prompts and payment lifecycle for the hosted Conto Pay agent ### Live Rollout Link: https://conto.finance/docs/conto-pay/live-rollout Understand launch evidence, live review, rollout gates, and public rollout evidence ### Approval Workflows Link: https://conto.finance/docs/guides/approval-workflows See how pending payment approvals are reviewed and resolved ### Assistant Overview Link: https://conto.finance/docs/assistant/overview Understand how the AI Assistant operates platform workflows through natural language --- # Using the Conto Pay Assistant Conto Pay is meant to feel like an agent, not just a wallet screen. The assistant is the main way to operate the hosted workspace: it keeps track of wallet readiness, the current payment draft, recipient controls, approval routing, and payment execution state. ## Activation And Live Mode When a user asks whether Conto Pay is ready, the assistant should check the workspace status or profile. Those tools expose the current activation status, whether live payments are enabled, and the latest live-review request state. Treat `livePaymentsEnabled` as the source of truth: if it is false, guide the user through sandbox testing, launch evidence, or the Activation card live-review request instead of describing the workspace as live-money ready. For launch review prep, in-product agents can call `get_conto_pay_launch_evidence`, and authenticated external agents can fetch `GET /api/conto-pay/launch-evidence`. Both return the same `{ launchEvidence }` packet as the Activation card copy action and intentionally omit SDK key prefixes and support-only review metadata. Use `launchEvidence.liveReview.rolloutPolicy` to explain no-review-yet, controlled rollout, open rollout, or paused approvals in customer-safe language. Use `launchEvidence.publicRolloutEvidence` to show missing public-rollout evidence labels and counts without exposing owner names, funding details, or internal reviewer metadata. `get_conto_pay_profile` also returns compact `rolloutReadiness` and sanitized `publicRolloutEvidence` summaries for ordinary setup/profile questions, while launch evidence remains the complete customer-safe handoff packet. ## Common Tasks | Goal | Example prompt | | --------------------------- | ----------------------------------------------------------------------------------------------------- | | Check workspace status | `Show me my Conto Pay workspace and payment draft.` | | Show my profile | `Show my Conto Pay handle, profile URL, and setup checklist.` | | Name my account | `Name my Conto Pay account Vendor AP and add search aliases for Accounts Payable and Vendor Billing.` | | Check wallet readiness | `Check why the Conto Pay wallet is not ready yet and what needs attention.` | | Refresh balance | `Refresh my Conto Pay wallet balance and tell me if it is ready to send.` | | Request sandbox funds | `Request Tempo testnet pathUSD for the Conto Pay wallet.` | | Review hosted controls | `Show me the current Conto Pay wallet limits and approval threshold.` | | Copy launch evidence | `Show my Conto Pay launch evidence and support packet for live review.` | | Fetch launch evidence tool | `Get my Conto Pay launch evidence packet for the live-review handoff.` | | Search the directory | `Search Conto Pay for Vendor Org and show the best matches.` | | Create a checkout link | `Create a Conto Pay request link for 250 pathUSD with memo "Invoice INV-100".` | | Cancel a checkout link | `Cancel the active checkout link for invoice INV-100.` | | Review contacts | `List my Conto Pay contacts and show which ones are saved.` | | Rename a contact | `Rename @vendor-org/accounts-payable to Vendor AP in my Conto Pay contacts.` | | Favorite a contact | `Add @vendor-org/accounts-payable to my favorite Conto Pay contacts.` | | Set contact defaults | `Set payment defaults for @vendor-org/accounts-payable to 250 pathUSD for June settlement.` | | Set contact limits | `Limit @vendor-org/accounts-payable to 500 pathUSD per Conto Pay payment.` | | Review contact trust | `Review and trust the current Conto Pay profile for @vendor-org/accounts-payable.` | | Pay with saved defaults | `Pay @vendor-org/accounts-payable using its saved Conto Pay defaults.` | | Add a recipient | `Add Acme Labs as a Conto Pay recipient at 0x1234...` | | Resolve a network payee | `Resolve @vendor-org/accounts-payable and show me the target wallet and chain.` | | Add a network recipient | `Add @vendor-org/accounts-payable as a Conto Pay network recipient and make it my default recipient.` | | Create a payment request | `Request 250 dollars from @buyer-org/accounts-payable for June settlement.` | | Review payment requests | `List incoming and outgoing Conto Pay payment requests.` | | Prepare an incoming request | `Prepare the latest incoming Conto Pay payment request for payment.` | | Set the payment target | `Set the draft recipient to Acme Labs.` | | Set the amount | `Set the Conto Pay amount to 250 dollars.` | | Add a purpose | `Use "April data labeling invoice" as the payment purpose.` | | Authorize the request | `Authorize this Conto Pay payment.` | | Inspect payment state | `Inspect my latest Conto Pay payment and tell me whether it is ready, waiting, or needs retry.` | | Review the activity inbox | `Show my Conto Pay activity inbox and the next actions I should take.` | | Open the latest receipt | `Give me the latest Conto Pay receipt or status link.` | | Review approvals | `List pending Conto Pay approvals.` | | Approve a payment | `Approve the latest Conto Pay payment.` | | Deny a payment | `Deny that payment and explain why.` | | Cancel a request | `Cancel that Conto Pay payment.` | | Retry a failed request | `Retry the latest Conto Pay payment.` | | Send after approval | `Send the approved Conto Pay payment now.` | ## Payment Lifecycle ```mermaid sequenceDiagram participant User participant Assistant participant Pay as "Conto Pay" participant Policies participant Chain User->>Assistant: Check wallet readiness Assistant->>Pay: Refresh wallet state / request sandbox funds User->>Assistant: Add recipient, amount, and purpose Assistant->>Pay: Update hosted draft User->>Assistant: Authorize payment Assistant->>Policies: Evaluate wallet and agent policies alt Approved immediately Policies->>Pay: Approved User->>Assistant: Inspect payment state User->>Assistant: Send payment Pay->>Chain: Execute transaction Chain->>Pay: Confirmed else Requires approval Policies->>Pay: Pending approval User->>Assistant: Approve or deny request Pay->>Chain: Execute only after approval else Execution failed Pay->>Assistant: Return diagnosis and next actions User->>Assistant: Retry or cancel request else Denied Policies->>Assistant: Return denial reason end ``` ## Paying Another Conto Pay Workspace To pay another organization already using Conto Pay, the assistant first resolves that hosted workspace and stores it as a verified network recipient in your normal allowlist. The target can be identified by: - a handle like `@vendor-org` or `@vendor-org/accounts-payable` - the account display name or public search aliases such as "Vendor AP" - organization slug or organization name - agent ID, agent slug, or agent name - hosted wallet address Directory matches include the hosted profile, Profile API, `paymentMode`, `agentReadiness`, `liveReview.rolloutPolicy`, and safe Pay/Request URL templates, so an agent can verify the JSON profile contract, rollout status, and action safety before saving, paying, or requesting from the payee. After the recipient is added, the payment lifecycle is the same as any other Conto Pay payment: draft the payment, authorize it against policies, wait for approval if needed, then send it from the hosted workspace. If the payer is using a saved contact and the saved trust snapshot no longer matches the current Profile API fingerprint, wallet, chain, currency, organization, or agent identity, Conto Pay blocks saved-contact payment preparation. The assistant should surface the trust warning, fetch or show the current Profile API details, and ask the operator to run `review_conto_pay_contact_trust` only after they accept the current public profile. ## Sharing Your Hosted Profile The assistant can also help operators start from the hosted Conto Pay identity rather than a raw wallet address. - ask for the current handle and hosted profile URL when you want another team to pay or find you - add public search aliases to the pay profile when counterparties know the account by team name, invoice desk, or internal vendor nickname - ask for Conto Pay contacts when you want saved payees or recent request counterparties before a broader directory search - rename saved contacts with personal aliases while keeping the verified Conto Pay handle visible - favorite saved contacts so repeat agent payees appear first in contact lists - review saved contact trust when the Profile API fingerprint, wallet, chain, or public name changes - set saved contact payment defaults for common amounts or purposes, then pay with those defaults - set saved contact limits for max per-payment amount, daily cap, approval requirement, or request permission - ask for contacts with trust warnings when a saved payee's public profile or hosted wallet may have changed - accept the current profile with `review_conto_pay_contact_trust` only after the user has reviewed the warning details - save a recent contact when you want future payments to use the verified network-recipient flow - use directory search when you know the organization or agent name but not the handle - use directory search when you know a public account alias but not the exact handle - start a payment or payment request from a directory result without opening the profile first - copy a hosted profile link from your profile card, contact row, or directory result - copy the Profile API link when another agent needs a JSON identity card for the same handle - use the hosted profile's payment-mode and readiness badges when a human operator is reviewing the payee in a browser - copy the Agent handoff packet when another operator or agent needs the handle, profile URL, Profile API URL, pay/request templates, activation state, public live-review state, `livePaymentsEnabled`, settlement details, compact `agentReadiness`, discovery aliases, instructions, and suggested prompts in one public-safe JSON object - use `get_conto_pay_profile` for ordinary setup/profile questions when the agent also needs compact `rolloutReadiness` and sanitized `publicRolloutEvidence` preview fields - fetch launch evidence when an operator or agent needs live-review prep plus public `paymentMode` and `agentReadiness.actions` in the same customer-safe packet - use the handoff packet `liveReview.status`, `liveReview.nextAction`, and Profile API URL to explain whether Conto live review is not requested, requested, in review, or completed - use `publicRolloutEvidence.status`, `missingFields`, and `nextAction` from launch evidence when the operator asks which public rollout approvals or owners still need to be captured - use `liveReview.rolloutPolicy` from launch evidence or the Profile API when the user or another agent asks why live payments are still guided, paused, or waiting on Conto rollout approval - use the hosted Pay and Request actions when a team shares a profile page directly; those actions also expose copyable deep links with the amount, memo, and invoice fields included - prefill a hosted profile link with `mode`, `amount`, `purpose`, and `invoiceId` when you want the recipient to open a ready-to-review pay or request form - ask the assistant to create a shareable payment link, request link, checkout link, or prefilled profile link; it uses `create_conto_pay_profile_checkout_link` and does not authorize or send money - use checkout link status, expiry, open count, last-opened time, and cancellation state to explain whether a shared link is still safe to use - when consuming another profile as an agent, fetch the Profile API and use the `actions.pay` or `actions.request` metadata for field schemas, URL templates, and the safe assistant prompt - when consuming another profile as an agent, also read `profile.discovery.aliases`, `profile.discovery.queryExamples`, and `profile.discovery.agentInstruction` before showing the payee name or suggesting how another agent should search for it - before presenting a profile as live-money ready, check `profile.activation.livePaymentsEnabled`; use `profile.liveReview.status` only to explain where Conto live review stands - use `profile.agentReadiness.actions` when deciding whether to verify, Pay, Request, or present live payments; `paymentMode.canPresentLivePayments` remains the source of truth for live-money claims - cache Profile API reads with the response `ETag` or `profile.integrity.fingerprint`, then refetch and compare the fingerprint before saving a payee, paying, or presenting live-money readiness - when listing saved contacts, use the saved trust snapshot `profileFingerprint` to explain whether the contact still matches the last reviewed Profile API identity - when consuming a tracked checkout link as an agent, keep the `intent` query parameter in the Profile API call so the response includes public checkout intent context This keeps discovery and payment setup inside the same hosted model as the rest of Conto Pay. ## Managing Checkout Links Checkout links are durable Conto Pay records, not throwaway URLs. The assistant and console can use them to hand a pay or request flow to another operator or agent while keeping the actual money movement gated by Conto Pay authorization. The assistant can: - create a Pay link or Request link for the current hosted profile - include amount, memo, and request-only invoice ID - return both the hosted profile URL and direct `/conto-pay` handoff URL - explain that opening the link only stages or prepares work; it does not send funds - report whether a link is active, expired, used, or cancelled - show the open count and last-opened timestamp for recent links - cancel an active checkout link when the amount, memo, invoice, or payer handoff is stale Agents should resolve the Profile API for a tracked checkout link before acting on it. If the Profile API response includes a `checkoutIntent` object with `CANCELLED` or `EXPIRED` status, the agent should ask for a fresh link instead of preparing a draft from the stale handoff. ## Requesting Payment From Another Workspace Hosted payment requests let a payee ask another Conto Pay workspace for payment before the payer starts drafting anything manually. The assistant can: - create a hosted request against a handle, organization, agent, or hosted wallet - include amount, purpose, invoice ID, due date, or expiration when needed - list incoming and outgoing requests - prepare an incoming request into the current payer draft without sending money When a payer prepares a request, Conto saves the requester as a verified network recipient and stages the amount and purpose, but the payer still authorizes and approves the payment through the normal hosted controls. Saved-contact trust warnings still apply when an operator asks to pay from a familiar alias or saved default. If `prepare_conto_pay_contact_payment` returns a trust block, do not call the lower-level network payment prep tool until the operator reviews and trusts the current profile. ## Example Network Prompts ```text Resolve @vendor-org/accounts-payable and show me the target wallet and chain. Add that workspace as a Conto Pay network recipient. Set the draft recipient to Vendor Org Conto Pay. Set the Conto Pay amount to 250 dollars. Use "June settlement" as the payment purpose. Authorize this Conto Pay payment. Inspect my latest Conto Pay payment and tell me whether it is ready, waiting, or needs retry. Send the approved Conto Pay payment now. ``` ## Recommended Operator Flow 1. Start by asking for the current workspace and draft. 2. Confirm the hosted wallet is ready before you authorize a payment. 3. In sandbox, request Tempo testnet funds if the wallet is present but underfunded. 4. Add or confirm the recipient before setting the amount. For cross-org hosted payments, resolve the target workspace and add it as a network recipient first. 5. Resolve any saved-contact trust warning before staging a repeat payment from defaults. 6. Set a clear payment purpose so approval reviewers have context. 7. Authorize the payment before asking to send it. 8. If a request moves to review, approve or deny it from the same assistant thread. 9. If execution fails, inspect the payment state first, then retry or cancel deliberately. ## Using The Activity Inbox The assistant can inspect the same unified activity inbox shown in the hosted workspace. - contacts show saved and recent agent accounts with aliases, favorite status, handles, profile links, trust status, profile-change warnings, payment defaults, payee limits, and suggested Pay/Request/Save/Rename/Favorite/Defaults/Limits prompts - direct payments and hosted requests appear in one timeline - items can be filtered by kind, direction, status, or next action - the assistant can return the primary hosted URL for a request or receipt - operators can copy the same full hosted URL from the activity inbox, request page, or receipt page - the next step stays explicit, such as `view_receipt`, `check_status`, `prepare_payment`, or `review_request` This is useful when operators are juggling both payables and receivables in the same Conto Pay thread. ## What The Assistant Can Manage The Conto Pay assistant is not limited to drafting a payment. It can also manage the hosted control surface around that payment: - wallet readiness and balance refresh - Tempo sandbox funding for the hosted wallet - recipient allowlist management - Conto Pay network-recipient resolution and verification - Conto Pay contact lookup, aliases, favorite pins, and payment defaults for saved and recent agent accounts - contact trust warnings based on saved Profile API fingerprints, with payment prep blocked until the current profile is reviewed - hosted profile naming, directory listing controls, shareable identity links, and public Profile API lookup - checkout link creation, open tracking, status inspection, and cancellation - hosted payment-request creation and review - approval threshold visibility and updates - wallet spend-limit visibility and updates - payment inspection for ready, waiting, failed, cancelled, or blocked requests - activity inbox review across payments and requests - hosted receipt and status links for the current request - retry and cancellation workflows when a request does not complete cleanly This is useful because the same conversation can move from setup, to review, to execution, to recovery without forcing the operator into a different tool. ## Reading Payment State When you ask the assistant to inspect a payment, Conto Pay summarizes the current request and the next operator action: - `ready` means the request is approved and can be sent - `waiting` usually means approval is still pending - `needs retry` means execution failed or the request needs another operator action - `cancelled` means the request was stopped before execution - `blocked` means the request cannot move forward in its current state If a request failed, Conto Pay points you back to the likely next step: refresh the wallet, confirm policy and balance readiness, then retry only if the request is still valid. ## Sandbox And Live Money The default Conto Pay workspace is sandbox-first, but the operating model stays the same: - the assistant remains the primary interface - the hosted wallet still has to be ready before payments can move - the same Conto policies are evaluated - the same approval workflow is used - Conto Pay network recipients still go through the same hosted controls - the same hosted agent state tracks the draft and the request lifecycle What changes between sandbox and live is the funding and execution environment, not the way users operate the hosted agent. Live use is enabled through Conto's guided rollout after workspace readiness, controls, support ownership, launch scope, trust-report ownership, and deployment evidence are reviewed and recorded. ## Related Docs ### Conto Pay Overview Link: https://conto.finance/docs/conto-pay/overview Learn what Conto Pay provisions and how it differs from self setup ### Live Rollout Link: https://conto.finance/docs/conto-pay/live-rollout Learn how launch evidence, live review, and rollout gates affect assistant behavior ### Approval Workflows Link: https://conto.finance/docs/guides/approval-workflows Understand the review path for requests that need a decision --- # Live Rollout Conto Pay is sandbox-first. A hosted workspace can discover payees, create checkout links, run closed-loop sandbox payments, and request payment from another organization before live money is enabled. Live money is enabled through a guided rollout. Conto reviews the workspace, launch evidence, support ownership, funding scope, trust-review ownership, and customer-facing claims before the workspace is marked live-enabled. Info: Agents and operators should treat `livePaymentsEnabled` as the source of truth for live-money claims. If it is `false`, keep the user in setup, sandbox testing, launch evidence, or live-review guidance. ## The Launch Path The Conto Pay Activation card and launch evidence packet use the same launch path: | Phase | What it means | Safe next action | | ------------- | --------------------------------------------------------------------------- | ----------------------------------------------------- | | Hosted setup | The workspace, profile, wallet, controls, or handoff links still need setup | Finish setup in the Conto Pay console | | Sandbox proof | Setup is usable, but sandbox payment evidence is incomplete | Run payer-initiated and payee-initiated sandbox flows | | Live review | Sandbox evidence is ready or review has been requested | Request live review or wait for Conto support | | Live-enabled | Conto has approved the workspace and live payments are enabled | Use live-money flows inside normal Conto controls | Operators can copy launch evidence from the Activation card. Authenticated agents can fetch the same customer-safe packet from: ```http GET /api/conto-pay/launch-evidence ``` The response returns `{ launchEvidence }`. It intentionally omits SDK key prefixes and support-only review metadata. ## What Launch Evidence Includes Launch evidence is safe to paste into a support thread or hand to another authenticated agent. It includes: - hosted profile handle, profile URL, and Profile API URL - account display name, public discovery aliases, and handoff query examples - setup, wallet, profile, approval, and handoff readiness - closed-loop payment and hosted request evidence status - live-review status and next action - sanitized public-rollout evidence completeness, missing labels, and next action - public `paymentMode` and compact `agentReadiness.actions` - customer-safe rollout-policy messaging - non-secret support packet details for Conto review, including sanitized public-rollout evidence Agents should use the packet to explain what the user can do next. They should not infer live-money capability from a profile being discoverable, a checkout link being active, or a live-review request existing. ## Requesting Live Review When hosted setup and sandbox proof are ready, operators can click **Request live review** from the Activation card. The request creates or reuses one Conto support review item for the workspace. Conto support can also create a launch-review record from the internal launch dashboard when a cohort is being prepared and the customer has not clicked the Activation card yet. That support created review gives launch evidence an audit-backed home, but it does not enable live payments by itself. A live-review request is not live approval. The workspace remains sandbox or guided-live until Conto approves the review and the Profile API reports `livePaymentsEnabled: true`. ## Public Rollout Evidence Before Conto Pay moves beyond a controlled cohort, Conto records launch-ops evidence for each workspace. The required public-rollout evidence fields are: | Evidence field | What Conto records | | ------------------------- | ------------------------------------------------------------------------------ | | Support owner | The named owner for customer questions, live review, and incidents | | Production funding limit | The approved live-funds scope and replenishment owner | | Funnel review cadence | How often launch funnel alerts are reviewed during rollout | | Trust-report owner | The owner for profile reports, impersonation concerns, and directory decisions | | Deployment evidence | Release, commit, pull request, or deployment evidence for the customer session | | Legal/compliance evidence | Counsel-approved legal or compliance evidence for external use | | Public rollout decision | The launch owner's public rollout decision and scope | | Claims review evidence | Review evidence for docs, marketing, onboarding, and sales claims | These fields are visible to Conto support in launch-readiness exports and signoff packets. They are not required for a supervised sandbox run, but they are required before broad live-money rollout. The same readiness response includes a `publicRolloutDecision` summary with the recommended decision, release scope, public-invite flag, live-rollout flag, reasons, and next action for the selected cohort. ## Rollout Gate Modes Conto uses a rollout gate before support can enable live mode: | Mode | Meaning | | --------- | --------------------------------------------------------------- | | Closed | Live approvals are paused | | Allowlist | Only configured organizations can be approved for live mode | | Open | Public live rollout is approved, subject to launch-ops evidence | An allowlist that permits all reviewed organizations is treated like a public rollout switch. Support still records the public-rollout evidence fields before enabling live mode. ## Agent Guidance Agents consuming Conto Pay profiles should follow this order: Fetch the public Profile API URL for the handle or checkout link. Keep any `intent` query parameter when reading a tracked checkout link. Use `profile.discovery.aliases`, `profile.discovery.queryExamples`, and `profile.discovery.agentInstruction` to decide how to display, search, or hand off the payee identity. Use the Profile API `profile.integrity.fingerprint`, response `ETag`, and any saved contact trust snapshot before preparing a repeat payment. If a saved contact has trust warnings, ask the operator to review the current profile before staging the payment. Use `profile.paymentMode.canPresentLivePayments` and `profile.activation.livePaymentsEnabled` before describing the payee as live-money capable. Use `profile.liveReview.status` and launch evidence `liveReview.rolloutPolicy` only to explain where Conto review stands. If live payments are not enabled, help the operator finish setup, run sandbox proof, request live review, or wait for Conto support. ## Operator Checklist Before asking Conto to approve live mode: - confirm hosted setup is complete - verify the hosted wallet is ready - name the public Conto Pay account and add any search aliases counterparties will use - run a payer-initiated sandbox payment to another Conto Pay workspace - run a payee-initiated hosted request loop - confirm no active warning or critical funnel alerts block the launch - review any open trust reports - copy the launch evidence packet - request live review from the Activation card For public rollout, Conto support also records the launch-ops evidence fields listed above and exports a signoff packet for launch, support, trust, and legal owners. ## Related Docs ### Conto Pay Overview Link: https://conto.finance/docs/conto-pay/overview Learn what Conto Pay provisions and how profiles, requests, and receipts work ### Using the Assistant Link: https://conto.finance/docs/conto-pay/assistant-workflow See the prompts and tool behavior for hosted Conto Pay operations ### Approval Workflows Link: https://conto.finance/docs/guides/approval-workflows Understand how payment approvals are reviewed and resolved ### Notification Channels Link: https://conto.finance/docs/integrations/notification-channels Subscribe to Conto Pay lifecycle webhooks for request events --- # Policy System The policy system is the core of Conto's spending controls. Policies define rules that govern how AI agents can spend funds. ## What is a Policy? A policy is a set of rules that determine whether a payment should be: - **APPROVED** - Payment can proceed - **DENIED** - Payment is blocked - **REQUIRES_APPROVAL** - Manual approval needed ## Policy Types ### Spend Limit Link: https://conto.finance/docs/policies/spend-limits Control maximum amounts per transaction, day, week, or month ### Time Window Link: https://conto.finance/docs/policies/time-windows Restrict transactions to specific hours and days ### Counterparty Link: https://conto.finance/docs/policies/counterparties Control which recipients are allowed based on trust ### Geographic Link: https://conto.finance/docs/policies/advanced#geographic-restrictions-ofac OFAC sanctions screening and country restrictions, built-in and configurable ### AgentScore Compliance Link: https://conto.finance/docs/policies/advanced#agentscore-commerce-rules Require verified humans, enforce jurisdiction allowlists, and trigger identity step-up before settlement ### Category Allow or block specific spending categories ### Contract Allowlist Link: https://conto.finance/docs/policies/advanced#contract-allowlist Restrict interactions to approved smart contracts and protocols via Contract Registry ### Approval Threshold Require manual approval above certain amounts ### Velocity Limit transaction frequency to prevent rapid drain ### Whitelist Only allow specific pre-approved addresses ### x402 Controls Link: https://conto.finance/docs/policies/advanced#x402-protocol-rules Price ceilings, service allowlists, and session budget caps for x402 micropayments ### MPP Controls Link: https://conto.finance/docs/policies/advanced#mpp-protocol-rules Session budgets, concurrency limits, and duration caps for MPP payments ### Budget Allocation Link: https://conto.finance/docs/policies/advanced#budget-allocations Allocate budgets by department or project with period tracking ### Expiration Link: https://conto.finance/docs/policies/advanced#expiration-policies Time-limited permissions with start and end dates ### Card Payment Link: https://conto.finance/docs/policies/advanced#card-payment-rules MCC restrictions, merchant filtering, and amount limits for card payments ## Policy Evaluation Policies are evaluated fail-closed. When multiple policies are assigned, **all must pass**. The first DENY stops evaluation immediately. ### Evaluation Order 1. **Pre-checks**: Agent must be ACTIVE with linked wallets 2. **Geographic & Sanctions**: OFAC country check + address sanctions screening (always active, no policy needed) 3. **Counterparty Trust**: Pre-fetch trust level and network trust score for use in policy rules 4. **Wallet Policies**: Spend limits, wallet-level time windows (timezone-aware), and other configured policy rules 5. **Merchant Identity Gates**: Optional AgentScore assess results can add verified-human, KYC, sanctions, and jurisdiction context before final settlement 6. **Counterparty Rules**: Block list, trust requirements, network intelligence 7. **Relationship Limits**: Per-counterparty spend limits from `AgentRelationship` records 8. **Final Decision**: Aggregate results Protocol-specific budget rules only count matching protocol transactions. x402 session budgets use the x402 `sessionId` recorded with each payment, and MPP session budgets use the MPP `sessionId`, so ordinary wallet transfers do not reduce protocol session allowance. Info: The default local sanctions provider now reads from Conto's `SanctionedAddress` table instead of a hardcoded demo list. That table is seeded by migration with known high-confidence OFAC matches and refreshed by the `sanctions-list-refresh` background job, so sanctions screening starts with a safe baseline even before the first feed sync completes. | Outcome | Condition | | --------------------- | ---------------------------------- | | **DENIED** | Any check denies | | **REQUIRES_APPROVAL** | No denial, and at least one rule or workflow requires approval | | **APPROVED** | All checks pass | ### Evaluation Semantics Policy rules use simple AND logic. Every active policy assigned to the selected agent or wallet is evaluated, and every rule inside those policies must pass unless it is a `DENY` or `REQUIRE_APPROVAL` trigger that does not match. | Action | Meaning | | ------ | ------- | | `ALLOW` | The condition describes what is permitted. If the condition does not match, the payment is denied. | | `DENY` | The condition describes what is blocked. If the condition matches, the payment is denied. | | `REQUIRE_APPROVAL` | The condition describes what needs review. If it matches and no DENY fires, the payment requires approval. | `priority` is sort order, not override precedence. A higher-priority `ALLOW` cannot override a lower-priority deny or a failed allowlist. Use one wider allowlist rule when you need alternatives, not two competing policies. For a hands-on walkthrough of how evaluation works, see the [Policy Testing guide](https://conto.finance/docs/guides/policy-testing). ## Creating Policies ### Via Dashboard Go to **Policies** in the sidebar and click **New Policy**. | Field | Description | |-------|-------------| | Name | Human-readable name | | Type | Policy type (spend limit, time window, etc.) | | Priority | 0-100 (higher = evaluated first, but never overrides a failing rule) | | Description | What this policy does | Define the specific rules for this policy. Select which agents this policy applies to. ### Via API ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Daily Spend Limit", "description": "Limits daily spending to $1000", "policyType": "SPEND_LIMIT", "priority": 50, "isActive": true }' ``` ## Policy Properties | Property | Type | Description | | ------------- | ------- | ------------------------------ | | `name` | string | Human-readable name | | `description` | string | Detailed description | | `policyType` | enum | Type of policy | | `priority` | number | Evaluation order (0-100), not override precedence | | `isActive` | boolean | Whether policy is enforced | | `rules` | array | Specific rules for this policy | ## Assigning Policies Policies can be assigned to: - **Agents** - Apply to specific agents - **Wallets** - Apply to specific wallets - **Cards** - Apply to specific payment cards ### Assign to Card ```bash curl -X POST https://conto.finance/api/cards/{cardId}/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -d '{ "policyId": "cmm5c0pol000l49h7dmsuc11p" }' ``` ### Assign to Agent ```bash curl -X POST https://conto.finance/api/agents/{agentId}/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -d '{ "policyId": "cmm5c0pol000l49h7dmsuc11p" }' ``` ## Example: Standard Agent Setup A typical agent configuration with multiple policies: ```json [ { "name": "Spend Limits", "policyType": "SPEND_LIMIT", "priority": 50, "rules": [ { "ruleType": "MAX_AMOUNT", "operator": "LTE", "value": "200", "action": "ALLOW" }, { "ruleType": "DAILY_LIMIT", "operator": "LTE", "value": "1000", "action": "ALLOW" }, { "ruleType": "MONTHLY_LIMIT", "operator": "LTE", "value": "10000", "action": "ALLOW" } ] }, { "name": "Business Hours", "policyType": "TIME_WINDOW", "priority": 50, "rules": [ { "ruleType": "TIME_WINDOW", "operator": "BETWEEN", "value": "{\"start\": \"09:00\", \"end\": \"18:00\"}", "action": "ALLOW" }, { "ruleType": "DAY_OF_WEEK", "operator": "IN", "value": ["Mon", "Tue", "Wed", "Thu", "Fri"], "action": "ALLOW" } ] }, { "name": "Trusted Vendors Only", "policyType": "COUNTERPARTY", "priority": 50, "rules": [{ "ruleType": "TRUST_SCORE", "operator": "GTE", "value": "0.6", "action": "ALLOW" }] } ] ``` ## Best Practices Create policies at different priority levels to make evaluation and debugging easier: - **HIGH (90-100)**: Security/Compliance (sanctions, blocked addresses) - **MEDIUM (40-60)**: Business Rules (limits, time windows) - **LOW (0-20)**: Defaults (catch-all rules) Priority changes evaluation order only. It does not let an allow rule override a stricter rule that runs later. Begin with strict policies and relax based on operational needs. Recommended starting limits for new agents: $100/tx, $500/day, $5,000/month. - Day 1: $100/day limit, 3 trusted vendors - Week 2: $500/day, add 5 more vendors - Month 2: $1,000/day, category-based restrictions Note: Auto-created wallet defaults are higher (daily: $1,000, weekly: $5,000, monthly: $20,000). Override these with policy-level limits for tighter control. Don't block high-value transactions entirely - require approval: ```json { "policyType": "APPROVAL_THRESHOLD", "rules": [ { "ruleType": "REQUIRE_APPROVAL_ABOVE", "operator": "GREATER_THAN", "value": "500", "action": "REQUIRE_APPROVAL" } ] } ``` Use descriptions to explain policy intent: ```json { "name": "OFAC Compliance", "description": "Blocks transactions to OFAC-sanctioned countries. Required for regulatory compliance. Do not modify without legal approval." } ``` ## Available Rule Types The value formats, operators, and caveats for every rule type live in [Advanced Policies](https://conto.finance/docs/policies/advanced). Quick index: | Category | Rule Types | |----------|-----------| | [Spend limits](https://conto.finance/docs/policies/advanced#supported-rule-types) | `MAX_AMOUNT`, `DAILY_LIMIT`, `WEEKLY_LIMIT`, `MONTHLY_LIMIT`, `BUDGET_CAP` | | [Time controls](https://conto.finance/docs/policies/advanced#supported-rule-types) | `TIME_WINDOW`, `DAY_OF_WEEK`, `DATE_RANGE`, `BLACKOUT_PERIOD` (aliases: `MAINTENANCE_WINDOW`, `BLOCKED_TIME_WINDOW`) | | [Counterparty & address](https://conto.finance/docs/policies/advanced#supported-rule-types) | `ALLOWED_COUNTERPARTIES`, `BLOCKED_COUNTERPARTIES`, `TRUST_SCORE`, `COUNTERPARTY_STATUS` | | [Category & contract](https://conto.finance/docs/policies/advanced#contract-allowlist) | `ALLOWED_CATEGORIES`, `BLOCKED_CATEGORIES`, `CONTRACT_ALLOWLIST` (aliases: `ALLOWED_CONTRACTS`, `PROTOCOL_ALLOWLIST`) | | [Geographic & compliance](https://conto.finance/docs/policies/advanced#geographic-restrictions-ofac) | `GEOGRAPHIC_RESTRICTION`, `VELOCITY_LIMIT`, `REQUIRE_APPROVAL_ABOVE`, `FAIRSCALE_MIN_SCORE` | | [Card payment](https://conto.finance/docs/policies/advanced#card-payment-rules) | `CARD_MAX_AMOUNT`, `CARD_ALLOWED_MCCS`, `CARD_BLOCKED_MCCS`, `CARD_ALLOWED_MERCHANTS`, `CARD_BLOCKED_MERCHANTS` | | [x402 protocol](https://conto.finance/docs/policies/advanced#x402-protocol-rules) | `X402_MAX_PER_REQUEST`, `X402_PRICE_CEILING`, `X402_MAX_PER_ENDPOINT`, `X402_MAX_PER_SERVICE`, `X402_ALLOWED_SERVICES`, `X402_BLOCKED_SERVICES`, `X402_ALLOWED_FACILITATORS`, `X402_VELOCITY_PER_ENDPOINT`, `X402_SESSION_BUDGET` | | [MPP protocol](https://conto.finance/docs/policies/advanced#mpp-protocol-rules) | `MPP_MAX_PER_REQUEST`, `MPP_PRICE_CEILING`, `MPP_MAX_PER_ENDPOINT`, `MPP_MAX_PER_SERVICE`, `MPP_ALLOWED_SERVICES`, `MPP_BLOCKED_SERVICES`, `MPP_VELOCITY_PER_ENDPOINT`, `MPP_SESSION_BUDGET`, `MPP_MAX_SESSION_DEPOSIT`, `MPP_MAX_CONCURRENT_SESSIONS`, `MPP_MAX_SESSION_DURATION`, `MPP_BLOCK_SESSION_INTENT` | | [AgentScore commerce](https://conto.finance/docs/policies/advanced#agentscore-commerce-rules) | `AGENTSCORE_REQUIRE_VERIFIED`, `AGENTSCORE_ALLOWED_JURISDICTIONS`, `AGENTSCORE_BLOCKED_JURISDICTIONS` | ## Violation Details When a payment is denied, detailed violation info is returned: ```json { "status": "DENIED", "reasons": ["Would exceed daily limit"], "violations": [ { "type": "DAILY_LIMIT", "limit": 1000, "current": 1150, "message": "[Wallet limit] Would exceed daily limit: $-150.00 remaining of $1000 daily limit", "source": "wallet_limit" }, { "type": "PER_TX_LIMIT", "limit": 200, "current": 300, "message": "[Policy: High-Value Guard] Amount 300 exceeds per-transaction limit of 200", "source": "policy_rule", "policyName": "High-Value Guard" } ] } ``` Each violation includes a `source` field indicating whether the denial came from a **wallet-level limit** (`"wallet_limit"`) or a **policy rule** (`"policy_rule"`). Policy rule violations also include `policyName`. ## Engine Architecture Each rule type is evaluated by a dedicated strategy module. The engine looks up the strategy for a rule's `ruleType` from a registry and delegates evaluation. New rule types can be added without modifying the core engine, register a new strategy and update the SKILL.md docs. ## Next Steps ### Spend Limits Link: https://conto.finance/docs/policies/spend-limits Configure amount-based limits ### Time Windows Link: https://conto.finance/docs/policies/time-windows Set up time-based restrictions --- # Spend Limit Policies Spend limit policies control the maximum amount that can be spent per transaction, day, week, or month. ## Configuration Create a SPEND_LIMIT policy and add rules via the API: ```bash # Create policy curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "Spend Limits", "policyType": "SPEND_LIMIT", "priority": 50, "isActive": true}' # Add rules curl -X POST https://conto.finance/api/policies/{policyId}/rules \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "rules": [ {"ruleType": "MAX_AMOUNT", "operator": "LTE", "value": "500", "action": "ALLOW"}, {"ruleType": "DAILY_LIMIT", "operator": "LTE", "value": "2000", "action": "ALLOW"}, {"ruleType": "WEEKLY_LIMIT", "operator": "LTE", "value": "10000", "action": "ALLOW"}, {"ruleType": "MONTHLY_LIMIT", "operator": "LTE", "value": "30000", "action": "ALLOW"} ] }' ``` ## Rule Types | Rule Type | Description | Operator | Value | |-----------|-------------|----------|-------| | `MAX_AMOUNT` | Maximum per single transaction | `LTE` | Amount (number) | | `DAILY_LIMIT` | Maximum total spend per day | `LTE` | Amount (number) | | `WEEKLY_LIMIT` | Maximum total spend per week | `LTE` | Amount (number) | | `MONTHLY_LIMIT` | Maximum total spend per month | `LTE` | Amount (number) | | `BUDGET_CAP` | Budget with period | `LTE` | `{"amount": N, "period": "MONTHLY"}` | ## How It Works 1. **Per-Transaction**: Checked against the requested amount 2. **Daily/Weekly/Monthly**: Checked against cumulative spend + requested amount Info: Conto uses fixed-precision monetary values for spend limits, balances, and transaction amounts to avoid floating-point rounding issues in financial calculations. ### Example Evaluation ``` Agent: Operations Agent Daily Limit: $1,000 Spent Today: $750 Request: $300 payment Evaluation: - Per-tx check: $300 < limit (pass) - Daily check: $750 + $300 = $1,050 > $1,000 (FAIL) Result: DENIED Reason: "Would exceed daily limit: $250 remaining" ``` ## Wallet-Level Limits In addition to policies, limits can be set on the agent-wallet link: ```json { "agentId": "cmm59z8fj000l49h7bjqza11p", "walletId": "cmm5b2wal002n49h7ckrtb33r", "spendLimitPerTx": 100, "spendLimitDaily": 1000, "spendLimitWeekly": 5000, "spendLimitMonthly": 15000 } ``` These are evaluated **first**, before policy rules. Info: **Auto-creation defaults:** When an external wallet is auto-created, the system applies these defaults: daily = $1,000, weekly = $5,000, monthly = $20,000, no per-transaction limit. You can override these when linking a wallet to an agent. Wallet-level limits treat `null`, omitted fields, and `0` as unlimited; use a deny policy or suspend the agent when you need to block spend. ## Tracking Spend The system tracks spending automatically: - **spentToday** - Resets at midnight UTC - **spentThisWeek** - Resets Monday midnight UTC - **spentThisMonth** - Resets 1st of month midnight UTC ## Best Practices Begin with a low per-transaction cap and increase based on operational needs: ```json { "ruleType": "MAX_AMOUNT", "operator": "LTE", "value": "50", "action": "ALLOW" } ``` Use multiple limit types for defense in depth: - Per-tx: Prevents single large payments - Daily: Limits daily exposure - Monthly: Controls overall budget Create different policies for different agent risk levels: - Low-risk agents: Higher limits - New agents: Lower limits until proven - Critical agents: Strict limits + approval --- # Time Window Policies Time window policies restrict when transactions can occur based on hours and days. Policy-rule time windows use the server's local time. Wallet-level time windows are evaluated in the agent-wallet link's configurable IANA `timezone`, which defaults to `UTC`. ## Configuration (API) Create rules via the Policy Rules API: ```bash curl -X POST https://conto.finance/api/policies/{policyId}/rules \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "rules": [ { "ruleType": "TIME_WINDOW", "operator": "BETWEEN", "value": "{\"start\": \"09:00\", \"end\": \"17:00\"}", "action": "ALLOW" }, { "ruleType": "DAY_OF_WEEK", "operator": "IN_LIST", "value": "[\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\"]", "action": "ALLOW" } ] }' ``` ## Rule Types ### TIME_WINDOW (Hours) Restrict transactions to specific hours of the day: | Property | Description | |----------|-------------| | `ruleType` | `TIME_WINDOW` | | `operator` | `BETWEEN` (allow within window) or `NOT_BETWEEN` (block within window) | | `value` | JSON string: `{"start": "HH:MM", "end": "HH:MM"}` | | `action` | `ALLOW` or `DENY` | ### DAY_OF_WEEK (Days) Restrict transactions to specific days of the week: | Property | Description | |----------|-------------| | `ruleType` | `DAY_OF_WEEK` | | `operator` | `IN_LIST` (allow these days) or `NOT_IN_LIST` (block these days) | | `value` | JSON string containing an array: `["Mon", "Tue", "Wed", "Thu", "Fri"]` | | `action` | `ALLOW` or `DENY` | Valid day values: `Mon`, `Tue`, `Wed`, `Thu`, `Fri`, `Sat`, `Sun` ### BLACKOUT_PERIOD Block transactions during maintenance windows or holidays: ```bash curl -X POST https://conto.finance/api/policies/{policyId}/rules \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "rules": [{ "ruleType": "BLACKOUT_PERIOD", "operator": "BETWEEN", "value": "{\"windows\": [{\"start\": \"02:00\", \"end\": \"06:00\", \"reason\": \"Maintenance\", \"recurring\": true}]}", "action": "DENY" }] }' ``` ## Wallet-Level Time Windows Time windows can also be set on the agent-wallet link (`POST /api/agents/{id}/wallets` or `PATCH /api/agents/{id}/wallets/{walletId}`): ```json { "walletId": "cmm5b2wal002n49h7ckrtb33r", "allowedHoursStart": 9, "allowedHoursEnd": 17, "allowedDays": ["Mon", "Tue", "Wed", "Thu", "Fri"], "timezone": "America/New_York" } ``` Info: `allowedHoursStart`/`allowedHoursEnd` and `allowedDays` are evaluated in the link's IANA `timezone`, which defaults to `UTC`. The `timezone` field can be set when linking the wallet (`POST /api/agents/{id}/wallets`) and changed later on the update endpoint (`PATCH /api/agents/{id}/wallets/{walletId}`); invalid IANA names are rejected with a 400. ## Use Cases ### Business Hours Only allow transactions during working hours ```json { "allowedHoursStart": 9, "allowedHoursEnd": 18, "allowedDays": ["Mon", "Tue", "Wed", "Thu", "Fri"] } ``` ### Extended Hours Allow transactions in extended support hours ```json { "allowedHoursStart": 7, "allowedHoursEnd": 22, "allowedDays": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] } ``` ### Weekends Only For agents that operate on weekends ```json { "allowedHoursStart": 0, "allowedHoursEnd": 24, "allowedDays": ["Sat", "Sun"] } ``` ### 24/7 No time restrictions (allow always) ```json { "allowedHoursStart": 0, "allowedHoursEnd": 24, "allowedDays": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] } ``` ## Error Response When a transaction is blocked by time window: ```json { "status": "DENIED", "reasons": ["Transaction outside allowed hours"], "violations": [ { "type": "TIME_WINDOW", "limit": 0, "current": 0, "message": "Transactions not allowed at 22:00 (America/New_York). Allowed hours: 9:00 - 17:00", "source": "wallet_limit" } ] } ``` ## Best Practices Set the link's `timezone` to your organization's operating timezone (for example, `America/New_York`) instead of converting hours to UTC by hand. With the timezone set, `allowedHoursStart`/`allowedHoursEnd` read as local business hours, daylight saving time is handled for you, and `allowedDays` matches the local calendar day. If you leave it unset, the link defaults to `UTC`. Time window violations include the evaluated timezone in the error message. Align time windows with when humans are available to monitor: - During work hours: Standard limits - After hours: Stricter limits or blocked Allow small transactions any time, but require approval after hours by assigning two policies to the agent. Conto evaluates them with AND logic. ```json [ { "name": "Business hours", "policyType": "TIME_WINDOW", "priority": 50, "rules": [ { "ruleType": "TIME_WINDOW", "operator": "BETWEEN", "value": "{\"start\": \"09:00\", \"end\": \"17:00\"}", "action": "ALLOW" } ] }, { "name": "After-hours approval", "policyType": "APPROVAL_THRESHOLD", "priority": 40, "rules": [ { "ruleType": "REQUIRE_APPROVAL_ABOVE", "operator": "GREATER_THAN", "value": "50", "action": "REQUIRE_APPROVAL" } ] } ] ``` --- # Counterparty Policies Counterparty policies control which recipients agents can pay based on trust levels, verification status, and relationships. ## Configuration (API) Create counterparty rules via the Policy Rules API: ```bash curl -X POST https://conto.finance/api/policies/{policyId}/rules \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "rules": [ { "ruleType": "ALLOWED_COUNTERPARTIES", "operator": "IN_LIST", "value": "[\"0x1234567890abcdef1234567890abcdef12345678\", \"0xabcdef1234567890abcdef1234567890abcdef12\"]", "action": "ALLOW" }, { "ruleType": "TRUST_SCORE", "operator": "GTE", "value": "0.7", "action": "ALLOW" } ] }' ``` ## Rule Types ### ALLOWED_COUNTERPARTIES Only allow payments to specific wallet addresses (allowlist): ```json { "ruleType": "ALLOWED_COUNTERPARTIES", "operator": "IN_LIST", "value": "[\"0x1234...\", \"0x5678...\"]", "action": "ALLOW" } ``` Address matching is **case-insensitive**. ### BLOCKED_COUNTERPARTIES Block payments to specific addresses: ```json { "ruleType": "BLOCKED_COUNTERPARTIES", "operator": "IN_LIST", "value": "[\"0xdead...\"]", "action": "DENY" } ``` ### TRUST_SCORE Only allow payments to counterparties above a trust threshold: ```json { "ruleType": "TRUST_SCORE", "operator": "GTE", "value": "0.7", "action": "ALLOW" } ``` Trust scores are calculated automatically based on: - Transaction history (30%) - Reliability/success rate (30%) - Account activity (20%) - Verification status (20%), includes [external providers](https://conto.finance/docs/integrations/trust-providers) like Fairscale (Solana) and sanctions screening Info: The trust score and trust level are automatically fetched during policy evaluation and passed into the rule engine. You don't need to provide them in the payment request, just create the rules and the evaluator populates the context from the counterparty relationship and network trust service. ### COUNTERPARTY_STATUS Require a specific trust level: ```json { "ruleType": "COUNTERPARTY_STATUS", "operator": "EQUALS", "value": "{\"status\": \"TRUSTED\"}", "action": "ALLOW" } ``` ## Trust Levels | Level | Score Range | Description | |-------|-------------|-------------| | `TRUSTED` | 0.75-1.00 | High confidence, minimal restrictions | | `VERIFIED` | 0.50-0.74 | Established relationship | | `UNKNOWN` | 0.20-0.49 | Limited history | | `BLOCKED` | 0.00-0.19 | Blocked from transactions | ## Whitelist Policy For maximum control, use `ALLOWED_COUNTERPARTIES` with `ALLOW` action to only allow specific addresses. Any recipient not in the list will be denied: ```json { "ruleType": "ALLOWED_COUNTERPARTIES", "operator": "IN_LIST", "value": "[\"0x1234567890abcdef1234567890abcdef12345678\", \"0xabcdef1234567890abcdef1234567890abcdef12\"]", "action": "ALLOW" } ``` ## Relationship Spend Limits In addition to policy rules, you can set per-counterparty spend limits on the `AgentRelationship` record. These are enforced automatically during payment evaluation: | Field | Description | |-------|-------------| | `spendLimitPerTx` | Maximum amount per transaction to this counterparty | | `spendLimitDaily` | Maximum total spend per day to this counterparty | | `spendLimitMonthly` | Maximum total spend per month to this counterparty | These limits are checked after the trust/block check and before the final approval decision. If a counterparty has a $500/day limit, the evaluator aggregates all confirmed/pending transactions to that address today and blocks if the new payment would exceed it. ```bash # Set per-counterparty limits when creating a relationship curl -X POST https://conto.finance/api/relationships \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "agentId": "cmm59z8fj000l49h7bjqza11p", "counterpartyId": "cmm5f0cpt000l49h7gpvxf11p", "spendLimitPerTx": 200, "spendLimitDaily": 500, "spendLimitMonthly": 5000 }' ``` ## Managing Counterparties ### Add Counterparty ```bash curl -X POST https://conto.finance/api/counterparties \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "name": "Amazon Web Services", "type": "VENDOR", "address": "0x1234...", "domain": "aws.amazon.com", "category": "INFRASTRUCTURE", "trustLevel": "TRUSTED" }' ``` ### Block Counterparty ```bash curl -X POST https://conto.finance/api/counterparties/{id}/status \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "status": "BLOCKED", "reason": "Suspicious activity detected" }' ``` ## Network Intelligence & External Providers Conto's Network Intelligence provides cross-organization trust signals: - See if other organizations have flagged an address - Benefit from collective fraud detection - Automatic trust score adjustments For Solana wallets, Conto also integrates with [Fairscale](https://fairscale.xyz) for onchain reputation scoring. Wallets with no existing network data are automatically enriched with Fairscale scores, and behavioral red flags generate network alerts. See [Trust & Risk Providers](https://conto.finance/docs/integrations/trust-providers) for configuration and all available providers. Note: Network data is anonymized. Organizations share aggregate signals, not transaction details. ## Best Practices Begin with a small list of trusted vendors: ```json { "policyType": "WHITELIST", "rules": [{ "addresses": ["0xaws...", "0xopenai...", "0xgcp..."] }] } ``` As you verify new vendors, increase their trust level: 1. New vendor: UNKNOWN (allowed within default spend limits, approval required on high network risk) 2. After review: VERIFIED 3. After history: TRUSTED Regularly review trust scores in the dashboard. Investigate any drops. --- # Advanced Policies Advanced policy types and the rule engine for complex business requirements. ## Policy Rules Each policy consists of one or more **rules**. Rules define specific conditions and actions: ### Rule Structure ```json { "ruleType": "MAX_AMOUNT", "operator": "GREATER_THAN", "value": "500", "action": "REQUIRE_APPROVAL" } ``` | Field | Description | | ---------- | -------------------------------------- | | `ruleType` | Type of condition (see below) | | `operator` | Comparison operator | | `value` | JSON-encoded value for comparison. Store objects and arrays as JSON strings. | | `action` | `ALLOW`, `DENY`, or `REQUIRE_APPROVAL` | Info: `POST /api/policies` accepts inline `rules` and is the safest API path for advanced rule types today. The standalone `POST /api/policies/{policyId}/rules` route currently accepts the standard rule subset and rejects x402, MPP, card, AgentScore, and Fairscale rule types until its schema is widened. ### Supported Rule Types Each rule type below maps to a dedicated strategy module in the policy engine. The engine dispatches evaluation through a registry, so adding a new rule type means adding a new strategy file rather than modifying core engine code. | Rule Type | Description | Example Value | | ------------------------ | --------------------------------- | -------------------------------------------------------------------------------------------- | | `MAX_AMOUNT` | Per-transaction amount | `"500"` | | `DAILY_LIMIT` | Daily spend cap | `"1000"` | | `WEEKLY_LIMIT` | Weekly spend cap | `"5000"` | | `MONTHLY_LIMIT` | Monthly spend cap | `"20000"` | | `BUDGET_CAP` | Budget allocation | `"{\"amount\": 50000, \"period\": \"MONTHLY\"}"` | | `TIME_WINDOW` | Time window restriction | `"{\"start\": \"09:00\", \"end\": \"18:00\"}"` | | `DAY_OF_WEEK` | Day restriction | `"[\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\"]"` | | `DATE_RANGE` | Temporal validity | `"{\"start\": \"2025-07-01\", \"end\": \"2025-09-30\"}"` | | `BLACKOUT_PERIOD` | Block during windows | `"{\"windows\": [{\"start\": \"02:00\", \"end\": \"06:00\", \"reason\": \"Maintenance\"}]}"` | | `ALLOWED_CATEGORIES` | Allowed categories | `"[\"software\", \"infrastructure\"]"` | | `BLOCKED_CATEGORIES` | Blocked categories | `"[\"gambling\", \"adult\"]"` | | `ALLOWED_COUNTERPARTIES` | Allowed addresses | `"[\"0x123...\", \"0x456...\"]"` | | `BLOCKED_COUNTERPARTIES` | Blocked addresses | `"[\"0xdead...\"]"` | | `VELOCITY_LIMIT` | Transaction frequency | `"{\"maxCount\": 10, \"period\": \"HOUR\"}"` | | `REQUIRE_APPROVAL_ABOVE` | Approval threshold | `"2500"` | | `GEOGRAPHIC_RESTRICTION` | Blocked countries | `"[\"CU\", \"IR\", \"KP\", \"SY\", \"RU\"]"` | | `TRUST_SCORE` | Min trust score | `"0.7"` | | `COUNTERPARTY_STATUS` | Trust level requirement | `"{\"status\": \"TRUSTED\"}"` | | `CONTRACT_ALLOWLIST` | Allowed contracts | `"{\"contracts\": [\"0x...\"], \"protocols\": [\"uniswap\"]}"` | | `FAIRSCALE_MIN_SCORE` | Min Fairscale reputation (Solana) | `"0.7"` | The current payment evaluation context does not populate `fairscaleScore` directly, so `FAIRSCALE_MIN_SCORE` fails closed when configured as an `ALLOW` rule. Use `TRUST_SCORE` for production policy gates until the Fairscale context is wired through the payment flow. ### Supported Operators | Operator | Description | | --------------- | --------------------------------- | | `EQUALS` | Exact match | | `NOT_EQUALS` | Not equal | | `GREATER_THAN` | Greater than | | `GTE` | Greater than or equal | | `LESS_THAN` | Less than | | `LTE` | Less than or equal | | `IN` | Value in list (also `IN_LIST`) | | `NOT_IN` | Value not in list (also `NOT_IN_LIST`) | | `BETWEEN` | Within range | | `NOT_BETWEEN` | Outside range | ### Rule Actions - **`ALLOW`** - The condition describes what is permitted. If it does not match, the payment is denied. - **`DENY`** - The condition describes what is blocked. If it matches, the payment is denied. - **`REQUIRE_APPROVAL`** - The condition describes what needs review. If it matches and no DENY fires, the payment requires manual approval. ### Example: High-Value Approval Rule Block transactions over $500 unless manually approved: ```json { "name": "High Value Transaction Review", "policyType": "APPROVAL_THRESHOLD", "priority": 80, "rules": [ { "ruleType": "REQUIRE_APPROVAL_ABOVE", "operator": "GREATER_THAN", "value": "500", "action": "REQUIRE_APPROVAL" } ] } ``` ## Geographic Restrictions (OFAC) Geographic restrictions include both **built-in enforcement** (always active) and **configurable rules** (via policies). ### Built-in Enforcement The policy evaluator automatically performs two checks before any other policy is evaluated: 1. **Country check**: If `recipientCountry` is provided in the payment context, it's checked against the OFAC sanctioned countries list. Blocked immediately if matched. 2. **Address sanctions screening**: The recipient address is screened against sanctions lists via the configured provider (Chainalysis, TRM Labs, or a local OFAC SDN list). Blocked immediately if flagged. Configure the sanctions provider via the `SANCTIONS_PROVIDER` environment variable: - `chainalysis`: Chainalysis Risk API (requires `CHAINALYSIS_API_KEY`) - `trm`: TRM Labs API (requires `TRM_API_KEY`) - `local`: Local OFAC SDN list (default, no API key needed) ### Local Provider Lifecycle When `SANCTIONS_PROVIDER=local`, Conto checks recipient addresses against the `SanctionedAddress` table in the application database rather than a hardcoded sample list. - The `20260506000000_add_sanctioned_address` migration seeds the table with known high-confidence matches so new deployments are never empty. - The `sanctions-list-refresh` scheduled job refreshes the table from configured OFAC feeds and records refresh metadata for auditability. - If upstream feeds are temporarily unavailable, the seeded dataset remains in place so sanctions screening still has a conservative baseline. Info: To enable country-based blocking, include `recipientCountry` (ISO 3166-1 alpha-2, e.g., `"US"`, `"IR"`) in the `PaymentContext` when calling the evaluator. The SDK payment endpoints populate this automatically when available. ### Configurable Rules Add custom country allow/deny lists on top of the built-in checks: ```bash curl -X POST https://conto.finance/api/policies/{policyId}/rules \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "rules": [ { "ruleType": "GEOGRAPHIC_RESTRICTION", "operator": "IN_LIST", "value": "[\"US\", \"GB\", \"DE\", \"FR\"]", "action": "ALLOW" } ] }' ``` ### OFAC Sanctioned Countries (Built-in) | Code | Country | | ---- | ----------- | | CU | Cuba | | IR | Iran | | KP | North Korea | | SY | Syria | | RU | Russia | | BY | Belarus | | MM | Myanmar | | VE | Venezuela | | SD | Sudan | | SS | South Sudan | | LB | Lebanon | | LY | Libya | | SO | Somalia | | YE | Yemen | Always consult legal counsel for compliance requirements. This is not legal advice. ## Approval Thresholds Require manual approval above certain amounts: ```json { "name": "Approval Over 500", "policyType": "APPROVAL_THRESHOLD", "priority": 70, "rules": [ { "ruleType": "REQUIRE_APPROVAL_ABOVE", "operator": "GREATER_THAN", "value": "500", "action": "REQUIRE_APPROVAL" } ] } ``` When triggered: - Payment returns `REQUIRES_APPROVAL` - Approvers are notified - Payment held until approved or denied Conto records only one final approval decision for each request, even if multiple approvers act at nearly the same time. This prevents the same payment from being resolved twice. For external channels, email approvals use per-user confirmation links. Shared channels such as Slack, Telegram, WhatsApp, and generic webhooks deep-link back to the dashboard until the acting approver can be verified reliably. When you pair policy rules with approval workflows, you can also scope the workflow itself to a specific set of agent IDs. That is useful for verifier pilots where only one or two agents should route into an external approval channel while the rest of the org keeps its normal flow. Approval workflows are evaluated for every non-denied payment, so a matching workflow can still hold a request after the policy engine would otherwise allow it. Use this for layered controls, such as routing approved invoice payments through an external verifier before execution. ## Velocity Limits Control transaction frequency: ```bash curl -X POST https://conto.finance/api/policies/{policyId}/rules \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "rules": [ { "ruleType": "VELOCITY_LIMIT", "operator": "LESS_THAN", "value": "{\"maxCount\": 10, \"period\": \"HOUR\"}", "action": "ALLOW" }, { "ruleType": "VELOCITY_LIMIT", "operator": "LESS_THAN", "value": "{\"maxAmount\": 1000, \"period\": \"DAILY\"}", "action": "ALLOW" } ] }' ``` Note: Velocity counting is **per-wallet, per-agent**. It counts transactions with status CONFIRMED or PENDING. The current transaction is included in the count (+1). Use cases: - Prevent rapid drain attacks - Detect unusual patterns - Rate limit agent activity ## Category Restrictions Allow or block specific categories: ```bash curl -X POST https://conto.finance/api/policies/{policyId}/rules \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "rules": [ { "ruleType": "BLOCKED_CATEGORIES", "operator": "IN_LIST", "value": "[\"gambling\", \"adult\", \"weapons\"]", "action": "DENY" }, { "ruleType": "ALLOWED_CATEGORIES", "operator": "IN_LIST", "value": "[\"infrastructure\", \"ai_services\", \"marketing\"]", "action": "ALLOW" } ] }' ``` Note: Category matching is **case-insensitive**. If no `category` is provided in the payment request, `ALLOWED_CATEGORIES` rules with `ALLOW` action deny for safety because the allow condition cannot be verified. `BLOCKED_CATEGORIES` rules skip when no category is present. ## Contract Allowlist Restrict agent interactions to approved smart contracts, protocols, and function selectors. Contract metadata is auto-populated from the **Contract Registry**. ### Setting Up the Contract Registry Register known contracts so the policy evaluator can enrich payment requests with protocol metadata: ```bash curl -X POST https://conto.finance/api/contract-registry \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -d '{ "address": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", "protocolName": "uniswap", "protocolCategory": "DEX", "label": "Uniswap V2 Router", "chainId": "1" }' ``` ### Contract Allowlist Rules ```json { "policyType": "CONTRACT_ALLOWLIST", "rules": [ { "ruleType": "CONTRACT_ALLOWLIST", "operator": "IN_LIST", "value": "{\"protocols\": [\"uniswap\", \"aave\"], \"categories\": [\"DEX\", \"LENDING\"]}", "action": "ALLOW" } ] } ``` The value supports four filter types (all optional): | Field | Description | Example | | ------------ | --------------------------------- | ------------------------------ | | `contracts` | Allowed contract addresses | `["0x7a25...", "0x1f98..."]` | | `protocols` | Allowed protocol names | `["uniswap", "aave"]` | | `categories` | Allowed protocol categories | `["DEX", "LENDING", "BRIDGE"]` | | `functions` | Allowed 4-byte function selectors | `["0xa9059cbb", "0x095ea7b3"]` | ### Passing Contract Context in Payment Requests Include `targetContractAddress` (and optionally `functionSelector`) in payment requests: ```typescript const result = await conto.payments.request({ amount: 100, recipientAddress: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', purpose: 'Swap USDC for ETH', targetContractAddress: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', functionSelector: '0x38ed1739', }); ``` The evaluator automatically looks up `protocolName` and `protocolCategory` from the Contract Registry. If the caller provides them explicitly, those values take precedence over the registry lookup. Note: If a `CONTRACT_ALLOWLIST` rule with `ALLOW` action exists but the payment request does not include `targetContractAddress`, the request is **denied** (fail-closed). This prevents bypassing the allowlist by omitting context. ## Budget Allocations Cap cumulative spend over a period with a `BUDGET_CAP` rule. Scope it to a team or project by assigning the policy to the agents that belong to that team: ```json { "name": "Engineering Monthly Budget", "policyType": "BUDGET_ALLOCATION", "priority": 60, "rules": [ { "ruleType": "BUDGET_CAP", "operator": "LTE", "value": "{\"amount\": 50000, \"period\": \"MONTHLY\"}", "action": "ALLOW" } ] } ``` `BUDGET_CAP` aggregates the agent's spend for the period and allows the payment only if the running total stays at or under `amount`. ## Expiration Policies Limit a permission to a date window with a `DATE_RANGE` rule. Outside the window the `ALLOW` rule stops matching, so the payment is denied: ```json { "name": "Trial Period Access", "policyType": "EXPIRATION", "priority": 60, "rules": [ { "ruleType": "DATE_RANGE", "operator": "BETWEEN", "value": "{\"start\": \"2026-07-01T00:00:00Z\", \"end\": \"2026-09-30T23:59:59Z\"}", "action": "ALLOW" } ] } ``` Use cases: - Temporary elevated access - Trial periods - Contract-based time limits ## Composite Policies A `COMPOSITE` policy groups several rules that must **all** pass. Conto combines rules within a policy, and all policies assigned to an agent, with AND logic. There is no nested OR condition tree. To allow alternatives, widen a single rule's allowlist rather than trying to OR two rules together. ```json { "name": "Infrastructure Spend Guardrail", "policyType": "COMPOSITE", "priority": 70, "rules": [ { "ruleType": "MAX_AMOUNT", "operator": "LTE", "value": "1000", "action": "ALLOW" }, { "ruleType": "ALLOWED_CATEGORIES", "operator": "IN_LIST", "value": "[\"infrastructure\"]", "action": "ALLOW" } ] } ``` ## Example: High-Security Agent Complete configuration for a high-security agent. Each policy holds real rules, and all four are evaluated together with AND logic: ```json [ { "name": "OFAC Compliance", "policyType": "GEOGRAPHIC", "priority": 100, "rules": [ { "ruleType": "GEOGRAPHIC_RESTRICTION", "operator": "NOT_IN", "value": "[\"KP\", \"IR\", \"SY\", \"CU\", \"RU\"]", "action": "ALLOW" } ] }, { "name": "Whitelist Only", "policyType": "WHITELIST", "priority": 90, "rules": [ { "ruleType": "ALLOWED_COUNTERPARTIES", "operator": "IN_LIST", "value": "[\"0x1234567890abcdef1234567890abcdef12345678\"]", "action": "ALLOW" } ] }, { "name": "Strict Limits", "policyType": "SPEND_LIMIT", "priority": 80, "rules": [ { "ruleType": "MAX_AMOUNT", "operator": "LTE", "value": "100", "action": "ALLOW" }, { "ruleType": "DAILY_LIMIT", "operator": "LTE", "value": "500", "action": "ALLOW" } ] }, { "name": "All Require Approval", "policyType": "APPROVAL_THRESHOLD", "priority": 70, "rules": [ { "ruleType": "REQUIRE_APPROVAL_ABOVE", "operator": "GREATER_THAN", "value": "0", "action": "REQUIRE_APPROVAL" } ] } ] ``` ### x402 Protocol Rules These rules govern HTTP 402 micropayments made through the x402 protocol: | Rule Type | Description | Value Format | | ---------------------------- | ---------------------------------- | ---------------------------------------------------- | | `X402_MAX_PER_REQUEST` | Maximum amount per x402 request | `N` or `{"amount": N}` | | `X402_PRICE_CEILING` | Price ceiling for any x402 payment | `N` or `{"amount": N}` | | `X402_MAX_PER_ENDPOINT` | Limit per API endpoint | `{"maxAmount": N, "maxCalls": N, "period": "DAILY"}` | | `X402_MAX_PER_SERVICE` | Limit per service domain | `{"maxAmount": N, "maxCalls": N, "period": "DAILY"}` | | `X402_ALLOWED_SERVICES` | Allowlist of service domains | `["api.example.com", "data.service.io"]` | | `X402_BLOCKED_SERVICES` | Blocklist of service domains | `["malicious.site"]` | | `X402_ALLOWED_FACILITATORS` | Allowed x402 facilitator addresses | `["0x..."]` | | `X402_VELOCITY_PER_ENDPOINT` | Rate limit per endpoint | `{"maxCalls": N, "period": "HOUR"}` | | `X402_SESSION_BUDGET` | Session-level spending budget | `N` | `X402_SESSION_BUDGET` evaluates spend from x402 records that share the same `sessionId`. The counter ignores generic wallet transactions and other x402 sessions. ### MPP Protocol Rules These rules govern Machine Payment Protocol (MPP) session-based micropayments: | Rule Type | Description | Value Format | | ----------------------------- | ---------------------------------- | ---------------------------------------------------- | | `MPP_MAX_PER_REQUEST` | Maximum per MPP credential charge | `N` or `{"amount": N}` | | `MPP_PRICE_CEILING` | Price ceiling for MPP payments | `N` or `{"amount": N}` | | `MPP_MAX_PER_ENDPOINT` | Limit per MPP resource endpoint | `{"maxAmount": N, "maxCalls": N}` | | `MPP_MAX_PER_SERVICE` | Limit per MPP service domain | `{"maxAmount": N, "maxCalls": N, "period": "DAILY"}` | | `MPP_ALLOWED_SERVICES` | Allowlist of MPP service domains | `["api.example.com"]` | | `MPP_BLOCKED_SERVICES` | Blocklist of MPP service domains | `["blocked.site"]` | | `MPP_SESSION_BUDGET` | Session-level spending budget | `N` | | `MPP_MAX_SESSION_DEPOSIT` | Hard cap on session deposit amount | `N` | | `MPP_MAX_CONCURRENT_SESSIONS` | Max active sessions per agent | `N` | | `MPP_MAX_SESSION_DURATION` | Maximum session duration in hours | `N` | | `MPP_BLOCK_SESSION_INTENT` | Block opening MPP sessions | any value; condition checks `intent === "session"` | | `MPP_VELOCITY_PER_ENDPOINT` | Rate limit per MPP endpoint | `{"maxCalls": N, "period": "HOUR"}` | `MPP_SESSION_BUDGET` evaluates spend from MPP records that share the same `sessionId`. Record settled per-call detail in `batchItems` when multiple charges are included in one settlement. Avoid `MPP_ALLOWED_METHODS` until the runtime check is fixed. The current strategy is inverted and can deny methods that are listed as allowed. ### AgentScore Commerce Rules These rules fold merchant identity and compliance checks into the normal Conto policy engine. They apply when the payment flow includes an AgentScore assess step, either because your agent is paying an AgentScore-gated merchant or because the merchant uses a conto-hosted gate. | Rule Type | Purpose | Example Value | | ---------------------------------- | ------------------------------------------ | ------------- | | `AGENTSCORE_REQUIRE_VERIFIED` | Require a verified human behind the agent | `"true"` | | `AGENTSCORE_ALLOWED_JURISDICTIONS` | Allow only specific operator jurisdictions | `["US","CA"]` | | `AGENTSCORE_BLOCKED_JURISDICTIONS` | Deny specific operator jurisdictions | `["IR","KP"]` | When a merchant gate needs more identity proof, Conto returns a `402`/`403` step-up response with a verification URL, stores an `AgentScoreVerification` session, and resumes the payment after the session reaches `VERIFIED`. The final allow/deny decision still runs back through the policy evaluator so AgentScore-derived jurisdiction or verification status can trip normal deny rules. ### Card Payment Rules These rules govern card-based payments (virtual or physical): | Rule Type | Description | Value Format | | ------------------------ | ------------------------------- | ---------------------- | | `CARD_MAX_AMOUNT` | Maximum per card transaction | `"500"` | | `CARD_ALLOWED_MCCS` | Allowed merchant category codes | `["5411", "5812"]` | | `CARD_BLOCKED_MCCS` | Blocked merchant category codes | `["7995"]` | | `CARD_ALLOWED_MERCHANTS` | Allowed merchant names | `["Amazon", "Stripe"]` | | `CARD_BLOCKED_MERCHANTS` | Blocked merchant names | `["Casino.com"]` | ## Bulk Policy Operations ### Create Multiple Policies ```bash curl -X POST https://conto.finance/api/policies/bulk \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "policies": [ { "name": "Policy 1", "policyType": "SPEND_LIMIT", ... }, { "name": "Policy 2", "policyType": "TIME_WINDOW", ... } ] }' ``` ### Assign to Multiple Agents ```bash curl -X PUT https://conto.finance/api/policies/bulk \ -H "Authorization: Bearer $CONTO_API_KEY" \ -d '{ "assignments": [ { "policyId": "cmm5c2pol002n49h7dmsuc33r", "agentIds": ["cmm5a4agt005q49h7bjqza66u", "cmm5a5agt006r49h7bjqza77v"] }, { "policyId": "cmm5c3pol003o49h7dmsuc44s", "agentIds": ["cmm5a6agt007s49h7bjqza88w"] } ] }' ``` --- # SDK Installation The Conto SDK provides two clients: - `Conto` for agent-scoped payment and read operations - `ContoAdmin` for organization-scoped provisioning and management ## Installation ```bash npm npm install @conto_finance/sdk ``` ```bash yarn yarn add @conto_finance/sdk ``` ```bash pnpm pnpm add @conto_finance/sdk ``` ```bash bun bun add @conto_finance/sdk ``` ## Packages | Package | Scope | Description | | ----------------------------------- | ---------------- | ------------------------------------------------------------- | | `@conto_finance/sdk` | `@conto` | TypeScript SDK for payment operations | | `@conto_finance/create-conto-agent` | `@conto_finance` | CLI quickstart tool (`npx @conto_finance/create-conto-agent`) | | `@conto_finance/mcp-server` | `@conto_finance` | MCP server for Claude Desktop | ## Requirements - Node.js 18+ or Bun - TypeScript 4.7+ (optional but recommended) ## Choose Your Client First Use `Conto` with an agent SDK key (`conto_agent_...`, stored as `CONTO_API_KEY`) for payment operations and agent-scoped reads, including the MCP server. Use `ContoAdmin` with an organization API key (`conto_...`, stored as `CONTO_ORG_API_KEY`) to provision agents, wallets, policies, or memberships from your backend. For the full credential selection guide, including admin SDK keys, see [Choose the Right Credential](https://conto.finance/docs/sdk/authentication#choose-the-right-credential). Do not put `conto_agent_...` into `CONTO_ORG_API_KEY`, and do not put `conto_...` into `CONTO_API_KEY`. ## Basic Agent Setup ```typescript import { Conto } from '@conto_finance/sdk'; const conto = new Conto({ apiKey: process.env.CONTO_API_KEY!, // conto_agent_xxx... }); ``` ## Organization Setup with `ContoAdmin` ```typescript import { ContoAdmin } from '@conto_finance/sdk'; const admin = new ContoAdmin({ orgApiKey: process.env.CONTO_ORG_API_KEY!, // conto_xxx... }); ``` ## Configuration Options | Option | Type | Default | Description | | --------- | ------ | ----------------------- | ------------------------------- | | `apiKey` | string | Required | Your agent's SDK API key | | `baseUrl` | string | `https://conto.finance` | API base URL | | `timeout` | number | `30000` | Request timeout in milliseconds | Info: The SDK automatically retries transient failures (429 rate limits, 5xx server errors) with exponential backoff. See [Retry Strategy](https://conto.finance/docs/sdk/error-handling#retry-strategy) for the exact behavior. ### Full Configuration Example ```typescript const conto = new Conto({ apiKey: process.env.CONTO_API_KEY!, timeout: 30000, // 30 seconds }); ``` ## Environment Variables We recommend using environment variables for configuration: ```bash .env CONTO_API_KEY=conto_agent_abc123def456... CONTO_ORG_API_KEY=conto_abc123def456... ``` Pass them to the constructors shown above: `apiKey` for `Conto`, `orgApiKey` for `ContoAdmin`. ## TypeScript Support The SDK is written in TypeScript and includes full type definitions: ```typescript import { Conto, ContoConfig, PaymentRequestInput, PaymentRequestResult, PaymentExecuteResult, ContoError, } from '@conto_finance/sdk'; // All types are automatically inferred const request: PaymentRequestResult = await conto.payments.request({ amount: 100, recipientAddress: '0x...', }); ``` ## Framework Integration ### Next.js ```typescript // lib/conto.ts import { Conto } from '@conto_finance/sdk'; export const conto = new Conto({ apiKey: process.env.CONTO_API_KEY!, }); ``` ### Express ```typescript // app.ts import express from 'express'; import { Conto } from '@conto_finance/sdk'; const app = express(); const conto = new Conto({ apiKey: process.env.CONTO_API_KEY!, }); app.post('/pay', async (req, res) => { const result = await conto.payments.pay(req.body); res.json(result); }); ``` ### Serverless (AWS Lambda) ```typescript import { Conto } from '@conto_finance/sdk'; // Initialize outside handler for connection reuse const conto = new Conto({ apiKey: process.env.CONTO_API_KEY!, timeout: 10000, // Lower timeout for Lambda }); export const handler = async (event: any) => { const result = await conto.payments.pay(JSON.parse(event.body)); return { statusCode: 200, body: JSON.stringify(result), }; }; ``` ## Verifying Installation Verify connectivity with a read-only call. `GET /api/sdk/setup` returns your agent, wallets, and granted scopes without creating any payment record: ```typescript async function verifySetup() { const res = await fetch('https://conto.finance/api/sdk/setup', { headers: { Authorization: `Bearer ${process.env.CONTO_API_KEY}` }, }); if (!res.ok) { throw new Error(`Setup check failed: ${res.status}`); } const setup = await res.json(); console.log('SDK connected successfully!'); console.log('Agent status:', setup.agent.status); console.log('Wallets:', setup.wallets.length); console.log('Scopes:', setup.scopes); } verifySetup().catch(console.error); ``` ## Next Steps ### Authentication Link: https://conto.finance/docs/sdk/authentication Learn about SDK authentication ### Admin SDK Link: https://conto.finance/docs/sdk/admin Provision agents and wallets with org API keys ### Payments Link: https://conto.finance/docs/sdk/payments Make your first payment --- # SDK Authentication Conto SDK requests authenticate with agent-specific SDK keys: ```text conto_agent_[64-character-hex-string] ``` Every SDK key belongs to exactly one agent. SDK keys always expire automatically: the default lifetime is **365 days** and the maximum is **730 days**. ## Choose the Right Credential Use the credential type that matches the job you need to do: | Credential | Format | Best for | Notes | | ------------------------ | ----------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------- | | **Standard SDK key** | `conto_agent_...` | The agent payment lifecycle (request, execute, approve, confirm) plus agent-scoped reads | Works with the `Conto` client | | **Admin SDK key** | `conto_agent_...` | Delegated agent workflows that need elevated access to agents, wallets, or policies | Agent-scoped identity with an expanded scope preset | | **Organization API key** | `conto_...` | Backend/admin automation across the whole organization | Use with `ContoAdmin` | Info: `ContoAdmin` requires an **organization API key**. Admin SDK keys can call elevated HTTP API endpoints, but they are not a drop-in replacement for the `ContoAdmin` constructor. ## Generate SDK Keys ### Via Dashboard Go to **Agents** and select the agent that will use the key. Open **SDK Keys** and click **Generate New Key**. Select **Standard** for the payment lifecycle plus read access, or **Admin** if the agent also needs elevated management access. Choose an expiration window. Keys default to 365 days and cannot exceed 730 days. The full key is shown only once. Store it in your secrets manager before closing the dialog. ### Via API ```bash curl -X POST https://conto.finance/api/agents/{agentId}/sdk-keys \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Production Key", "expiresInDays": 90, "keyType": "standard" }' ``` **Response** ```json { "id": "cmm5d0key000l49h7entvd11p", "key": "conto_agent_abc123def456...", "name": "Production Key", "keyType": "standard", "scopes": [ "payments:request", "payments:execute", "payments:approve", "payments:confirm", "wallets:read", "policies:read", "transactions:read", "counterparties:read", "alerts:read", "agents:read", "analytics:read", "network:read" ], "message": "Save this key now! It will not be shown again." } ``` Info: `POST /api/agents/{agentId}/sdk-keys` accepts `name`, optional `expiresInDays`, and optional `keyType`. Standard keys created through this endpoint use the standard preset shown above: the payment lifecycle plus read scopes. ## Use SDK Keys Client initialization and environment-variable setup live in [SDK Installation](https://conto.finance/docs/sdk/installation): pass the agent SDK key as `apiKey` to `Conto`, and the organization API key as `orgApiKey` to `ContoAdmin`. ### Admin SDK Reference Link: https://conto.finance/docs/sdk/admin Use organization API keys with `ContoAdmin` for organization-wide provisioning and management. Info: Organization API keys are the right credential for programmatic wallet provisioning and cleanup. That includes `create`, `get`, `update`, and `delete` wallet operations through the Admin SDK or the corresponding `/api/wallets` HTTP endpoints. To archive a wallet, use `update({ status: 'ARCHIVED' })`. ## Standard SDK Scopes Standard SDK keys cover the full payment lifecycle plus read access. Spending control comes from policies, spend limits, approvals, and custody, not from withholding payment scopes. | Scope | Included by default | Description | | ---------------------- | ------------------- | --------------------------------------------------------- | | `payments:request` | Yes | Request policy evaluation for a payment | | `payments:execute` | Yes | Execute approved payments or use `autoExecute` | | `payments:approve` | Yes | Approve external-wallet payments | | `payments:confirm` | Yes | Confirm external-wallet payments | | `wallets:read` | Yes | View wallet balances and limits | | `policies:read` | Yes | View policies assigned to the agent | | `transactions:read` | Yes | View transaction history | | `counterparties:read` | Yes | View counterparties and trust data | | `alerts:read` | Yes | View alerts related to the agent | | `agents:read` | Yes | View agent profile and setup summary | | `analytics:read` | Yes | View spend analytics | | `network:read` | Yes | Query network trust data | | `transactions:write` | No | Retry failed transactions or record x402/MPP transactions | | `policies:exceptions` | No | Request and view policy exceptions | | `counterparties:write` | No | Create and update counterparties | | `alerts:write` | No | Acknowledge and resolve alerts | | `audit:read` | No | View audit logs | Info: Standard SDK keys created through the SDK-key management endpoint start from this preset, and the creation response lists the granted `scopes`. Every payment a standard key executes still passes through policy evaluation, spend limits, and any approval workflows. Use `keyType: "admin"` only when the agent needs delegated management access to agents, wallets, or policies. ## Admin SDK Keys Admin SDK keys use an elevated preset intended for delegated agent management workflows. They include: - All standard SDK scopes - `agents:write` - `wallets:write` - `policies:write` They do **not** include organization-superuser capabilities such as team management, organization settings, or the `admin` super-scope. They also cannot create other admin SDK keys. That escalation path is blocked intentionally. ## Key Expiration All SDK keys have a mandatory expiration. | Value | Behavior | | ------- | -------------------------------------- | | Omitted | Defaults to **365 days** | | `30` | Short-lived testing key | | `90` | Recommended production rotation window | | `365` | Long-lived standard key | | `730` | Maximum allowed lifetime | There is no non-expiring SDK key mode. Build key rotation into your operational runbooks. ## Revoke Keys ### Via Dashboard 1. Go to **Agents** 2. Open the agent 3. Open **SDK Keys** 4. Click **Revoke** ### Via API ```bash curl -X DELETE "https://conto.finance/api/agents/{agentId}/sdk-keys?keyId={keyId}" \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" ``` Revocation is immediate. ## Best Practices - Store SDK keys in a secrets manager, not in source control. - Use separate keys for development, staging, and production. - Prefer standard keys unless the agent truly needs elevated management access. - Standard keys can move funds, so constrain agents with policies, spend limits, and approval workflows rather than treating the key as the control surface. - Rotate keys on a schedule instead of waiting for emergency revocations. --- # Admin SDK The Admin SDK lets you programmatically create agents, provision wallets, and configure spending policies. It uses **organization API keys** (`conto_xxx...`) which operate at the org level, separate from the agent SDK keys used for payments. ```typescript import { ContoAdmin } from '@conto_finance/sdk'; const admin = new ContoAdmin({ orgApiKey: process.env.CONTO_ORG_API_KEY!, }); // Create a policy, create an agent, wire them together const policy = await admin.policies.create({ name: 'Daily $500 limit', policyType: 'SPEND_LIMIT', rules: [{ ruleType: 'DAILY_LIMIT', operator: 'LTE', value: '500' }], }); const agent = await admin.agents.create({ name: 'billing-agent', agentType: 'CUSTOM', }); await admin.agents.assignPolicy(agent.id, policy.id); ``` ## Organization API Keys Organization API keys authenticate at the org level and can manage all agents, wallets, and policies in the organization. They are different from agent SDK keys. | | Org API Key | Agent SDK Key | |---|---|---| | **Format** | `conto_xxx...` | `conto_agent_xxx...` | | **Scope** | Entire organization | Single agent | | **Used for** | Admin operations | Payment operations | | **SDK class** | `ContoAdmin` | `Conto` | ### Creating an Org API Key Navigate to **Settings** > **API Keys** in the dashboard. Click **Create API Key**, enter a name, and select a scope preset: - **Read Only** - View agents, wallets, policies - **Standard** - Read + write agents, wallets, policies, plus membership lookup for ownership flows - **Admin** - Full access (Owner only) Copy and save the key immediately. It is only shown once. ### Scopes Org API keys use fine-grained scopes that control what the key can access: | Scope | Description | |-------|-------------| | `agents:read` | List and view agents | | `agents:write` | Create, update, delete, freeze/unfreeze agents | | `wallets:read` | List and view wallets | | `wallets:write` | Create, update, delete, provision wallets | | `policies:read` | List and view policies and rules | | `policies:write` | Create, update, delete policies, manage rules, assign to agents | | `transactions:read` | View transaction history | | `counterparties:read` | View counterparties | | `counterparties:write` | Create and update counterparties | | `alerts:read` | View alerts | | `alerts:write` | Acknowledge and resolve alerts | | `analytics:read` | View spending analytics | | `audit:read` | View audit logs | | `team:read` | List organization memberships and ownership candidates | ## Initialization ```typescript import { ContoAdmin } from '@conto_finance/sdk'; const admin = new ContoAdmin({ orgApiKey: process.env.CONTO_ORG_API_KEY!, timeout: 30000, // Optional, 30s default }); ``` Info: `ContoAdmin` rejects agent SDK keys (`conto_agent_xxx`). If you pass one, it throws an error telling you to use the `Conto` class instead. ## admin.agents Manage the lifecycle of AI agents in your organization. ### agents.list() List agents with optional filters. ```typescript const { agents, total } = await admin.agents.list({ status: 'ACTIVE', search: 'billing', limit: 20, offset: 0, }); ``` | Parameter | Type | Description | |-----------|------|-------------| | `status` | string | Filter by status: ACTIVE, PAUSED, SUSPENDED, REVOKED, FROZEN | | `search` | string | Search by name or description | | `limit` | number | Results per page (1-100, default 50) | | `offset` | number | Pagination offset | ### agents.create() Create a new agent. ```typescript const { members } = await admin.team.listMembers(); const serviceOwner = members.find((member) => member.user?.email === 'ops@yourcompany.com'); const agent = await admin.agents.create({ name: 'billing-agent', agentType: 'CUSTOM', description: 'Handles vendor payments', ownerMembershipId: serviceOwner?.id, }); ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `name` | string | Yes | Agent name (1-100 chars) | | `agentType` | string | Yes | OPENAI_ASSISTANT, ANTHROPIC_CLAUDE, LANGCHAIN, AUTOGPT, or CUSTOM | | `description` | string | No | Description (max 500 chars) | | `publicKey` | string | No | Ethereum address (auto-generated if omitted) | | `externalId` | string | No | Your own identifier for the agent | | `ownerMembershipId` | string | No | Organization member to record as the agent owner for programmatic/admin flows. Fetch this from `admin.team.listMembers()`. If omitted, Conto assigns a default owner. | ## admin.team List organization memberships for the authenticated organization. This is useful when you need a stable `ownerMembershipId` to reuse across agent creation and repair flows. ### team.listMembers() ```typescript const { organizationId, members } = await admin.team.listMembers(); const dedicatedOwner = members.find((member) => member.user?.email === 'ops@yourcompany.com'); if (!dedicatedOwner) { throw new Error('No dedicated owner membership found'); } await admin.agents.create({ name: 'billing-agent', agentType: 'CUSTOM', ownerMembershipId: dedicatedOwner.id, }); ``` This method requires an org API key with the `team:read` scope or `admin`. ### agents.get() ```typescript const agent = await admin.agents.get('agent_id'); ``` ### agents.update() ```typescript await admin.agents.update('agent_id', { name: 'Updated Name', status: 'PAUSED', }); ``` ### agents.delete() Soft-deletes an agent. Deactivates its SDK keys and wallet/card links. ```typescript await admin.agents.delete('agent_id'); ``` ### agents.freeze() / agents.unfreeze() Freeze blocks all transactions for an agent. Unfreeze restores them. ```typescript await admin.agents.freeze('agent_id', { reason: 'Suspicious activity detected', freezeWallets: true, }); await admin.agents.unfreeze('agent_id', { reason: 'Investigation complete', unfreezeWallets: true, resetCounters: true, }); ``` ### agents.linkWallet() Link a wallet to an agent with spending limits. ```typescript await admin.agents.linkWallet('agent_id', { walletId: 'wallet_id', delegationType: 'LIMITED', spendLimitPerTx: 100, spendLimitDaily: 1000, spendLimitWeekly: 5000, allowedDays: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], }); ``` | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `walletId` | string | Required | Wallet to link | | `delegationType` | string | LIMITED | FULL, LIMITED, VIEW_ONLY, PREAPPROVED, ALLOWLIST | | `spendLimitPerTx` | number | 100 | Max per transaction | | `spendLimitDaily` | number | 1000 | Max per day | | `spendLimitWeekly` | number | - | Max per week | | `spendLimitMonthly` | number | - | Max per month | | `allowedHoursStart` | number | 0 | Allowed hours start (0-23) | | `allowedHoursEnd` | number | 24 | Allowed hours end (1-24) | | `allowedDays` | string[] | Mon-Fri | Allowed days of week | ### agents.assignPolicy() / agents.unassignPolicy() ```typescript await admin.agents.assignPolicy('agent_id', 'policy_id'); await admin.agents.unassignPolicy('agent_id', 'policy_id'); ``` ### agents.listWallets() / agents.listPolicies() ```typescript const { wallets } = await admin.agents.listWallets('agent_id'); const { policies } = await admin.agents.listPolicies('agent_id'); ``` ### agents.createSdkKey() / agents.listSdkKeys() / agents.revokeSdkKey() Create agent SDK keys programmatically. The key value is returned only once. ```typescript const { key } = await admin.agents.createSdkKey('agent_id', { name: 'Production Key', keyType: 'standard', expiresInDays: 90, }); console.log('Save this key:', key); // conto_agent_xxx... const keys = await admin.agents.listSdkKeys('agent_id'); await admin.agents.revokeSdkKey('agent_id', 'key_id'); ``` ## admin.wallets Manage wallets across the organization. ### wallets.list() ```typescript const { wallets, total } = await admin.wallets.list({ chainType: 'EVM', status: 'ACTIVE', limit: 20, }); ``` | Parameter | Type | Description | |-----------|------|-------------| | `status` | string | ACTIVE, FROZEN, ARCHIVED | | `chainType` | string | EVM or SOLANA | | `chainId` | string | Specific chain ID | | `limit` | number | Results per page (1-100, default 50) | | `offset` | number | Pagination offset | ### wallets.create() ```typescript const wallet = await admin.wallets.create({ name: 'billing-wallet', chainType: 'EVM', custodyType: 'SPONGE', }); ``` | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `name` | string | Required | Wallet name (1-100 chars) | | `chainType` | string | EVM | EVM or SOLANA | | `chainId` | string | - | Chain ID (defaults to Tempo testnet) | | `custodyType` | string | PRIVY | PRIVY, SPONGE, EXTERNAL, SMART_CONTRACT | | `walletType` | string | EOA | EOA, SMART_WALLET, MULTISIG | | `address` | string | - | Required when attaching an existing wallet instead of minting a new one | | `externalWalletId` | string | - | Existing provider wallet ID. Use with `custodyType=PRIVY` to attach an existing Privy wallet | | `importAddress` | string | - | Legacy watch-only import path for `EXTERNAL` custody | Attach an existing Privy-backed wallet: ```typescript const wallet = await admin.wallets.create({ name: 'enchant-treasury', chainType: 'EVM', chainId: '8453', custodyType: 'PRIVY', externalWalletId: 'privy_wallet_123', address: '0x1234...abcd', }); ``` Register a self-custodied wallet: ```typescript const wallet = await admin.wallets.create({ name: 'external-ops-wallet', chainType: 'EVM', chainId: '8453', custodyType: 'EXTERNAL', address: '0xabcd...1234', }); ``` `wallets.create()` is idempotent within the organization per `externalWalletId + chainId` or `address + chainId`, so retrying the same request returns the existing wallet instead of creating a duplicate. This attach flow only works when the referenced wallet is visible to the same Privy app Conto is configured to use for managed execution. If the signer lives in a different Privy app or an external wallet stack, register it as `EXTERNAL` instead. ### wallets.get() / wallets.update() / wallets.delete() ```typescript const wallet = await admin.wallets.get('wallet_id'); await admin.wallets.update('wallet_id', { name: 'Renamed Wallet', status: 'FROZEN', }); await admin.wallets.delete('wallet_id'); // Fails if linked to agents or if payment history exists ``` Organization API keys can now manage the full wallet lifecycle through `wallets.get()`, `wallets.update()`, and `wallets.delete()` in addition to `wallets.list()` and `wallets.create()`. ### wallets.provision() Link a wallet to its custody provider and sync its onchain state. ```typescript const result = await admin.wallets.provision('wallet_id'); console.log('Address:', result.wallet.address); console.log('Balance:', result.wallet.balance, result.wallet.currency); ``` ### wallets.refreshBalance() Fetch the latest balance from the chain. ```typescript const result = await admin.wallets.refreshBalance('wallet_id'); console.log('Total:', result.totalBalance); for (const balance of result.balances) { console.log(`${balance.chainName}:`, balance.balance, balance.symbol); } ``` ## admin.policies Create and manage spending policies and their rules. ### policies.list() ```typescript const { policies, total } = await admin.policies.list({ limit: 50, offset: 0, }); ``` ### policies.create() Create a policy with optional rules and agent assignments in one call. ```typescript const policy = await admin.policies.create({ name: 'Conservative limits', policyType: 'SPEND_LIMIT', priority: 50, rules: [ { ruleType: 'MAX_AMOUNT', operator: 'LTE', value: '200' }, { ruleType: 'DAILY_LIMIT', operator: 'LTE', value: '1000' }, { ruleType: 'MONTHLY_LIMIT', operator: 'LTE', value: '10000' }, ], agentIds: ['cmm5a2agt003o49h7bjqza44s', 'cmm5a3agt004p49h7bjqza55t'], // Assign immediately }); ``` ### Policy Types | Type | Description | |------|-------------| | `SPEND_LIMIT` | Transaction and periodic spending limits | | `APPROVAL_THRESHOLD` | Require human approval above a threshold | | `COUNTERPARTY` | Allow/block specific counterparties | | `CATEGORY` | Allow/block spending categories | | `GEOGRAPHIC` | Country-based restrictions | | `TIME_WINDOW` | Time-of-day restrictions | | `VELOCITY` | Transaction frequency limits | | `WHITELIST` | Allowlist-only recipients | | `CONTRACT_ALLOWLIST` | Allowed smart contracts | | `BLACKOUT_PERIOD` | Block transactions during specific periods | | `BUDGET_ALLOCATION` | Budget cap enforcement | | `EXPIRATION` | Date-range validity | | `COMPOSITE` | Combine multiple rule types | | `MERCHANT` | Merchant category restrictions | ### policies.get() / policies.update() / policies.delete() ```typescript const policy = await admin.policies.get('policy_id'); await admin.policies.update('policy_id', { name: 'Updated name', isActive: false, priority: 75, }); await admin.policies.delete('policy_id'); ``` ### Rule Management Add, update, and remove individual rules on a policy. ```typescript // Add a single rule await admin.policies.addRule('policy_id', { ruleType: 'DAILY_LIMIT', operator: 'LTE', value: '500', action: 'DENY', }); // Add multiple rules at once await admin.policies.addRules('policy_id', [ { ruleType: 'MAX_AMOUNT', operator: 'LTE', value: '100' }, { ruleType: 'WEEKLY_LIMIT', operator: 'LTE', value: '2000' }, ]); // Update a rule await admin.policies.updateRule('policy_id', 'rule_id', { value: '750', }); // Delete a rule await admin.policies.deleteRule('policy_id', 'rule_id'); // Delete all rules await admin.policies.deleteAllRules('policy_id'); ``` ### Rule Operators | Operator | Description | |----------|-------------| | `EQUALS` | Exact match | | `NOT_EQUALS` | Not equal | | `GREATER_THAN` | Greater than | | `LESS_THAN` | Less than | | `GTE` | Greater than or equal | | `LTE` | Less than or equal | | `IN` / `IN_LIST` | Value is in list | | `NOT_IN` / `NOT_IN_LIST` | Value is not in list | | `BETWEEN` | Value is between two bounds | | `NOT_BETWEEN` | Value is outside bounds | | `DENY` | Always deny | ### Rule Actions | Action | Description | |--------|-------------| | `ALLOW` | Allow if condition met (default) | | `DENY` | Block if condition met | | `REQUIRE_APPROVAL` | Require human approval if condition met | ## Complete Example Provision a new agent from scratch: ```typescript import { ContoAdmin } from '@conto_finance/sdk'; const admin = new ContoAdmin({ orgApiKey: process.env.CONTO_ORG_API_KEY!, }); // 1. Create a wallet const wallet = await admin.wallets.create({ name: 'ops-wallet', chainType: 'EVM', custodyType: 'SPONGE', }); await admin.wallets.provision(wallet.id); // 2. Create a spending policy const policy = await admin.policies.create({ name: 'Standard ops limits', policyType: 'SPEND_LIMIT', rules: [ { ruleType: 'MAX_AMOUNT', operator: 'LTE', value: '500' }, { ruleType: 'DAILY_LIMIT', operator: 'LTE', value: '2000' }, ], }); // 3. Create the agent const agent = await admin.agents.create({ name: 'ops-agent', agentType: 'CUSTOM', description: 'Handles operational payments', }); // 4. Link wallet with per-agent limits await admin.agents.linkWallet(agent.id, { walletId: wallet.id, delegationType: 'LIMITED', spendLimitPerTx: 500, spendLimitDaily: 2000, }); // 5. Assign the policy await admin.agents.assignPolicy(agent.id, policy.id); // 6. Generate an SDK key for the agent const { key } = await admin.agents.createSdkKey(agent.id, { name: 'Production', expiresInDays: 90, }); console.log('Agent ready. SDK key:', key); ``` ## Security Org API keys can manage all agents and wallets in the organization. Store them in a secrets manager (AWS Secrets Manager, Vault, etc.), never in source control. Use the minimum scope needed for the task. Create keys with only the scopes your pipeline needs. A deployment script that provisions agents only needs `agents:write`, `wallets:write`, and `policies:write`. Set expiration when creating keys. When rotating: 1. Create a new key 2. Update your secrets 3. Deploy 4. Revoke the old key Every operation made with an org API key is recorded in the audit log with actor type `API_KEY` and the key ID. Review audit logs in the dashboard under **Audit Logs**. ### Limitations Org API keys **cannot** change billing plans. Billing changes require dashboard session auth with an Owner account. ## Error Handling ```typescript try { await admin.agents.create({ name: 'test', agentType: 'CUSTOM' }); } catch (error) { console.error(error.code, error.status, error.message); } ``` | Error Code | Status | Description | |------------|--------|-------------| | `AUTH_FAILED` | 401 | Invalid or revoked API key | | `INSUFFICIENT_SCOPE` | 403 | Key lacks required scope | | `NOT_FOUND` | 404 | Resource not found | | `VALIDATION_FAILED` | 400 | Invalid request body | | `TIMEOUT` | 0 | Request timed out | ## Next Steps ### Policies Link: https://conto.finance/docs/policies/overview Learn about the policy engine and all rule types ### Authentication Link: https://conto.finance/docs/sdk/authentication Agent SDK keys and scopes ### Payments Link: https://conto.finance/docs/sdk/payments Making payments with agent SDK keys ### CLI Policies Link: https://conto.finance/docs/cli/policies Manage policies from the command line --- # Payments API The payments API allows agents to request authorization and execute stablecoin payments. ## Overview The payment flow has two steps: 1. **Request** - Request authorization and policy evaluation 2. **Execute** - Execute the approved payment onchain Or use `autoExecute: true` to request and execute in a single API call. You can also use the SDK convenience method `pay()` to do both in one call. ## Choose The Right Flow | Wallet model | Use this flow | What Conto can stop | | ------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------- | | **Managed** (`PRIVY`, `SPONGE`) | `request -> execute` | Conto stays in the execution path and can block the spend | | **External** (`EXTERNAL`) | `approve -> transfer -> confirm` | Conto governs the Conto-routed flow, but cannot block a direct self-signed transfer outside Conto | `payments.execute()` is for managed wallets. If your agent holds the signing keys, use the external-wallet `approve -> confirm` flow instead. ## payments.request() Request authorization for a payment. This evaluates policies without executing. ```typescript const request = await conto.payments.request({ amount: 100, recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...', recipientName: 'OpenAI', purpose: 'GPT-4 API credits', category: 'AI_SERVICES', }); ``` ### Parameters | Parameter | Type | Required | Description | | ----------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `amount` | number | Yes | Payment amount | | `recipientAddress` | string | Yes | Wallet address. `0x` + 40 hex chars for EVM, or base58 (32-44 chars) for Solana. Validated via Zod schema. | | `recipientName` | string | No | Human-readable name | | `purpose` | string | No | Why this payment is needed | | `category` | string | No | Spending category | | `context` | object | No | Additional metadata | | `walletId` | string | No | Specific wallet to use | | `urgency` | string | No | LOW, NORMAL, HIGH, CRITICAL | | `autoExecute` | `boolean` | No | If `true`, automatically execute the payment when approved. Returns the transaction result directly instead of requiring a separate `execute()` call. | | `targetContractAddress` | string | No | Smart contract address for contract interaction policy evaluation | | `functionSelector` | string | No | 4-byte function selector (e.g., `0xa9059cbb`) for contract allowlist rules | | `idempotencyKey` | string | No | Client-supplied key that makes retries safe. Reusing the same key with the same request returns the original request; reusing it with different request parameters returns a conflict. | Note: **External wallet users:** If your agent controls its own wallet keys and uses the `/api/sdk/payments/approve` endpoint instead, `chainId` is a required parameter. See the [Agent Skills guide](https://conto.finance/docs/sdk/skills) (OpenClaw and Hermes) for the external-wallet flow. Note: If you include `context.invoice`, Conto preserves that payload in the raw request context and also stores a typed invoice record on the `PaymentRequest`. Supported invoice fields are `vendorId`, `vendorAddress`, `id`, `hash`, `sourceUrl`, `payload`, `expectedAmount`, `currency`, and `dueDate`. Delta verification workflows and `payment.executed` webhook payloads prefer this typed invoice record for new requests. For a full setup and live test example, see [Delta Verification Setup](https://conto.finance/docs/guides/delta-setup) and [Delta Smoke Test](https://conto.finance/docs/guides/delta-smoke-test). Note: Delta access is currently enabled by Conto during onboarding. If you want to use this flow, contact [sales@conto.finance](mailto:sales@conto.finance). Note: If an approval workflow matches any non-denied request, Conto opens the approval request immediately and includes `approvalRequestId` in the API response. This includes workflows that intentionally gate otherwise policy-approved payments, such as the Delta pilot workflow. ### External Wallet Approve/Confirm Flow If your agent holds the signing keys, use the external-wallet flow instead of `payments.execute()`: 1. Call `POST /api/sdk/payments/approve` to evaluate policy and receive an `approvalToken` 2. Submit the onchain transfer through your own signer or wallet integration 3. Call `POST /api/sdk/payments/{requestId}/confirm` with the final `txHash`, plus the `approvalToken` when the original `/approve` response returned one This keeps the same policy checks and audit trail while leaving execution in the agent's control. It does not cryptographically block a direct transfer signed outside Conto. Note: Confirmation atomically claims an approved external-wallet payment before creating the transaction record and updating spend tracking. A repeated confirmation for the same request returns a conflict instead of creating duplicate ledger effects. Note: If the `senderAddress` has not been seen before, Conto auto-creates an external wallet record for that address and links it to the agent's organization. That record still counts toward the organization's wallet limit, so approval can fail with `WALLET_LIMIT_REACHED` when the org is already at capacity. Note: The external-wallet `approve` flow accepts the same optional `context.invoice` object as `payments.request()` and stores the same typed invoice fields on the resulting `PaymentRequest`. Note: If an approval workflow matches, `/api/sdk/payments/approve` returns `requiresHumanApproval: true` and includes `approvalRequestId` in the response instead of issuing an `approvalToken`. After that workflow approves the payment, `POST /api/sdk/payments/{requestId}/confirm` can be called with just the final `txHash`. ### Response ```typescript interface PaymentRequestResult { requestId: string; // Use this to execute status: 'APPROVED' | 'DENIED' | 'REQUIRES_APPROVAL' | 'EXECUTED'; error?: string; // Present on some denied or verification-required responses code?: string; // Machine-readable denial or verification code idempotent?: boolean; // Present when a retry returns an existing request approvalRequestId?: string; // Present when the request is routed into an approval workflow // If approved or executed wallet?: { id: string; address: string; chainId: string; custodyType: string; availableBalance: number; }; walletSelectionReason?: string; expiresAt?: string; // ISO timestamp currency?: string; // e.g., "USDC", "USDT", "pathUSD" chain?: { chainId: string; chainName: string; chainType: string; explorerUrl?: string; }; // If executed (autoExecute was true) execution?: { transactionId: string; txHash: string; explorerUrl: string; status: string; }; // Always present reasons: string[]; // If denied - includes enriched context violations?: { type: string; limit: number; current: number; message: string; // Prefixed with source, e.g. "[Wallet limit]" or "[Policy: Name]" source?: 'wallet_limit' | 'policy_rule'; policyName?: string; // Present when source is "policy_rule" }[]; context?: { wallets?: Array<{ id: string; address: string; chainId: string; custodyType: string; balance: number; }>; nextSteps?: string[]; }; // If autoExecute failed autoExecuteError?: { error: string; code?: string }; } ``` Denied and verification-required responses include machine-readable `code` values when Conto can classify the stop reason, such as `BUDGET_EXCEEDED` for budget denials or `VERIFICATION_REQUIRED` for merchant identity step-up. Info: All payment responses now include `currency` (e.g., "USDC", "USDT", "USDC.e", or "pathUSD") and `chain` (with chainId, chainName, chainType, and explorerUrl) so agents know exactly which network and token the payment uses. Info: **Currency depends on chain:** The `currency` field reflects the stablecoin used on the wallet's blockchain. On Base, Ethereum, Arbitrum, and Polygon, both `USDC` and `USDT` are supported. On Tempo Testnet, it is `pathUSD`. On Tempo Mainnet, it is `USDC.e`. The amount is always denominated in the stablecoin configured for the payment. ### Idempotent Retries Use `idempotencyKey` when your caller may retry the same payment request because of network timeouts or uncertain client state. - Same `idempotencyKey` + same request payload: returns the original `requestId` with `idempotent: true` - Same `idempotencyKey` + different request payload: returns HTTP `409` with `code: "IDEMPOTENCY_CONFLICT"` - Different `idempotencyKey`: creates a new payment request ```typescript const request = await conto.payments.request({ amount: 100, recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...', purpose: 'Top up API credits', idempotencyKey: 'payment-req-2026-04-17-001', }); ``` ### Example ```typescript const request = await conto.payments.request({ amount: 50, recipientAddress: '0x...', purpose: 'API credits', }); switch (request.status) { case 'APPROVED': console.log('Payment approved'); console.log('Wallet:', request.wallet?.address); console.log('Expires:', request.expiresAt); break; case 'DENIED': console.log('Payment denied:', request.reasons); break; case 'REQUIRES_APPROVAL': console.log('Needs manual approval'); break; } ``` ## payments.execute() Execute an approved payment request. ```typescript const result = await conto.payments.execute(requestId); ``` Info: `payments.execute()` now delegates execution to Conto's shared payment execution service. The route still authenticates the SDK key, checks ownership, enforces rate limits, and requires `payments:execute`; custody dispatch, claim locking, spend-limit revalidation, retry accounting, provisional ledger effects, and confirmation-job dispatch all happen in the shared service used by Conto Pay and dashboard approval flows. ### Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | ---------------------------------- | | `requestId` | string | Yes | The requestId from payment request | ### Response ```typescript interface PaymentExecuteResult { transactionId: string; txHash: string; // Blockchain transaction hash (placeholder when simulated) status: 'COMPLETED' | 'CONFIRMING' | 'CONFIRMED' | 'FAILED'; simulated: boolean; // True when no onchain transfer happened amount: number; currency: string; // Stablecoin type recipient: string; recipientName?: string; wallet: { address: string; }; explorerUrl: string; // Block explorer link } ``` Info: Sandbox organizations always execute in simulated mode: the policy check, receipt, spend tracking, and audit log are real, no onchain transfer happens, and the response is finalized immediately with `status: 'COMPLETED'` and `simulated: true`. Real organizations execute onchain and return `status: 'CONFIRMING'` with `simulated: false` while chain confirmation is tracked in the background. ### Example ```typescript const request = await conto.payments.request({ amount: 50, recipientAddress: '0x...', }); if (request.status === 'APPROVED') { const result = await conto.payments.execute(request.requestId); console.log('Transaction hash:', result.txHash); console.log('Explorer:', result.explorerUrl); } ``` ## payments.pay() Convenience method that requests and executes in one call. ```typescript const result = await conto.payments.pay({ amount: 50, recipientAddress: '0x...', purpose: 'API credits', }); ``` ### Behavior - If **approved**: Executes immediately and returns result - If **denied**: Throws `ContoError` with code `PAYMENT_DENIED` - If **requires approval**: Throws `ContoError` with code `REQUIRES_APPROVAL` ### Example ```typescript try { const result = await conto.payments.pay({ amount: 50, recipientAddress: '0x...', purpose: 'API credits', }); console.log('Paid! TX:', result.txHash); } catch (error) { if (error.code === 'PAYMENT_DENIED') { console.log('Payment denied:', error.message); } else if (error.code === 'REQUIRES_APPROVAL') { console.log('Payment needs manual approval'); } } ``` ## autoExecute Flag The `autoExecute` flag lets you request authorization and execute the payment in a single API call, without needing a separate `execute()` call. Requires both `payments:request` and `payments:execute` scopes. The standard SDK key preset includes both. If a key lacks `payments:execute` (for example, a legacy custom-scoped key), the flag is silently ignored and the response is a normal APPROVED status that you must execute separately. ### How It Works - If **APPROVED** + `autoExecute: true`: Executes immediately, returns `status: "EXECUTED"` with `execution` object containing `txHash` - If **DENIED** or **REQUIRES_APPROVAL**: `autoExecute` is ignored, normal response returned - If execution **fails**: Returns `status: "APPROVED"` with `autoExecuteError` message and `executeUrl` for manual retry ### Example ```typescript // Single-call payment: request + execute const result = await fetch('/api/sdk/payments/request', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 50, recipientAddress: '0x...', recipientName: 'OpenAI', purpose: 'API credits', autoExecute: true }) }).then(r => r.json()); if (result.status === 'EXECUTED') { console.log('Payment complete!'); console.log('TX Hash:', result.execution.txHash); console.log('Explorer:', result.execution.explorerUrl); } else if (result.status === 'APPROVED' && result.autoExecuteError) { // Auto-execute failed, retry manually console.log('Auto-execute failed:', result.autoExecuteError.error); const execResult = await fetch(result.executeUrl, { method: 'POST', ... }); } ``` ## payments.status() Check the status of a payment request. ```typescript const status = await conto.payments.status(requestId); ``` ### Response ```typescript interface PaymentStatusResult { requestId: string; status: 'PENDING' | 'APPROVED' | 'DENIED' | 'COMPLETED' | 'EXPIRED'; policyResult: string; amount: number; currency: string; recipient: string; recipientName?: string; purpose?: string; category?: string; wallet?: { address: string }; requiresApproval: boolean; approvedAt?: string; deniedAt?: string; denialReason?: string; expiresAt?: string; createdAt: string; // If executed transaction?: { id: string; txHash: string; status: 'PENDING' | 'CONFIRMING' | 'CONFIRMED' | 'FAILED'; confirmedAt?: string; blockNumber?: number; }; } ``` ### Example: Polling for Confirmation ```typescript async function waitForConfirmation(requestId: string) { while (true) { const status = await conto.payments.status(requestId); if (status.transaction?.status === 'CONFIRMED') { console.log('Confirmed at block:', status.transaction.blockNumber); return status; } if (status.transaction?.status === 'FAILED') { throw new Error('Transaction failed'); } await new Promise((r) => setTimeout(r, 2000)); // Wait 2 seconds } } ``` ## Status Reference Payment requests and transactions use different status values: | Payment Request Status | Description | | ---------------------- | ------------------------------------------------------------------- | | `APPROVED` | Policies passed, ready to execute | | `DENIED` | Blocked by a policy or wallet limit | | `REQUIRES_APPROVAL` | Needs manual human approval | | `EXECUTED` | Auto-executed successfully (when `autoExecute: true`) | | `PENDING` | Awaiting human approval (maps to REQUIRES_APPROVAL in SDK response) | | `COMPLETED` | Payment fully confirmed onchain | | `EXPIRED` | Approval window elapsed without execution | | Transaction Status | Description | | ------------------ | -------------------------------------------------- | | `PENDING` | Transaction submitted, awaiting confirmation | | `EXECUTING` | Transaction is being processed | | `CONFIRMING` | Transaction broadcast, awaiting block confirmation | | `CONFIRMED` | Transaction confirmed onchain | | `FAILED` | Transaction failed | | `REJECTED` | Transaction rejected | | `CANCELLED` | Transaction cancelled before execution | | Policy Result | Description | | ------------------- | ------------------------------------------------ | | `ALLOWED` | All policies passed | | `DENIED` | At least one policy denied the payment | | `REQUIRES_APPROVAL` | Policies passed but approval threshold triggered | | `FLAGGED` | Payment flagged for review | | `PENDING` | Policy evaluation not yet complete | ## Categories Use standard categories for better analytics: | Category | Description | | ---------------- | ----------------------- | | `INFRASTRUCTURE` | Cloud, hosting, compute | | `AI_SERVICES` | AI APIs, model training | | `MARKETING` | Advertising, promotions | | `OPERATIONS` | General operations | | `VENDOR` | Vendor payments | | `EMPLOYEE` | Employee reimbursements | | `TESTING` | Test transactions | ## Urgency Levels | Level | Description | | ---------- | --------------------------- | | `LOW` | Can wait, batch if possible | | `NORMAL` | Standard priority (default) | | `HIGH` | Process quickly | | `CRITICAL` | Immediate processing | ## Best Practices Including purpose improves audit trails and analytics: ```typescript await conto.payments.pay({ amount: 100, recipientAddress: '0x...', purpose: 'AWS EC2 instance for training job #1234', // Specific category: 'INFRASTRUCTURE' }); ``` Approvals from `/request` expire after **5 minutes**. Approvals from `/approve` (external wallets) expire after **10 minutes**. Check expiration before executing: ```typescript const request = await conto.payments.request({ ... }); if (request.status === 'APPROVED') { const expiresAt = new Date(request.expiresAt!); if (expiresAt > new Date()) { await conto.payments.execute(request.requestId); } else { // Request a new approval const newRequest = await conto.payments.request({ ... }); } } ``` Use separate request/execute when you need to: - Validate before executing - Show user confirmation - Handle requires_approval status ```typescript const request = await conto.payments.request({ ... }); if (request.status === 'REQUIRES_APPROVAL') { // Store requestId, notify approvers await notifyApprovers(request.requestId); return { pending: true, requestId: request.requestId }; } if (request.status === 'APPROVED') { return conto.payments.execute(request.requestId); } ``` Use the context field for debugging info: ```typescript await conto.payments.pay({ amount: 100, recipientAddress: '0x...', purpose: 'API subscription', context: { jobId: '1234', userId: 'user_abc', environment: 'production' } }); ``` ## Next Steps ### Error Handling Link: https://conto.finance/docs/sdk/error-handling Handle payment errors gracefully ### Examples Link: https://conto.finance/docs/sdk/examples See complete integration examples --- # Budget Requests Budget requests let an agent ask for a spending budget that a human reviews and approves in the dashboard. Once approved, spend is tracked against the approved amount across **all payment types** (standard, x402, MPP, card). When the budget is exhausted, further payments are blocked. Info: Budget requests are **optional**. If no active budget exists for an agent, all payment flows work normally using existing spend limits and policies. When an active budget _does_ exist, both the budget and policies must pass for a payment to go through. ## How It Works ``` Agent Human (Dashboard) │ │ ├─ request_budget ──────────────────────> │ Sees request in Budgets tab │ (amount, purpose) │ │ │ ├─ get_budget_request ◄────────────────── │ Approves (optionally adjusts │ (polls for APPROVED) │ amount) or rejects │ │ ├─ Makes payments normally: │ │ • payments/request ──> budget check │ │ • x402/pre-authorize ──> budget check │ │ • mpp/pre-authorize ──> budget check │ │ • After execution ──> spend decremented │ │ │ └─ Budget exhausted → payments blocked │ Sees spend progress bar ``` ## Lifecycle A budget request moves through these states: | Status | Description | | ----------- | ------------------------------------------------------------------------------------- | | `PENDING` | Awaiting human review. Expires 24h after creation if not acted on. | | `APPROVED` | Human approved. Spend is tracked. Expires at a set time (default 24h after approval). | | `REJECTED` | Human rejected with an optional reason. | | `EXPIRED` | Timed out without approval, or approved budget window elapsed. | | `EXHAUSTED` | Approved budget fully spent (`currentSpend >= approvedAmount`). | **Constraints:** - One active (PENDING or APPROVED) budget request per agent at a time - Creating a new request while one is active returns `409 BUDGET_REQUEST_EXISTS` ## SDK API ### Create a Budget Request ```bash curl -X POST https://conto.finance/api/sdk/budget-request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 50, "purpose": "Research 200 companies via StableEnrich and generate reports", "category": "API_PROVIDER" }' ``` **Parameters:** | Parameter | Type | Required | Description | | ---------- | ------ | -------- | ------------------------------------------------------- | | `amount` | number | Yes | Requested budget in USDC | | `purpose` | string | Yes | What this budget is for (shown to the reviewer) | | `category` | string | No | Spend category (e.g., `API_PROVIDER`, `INFRASTRUCTURE`) | | `metadata` | object | No | Arbitrary context (JSON) | **Response (201):** ```json { "budgetRequestId": "cmm59z...", "status": "PENDING", "requestedAmount": 50.0, "purpose": "Research 200 companies via StableEnrich and generate reports", "category": "API_PROVIDER", "createdAt": "2026-04-07T12:00:00.000Z" } ``` **Error (409), active request already exists:** ```json { "error": "Agent already has an active budget request", "code": "BUDGET_REQUEST_EXISTS", "existingBudgetRequestId": "cmm58y..." } ``` ### Check Budget Request Status ```bash curl https://conto.finance/api/sdk/budget-request?status=APPROVED \ -H "Authorization: Bearer $CONTO_API_KEY" ``` **Query Parameters:** | Parameter | Type | Required | Description | | --------- | ------ | -------- | ----------------------------------------------------------------- | | `id` | string | No | Specific budget request ID | | `status` | string | No | Filter: `PENDING`, `APPROVED`, `REJECTED`, `EXPIRED`, `EXHAUSTED` | **Response (200):** ```json { "budgetRequests": [ { "id": "cmm59z...", "status": "APPROVED", "requestedAmount": 50.0, "approvedAmount": 25.0, "currentSpend": 12.5, "remainingBudget": 12.5, "purpose": "Research 200 companies via StableEnrich and generate reports", "category": "API_PROVIDER", "expiresAt": "2026-04-08T12:00:00.000Z", "createdAt": "2026-04-07T12:00:00.000Z" } ] } ``` ## MCP Tools ### request_budget Request a spending budget for payments. Submits a request for human approval. Only one active budget request per agent at a time. Applies to all payment types. | Parameter | Type | Required | Description | | ---------- | ------ | -------- | ------------------------------------------------------- | | `amount` | number | Yes | Requested budget in USDC | | `purpose` | string | Yes | What this budget is for (shown to reviewer) | | `category` | string | No | Spend category (e.g., `API_PROVIDER`, `INFRASTRUCTURE`) | | `metadata` | object | No | Additional context | ### get_budget_request Check status and remaining balance of your budget requests. Use to poll for approval and monitor remaining budget. | Parameter | Type | Required | Description | | ----------------- | ------ | -------- | ----------------------------------------------------------------- | | `budgetRequestId` | string | No | Specific request ID | | `status` | string | No | Filter: `PENDING`, `APPROVED`, `REJECTED`, `EXPIRED`, `EXHAUSTED` | ## Payment Flow Integration When an active (approved, non-expired) budget exists, every payment flow checks it automatically: **Pre-execution (blocking):** - `payments/request`: checks budget before policy evaluation - `payments/approve`: checks budget for external wallet payments - `x402/pre-authorize`: checks budget before authorizing x402 payments - `mpp/pre-authorize`: checks budget before authorizing MPP payments **Post-execution (decrement):** - `payments/execute`: decrements budget after successful execution - `x402/record`: decrements budget when recording x402 payments - `mpp/record`: decrements budget when recording MPP payments If a payment would exceed the remaining budget, it is denied with a `budgetRequest` object in the response: ```json { "authorized": false, "reasons": ["Payment of $30.00 exceeds remaining budget of $12.50"], "budgetRequest": { "id": "cmm59z...", "approvedAmount": 25.0, "currentSpend": 12.5, "remainingBudget": 12.5 } } ``` ## Dashboard Budget requests appear in the **Budgets** tab on the Alerts & Approvals page. **Pending requests** show: - Agent name, purpose, requested amount, category - Approve / Reject buttons - Optional amount adjustment field (approve a different amount than requested) **Approved requests** show: - Spend progress bar (currentSpend / approvedAmount) - Remaining balance and expiry countdown - Whether the amount was adjusted from the original request **Completed requests** (rejected, expired, exhausted) show their final state. ### Approving a Request ```bash curl -X POST https://conto.finance/api/budget-requests/{id}/decide \ -H "Authorization: Bearer $SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "decision": "APPROVED", "approvedAmount": 25.00, "expiresInHours": 48 }' ``` | Parameter | Type | Required | Description | | ---------------- | ------ | -------- | ---------------------------------------------- | | `decision` | string | Yes | `APPROVED` or `REJECTED` | | `approvedAmount` | number | No | Override amount (defaults to requested amount) | | `expiresInHours` | number | No | Budget window in hours (default: 24) | | `comment` | string | No | Optional note | ## Audit Trail Every state transition creates an audit log entry: | Transition | Action | Actor | | --------------------- | --------- | ------ | | Agent creates request | `CREATE` | Agent | | Human approves | `APPROVE` | User | | Human rejects | `REJECT` | User | | Spend recorded | `UPDATE` | Agent | | Budget exhausted | `UPDATE` | System | | Budget expired | `UPDATE` | System | ## Example: Agent Workflow ```typescript // 1. Request a budget const budget = await fetch('/api/sdk/budget-request', { method: 'POST', headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ amount: 50, purpose: 'Research 200 companies via paid APIs', category: 'API_PROVIDER', }), }).then((r) => r.json()); console.log('Budget request:', budget.budgetRequestId); // PENDING // 2. Poll for approval let approved = false; while (!approved) { const status = await fetch(`/api/sdk/budget-request?id=${budget.budgetRequestId}`, { headers: { Authorization: `Bearer ${apiKey}` }, }).then((r) => r.json()); const req = status.budgetRequests[0]; if (req.status === 'APPROVED') { console.log(`Approved: $${req.approvedAmount} budget`); approved = true; } else if (req.status === 'REJECTED' || req.status === 'EXPIRED') { throw new Error(`Budget ${req.status}`); } await new Promise((r) => setTimeout(r, 5000)); } // 3. Make payments normally, budget is enforced automatically await conto.payments.pay({ amount: 0.05, recipientAddress: '0x...', purpose: 'StableEnrich API call', }); // Budget decremented: $49.95 remaining ``` ## Next Steps ### Payments Link: https://conto.finance/docs/sdk/payments Standard payment request and execution ### x402 Payments Link: https://conto.finance/docs/sdk/x402-payments HTTP 402 micropayment handling ### Spend Limits Link: https://conto.finance/docs/policies/spend-limits Configure wallet spend limits ### MCP Tools Link: https://conto.finance/docs/mcp/tools Full MCP tools reference --- # Agent-to-Agent (A2A) Payments Conto supports direct payment requests between agents in the same organization. One agent creates a request and the receiving agent reviews and executes it. ## How It Works ```text Requesting agent -> creates request -> target agent reviews -> target agent executes ``` 1. Agent A calls `POST /api/sdk/a2a/request` 2. Agent B either receives a `payment_request.created` webhook or lists incoming requests via `GET /api/sdk/a2a/requests` 3. Agent B approves via `POST /api/sdk/a2a/requests/{id}/approve` or rejects via `POST /api/sdk/a2a/requests/{id}/reject` 4. Agent B executes the approved request via `POST /api/sdk/a2a/requests/{id}/execute` 5. The transfer still runs through Conto policy evaluation before settlement ## Create a Request You can target the receiving agent by `targetAgentId` or by `targetWalletAddress`. ```bash curl -X POST https://conto.finance/api/sdk/a2a/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "targetAgentId": "cmm5a0agt001m49h7bjqza22q", "amount": 50, "currency": "USDC", "purpose": "Reimbursement for API credits", "metadata": { "invoiceId": "INV-2026-001" } }' ``` **Response** ```json { "success": true, "paymentRequest": { "id": "cmm5h1a2a001m49h7irxzh22q", "status": "PENDING", "requestingAgentId": "cmm59z8fj000l49h7bjqza11p", "requestedFromAgentId": "cmm5a0agt001m49h7bjqza22q", "amount": 50, "currency": "USDC", "purpose": "Reimbursement for API credits" }, "message": "Payment request sent to DevOps Agent" } ``` Info: If you pass `targetWalletAddress`, Conto resolves it to a registered agent first. Requests to unknown addresses are rejected. ## List Requests ```bash GET /api/sdk/a2a/requests ``` Use this endpoint to view both incoming and outgoing requests for the authenticated agent. ## Webhook-First Automation If the requested-from agent has a webhook or callback URL configured, Conto also emits `payment_request.created` as soon as a new request is created. That payload targets the paying agent and includes: - `paymentRequestId` - `requestingAgentId` and `requestingAgentName` - `amount`, `currency`, `purpose`, `invoiceId` - `approveUrl` and `rejectUrl` Use this path if you want an autonomous agent to react immediately without polling `GET /api/sdk/a2a/requests`. ## Approve or Reject a Request The paying agent can explicitly approve a pending request before execution: ```bash curl -X POST https://conto.finance/api/sdk/a2a/requests/{id}/approve \ -H "Authorization: Bearer $CONTO_API_KEY" ``` To reject it, call the reject endpoint. You can include an optional `reason` that is stored with the request. ```bash curl -X POST https://conto.finance/api/sdk/a2a/requests/{id}/reject \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "reason": "This invoice is missing the deployment reference" }' ``` ## Execute a Request The receiving agent executes the request: ```bash curl -X POST https://conto.finance/api/sdk/a2a/requests/{id}/execute \ -H "Authorization: Bearer $CONTO_API_KEY" ``` Spend limits, approval rules, counterparty rules, and other policies still apply. ## Resolve an Agent from a Wallet Address ```bash curl -X POST https://conto.finance/api/sdk/a2a/resolve \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "address": "0x1234567890abcdef..." }' ``` ## A2A Statistics ```bash GET /api/sdk/a2a/stats ``` ## API Reference | Endpoint | Method | Description | | ------------------------------------ | ------ | -------------------------------------- | | `/api/sdk/a2a/request` | POST | Create an A2A payment request | | `/api/sdk/a2a/requests` | GET | List A2A requests | | `/api/sdk/a2a/requests/{id}` | GET | Get one request | | `/api/sdk/a2a/requests/{id}/approve` | POST | Approve a pending request | | `/api/sdk/a2a/requests/{id}/reject` | POST | Reject a pending request | | `/api/sdk/a2a/requests/{id}/execute` | POST | Execute an approved request | | `/api/sdk/a2a/resolve` | POST | Resolve an agent from a wallet address | | `/api/sdk/a2a/stats` | GET | View A2A statistics | --- # Card Payments Conto supports connecting existing payment cards to the policy engine, giving you spend limits, merchant controls, time windows, and MCC-based restrictions for agent card usage. Info: Issuing new cards directly through Conto is not yet generally available. Today, you can connect any existing card manually and enforce policies through the SDK approve/confirm flow. ## Connecting a Card Register an existing card by providing its last 4 digits, brand, and spend limits. Card management routes currently use the signed-in dashboard session; they do not accept agent SDK keys. Set `CONTO_DASHBOARD_COOKIE` to the full Cookie header from a signed-in dashboard request. ```bash curl -X POST https://conto.finance/api/cards \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "provider": "MANUAL", "name": "Marketing Card", "last4": "4242", "brand": "VISA", "cardType": "VIRTUAL", "spendLimitDaily": 1000, "spendLimitPerTx": 500 }' ``` **Response:** ```json { "card": { "id": "cmm5e0crd000l49h7fouwe11p", "name": "Marketing Card", "provider": "MANUAL", "last4": "4242", "brand": "VISA", "status": "ACTIVE" } } ``` You can also create cards from the dashboard at **Cards > Create Card**. ## Assigning Cards to Agents After connecting a card, assign it to an agent with per-agent limits: ```bash curl -X POST https://conto.finance/api/agents/{agentId}/cards \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" \ -H "Content-Type: application/json" \ -d '{ "cardId": "cmm5e0crd000l49h7fouwe11p", "spendLimitPerTx": 250, "spendLimitDaily": 500, "allowedDays": ["Mon", "Tue", "Wed", "Thu", "Fri"], "allowedHoursStart": 9, "allowedHoursEnd": 17, "blockedCategories": ["7995"] }' ``` Agent-level limits cannot exceed card-level limits. One card can be assigned to multiple agents, each with their own spend controls. ## Card State Management Pause, resume, or cancel cards from the dashboard or API: ```bash # Pause a card curl -X PATCH https://conto.finance/api/cards/{cardId}/state \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" \ -d '{ "state": "PAUSED" }' # Resume a card curl -X PATCH https://conto.finance/api/cards/{cardId}/state \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" \ -d '{ "state": "ACTIVE" }' # Cancel a card (deactivates all agent links) curl -X PATCH https://conto.finance/api/cards/{cardId}/state \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" \ -d '{ "state": "CANCELLED" }' ``` ## Linking Policies to Cards Beyond the per-agent field-based limits, you can link named policies to cards. This uses the same `Policy` / `PolicyRule` framework as wallets and agents. ```bash # Link a policy to a card curl -X POST https://conto.finance/api/cards/{cardId}/policies \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" \ -d '{ "policyId": "cmm5c0pol000l49h7dmsuc11p" }' # List linked policies curl https://conto.finance/api/cards/{cardId}/policies \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" # Unlink a policy curl -X DELETE https://conto.finance/api/cards/{cardId}/policies/{policyId} \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" ``` Card policies support all standard rule types plus card-specific ones: | Rule Type | Description | | ------------------------ | ----------------------------------- | | `CARD_ALLOWED_MCCS` | Whitelist merchant category codes | | `CARD_BLOCKED_MCCS` | Blocklist merchant category codes | | `CARD_ALLOWED_MERCHANTS` | Whitelist merchant names/IDs | | `CARD_BLOCKED_MERCHANTS` | Blocklist merchant names/IDs | | `CARD_MAX_AMOUNT` | Per-card transaction amount ceiling | See [Advanced Policies](https://conto.finance/docs/policies/advanced#card-payment-rules) for value formats. ## Policy Enforcement Card payments are evaluated through two layers: ### Layer 1: Agent-Card Limits Field-based limits set when assigning a card to an agent: - Per-transaction, daily, weekly, monthly spend limits - Time windows (allowed days and hours) - MCC category allow/block lists - Merchant allow/block lists ### Layer 2: Policy Rule Engine Database-defined policies linked to the card or agent: - All standard rule types (velocity, geographic, approval thresholds) - Card-specific MCC and merchant rules - Priority-ordered evaluation with AND logic Both layers run together. The first violation from either layer denies the payment. ## SDK Approve/Confirm Flow Agents use the approve/confirm pattern before charging a connected card: Agent calls `POST /api/sdk/cards/approve` before charging the card. ```bash curl -X POST https://conto.finance/api/sdk/cards/approve \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "cardId": "cmm5e0crd000l49h7fouwe11p", "amount": 99.99, "merchantName": "AWS", "merchantCategory": "5734", "purpose": "EC2 instance charges" }' ``` Conto evaluates both policy layers and returns an approval token (valid 5 minutes). ```json { "approved": true, "requestId": "cmm5e1crq001m49h7fouwe22q", "approvalToken": "a1b2c3...", "expiresAt": "2026-06-15T10:05:00Z", "card": { "last4": "4242", "brand": "VISA" }, "limits": { "remainingDaily": 400.01, "remainingPerTx": 500 } } ``` Agent processes the card charge through its own payment integration. Agent calls `POST /api/sdk/cards/{requestId}/confirm` with the transaction reference. ```bash curl -X POST https://conto.finance/api/sdk/cards/cmm5e1crq001m49h7fouwe22q/confirm \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "approvalToken": "a1b2c3...", "externalTxId": "ch_1234567890", "authorizationCode": "A1B2C3", "actualAmount": 99.99 }' ``` You can also include `merchantDetails` if the card processor returns the settled merchant name, MCC, or location after authorization. ## API Reference | Endpoint | Method | Auth | Description | | ------------------------------------- | ------ | ---- | --------------------------- | | `/api/cards` | GET | Dashboard session | List all cards | | `/api/cards` | POST | Dashboard session | Connect a card (manual) | | `/api/cards/{id}` | GET | Dashboard session | Card details | | `/api/cards/{id}` | PATCH | Dashboard session | Update card limits/settings | | `/api/cards/{id}/state` | PATCH | Dashboard session | Change card state | | `/api/cards/{id}/policies` | GET | Dashboard session | List linked policies | | `/api/cards/{id}/policies` | POST | Dashboard session | Link a policy | | `/api/cards/{id}/policies/{policyId}` | DELETE | Dashboard session | Unlink a policy | | `/api/agents/{id}/cards` | GET | Dashboard session | List agent's cards | | `/api/agents/{id}/cards` | POST | Dashboard session | Assign card to agent | | `/api/sdk/cards/approve` | POST | Agent SDK key | SDK: request card approval | | `/api/sdk/cards/{id}/confirm` | POST | Agent SDK key | SDK: confirm card payment | ## Card Alert Types Card transactions are monitored for anomalies after each confirmed payment. These alerts are created automatically: | Alert Type | Severity | Trigger | | ---------------------- | ----------- | ------------------------------------------------------------------------------------------- | | `CARD_SPEND_VELOCITY` | MEDIUM/HIGH | Current hour spend exceeds 3x the 30-day hourly average | | `CARD_LARGE_TX` | MEDIUM/HIGH | Single transaction exceeds 3x the 30-day per-transaction average. HIGH if ratio exceeds 10x | | `CARD_NEW_MERCHANT` | LOW | First transaction with a given merchant | | `CARD_RAPID_SWITCHING` | MEDIUM/HIGH | More than 5 distinct merchants within 60 minutes. HIGH if more than 10 | | `CARD_DAILY_BURN` | MEDIUM/HIGH | Daily spend exceeds 80% of daily limit. HIGH if exceeds 95% | Info: Card alerts require sufficient transaction history for statistical detection. `CARD_SPEND_VELOCITY` needs at least 5 days of history and 10 prior transactions. `CARD_LARGE_TX` needs at least 10 prior transactions. ## Next Steps ### Card Management Guide Link: https://conto.finance/docs/guides/card-management Dashboard walkthrough for managing cards ### Advanced Policies Link: https://conto.finance/docs/policies/advanced#card-payment-rules Card-specific policy rule types ### Standard Payments Link: https://conto.finance/docs/sdk/payments Stablecoin payment flow ### Spend Limits Link: https://conto.finance/docs/policies/spend-limits Configure spending controls --- # x402 Protocol Payments Conto integrates with the [x402 protocol](https://www.x402.org/) to let AI agents pay for HTTP APIs that return `402 Payment Required`. Conto acts as a policy layer between your agent and the x402 facilitator. ## How It Works ``` Agent calls API → Gets 402 response → Conto pre-authorizes → Agent pays & retries ``` 1. Agent sends a request to an x402-enabled API 2. API returns HTTP 402 with payment details (amount, recipient, facilitator) 3. Agent calls Conto to pre-authorize the payment against policies 4. If approved, agent signs the payment and retries the API call 5. Agent records the transaction in Conto for tracking ## Pre-Authorization Before making an x402 payment, check it against your policies and budget limits: ```bash curl -X POST https://conto.finance/api/sdk/x402/pre-authorize \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 0.05, "recipientAddress": "0xFacilitatorAddress", "resourceUrl": "https://api.example.com/data", "sessionId": "x402_session_xyz", "facilitator": "0xFacilitatorAddress", "scheme": "exact" }' ``` Conto derives `serviceDomain` from `resourceUrl`, so you do not need to send it separately. **Response (Approved):** ```json { "authorized": true, "wallet": { "id": "cmm5b0wal000l49h7ckrtb11p", "address": "0xAgentWallet", "chainId": "8453", "availableBalance": 500.0 }, "reasons": ["Within x402 service budget", "Service domain allowed"] } ``` **Response (Denied):** ```json { "authorized": false, "error": "X402 pre-authorization denied", "code": "BUDGET_EXCEEDED", "reasons": ["X402 price ceiling exceeded: $0.05 > $0.01 max"], "violations": [ { "type": "X402_PRICE_CEILING", "limit": 0.01, "current": 0.05, "message": "Amount exceeds x402 price ceiling" } ] } ``` ## Recording Transactions After the x402 payment is executed onchain, record it in Conto: ```bash curl -X POST https://conto.finance/api/sdk/x402/record \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 0.05, "recipientAddress": "0xFacilitatorAddress", "txHash": "0xabc123...", "resourceUrl": "https://api.example.com/data", "sessionId": "x402_session_xyz", "facilitator": "0xFacilitatorAddress", "scheme": "exact", "walletId": "cmm5b0wal000l49h7ckrtb11p", "chainId": "8453" }' ``` ### Batch Recording For high-frequency micropayments, batch multiple records: ```bash curl -X POST https://conto.finance/api/sdk/x402/record \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 0.03, "recipientAddress": "0xFacilitatorAddress", "txHash": "0xsettlement123...", "resourceUrl": "https://api.example.com/batch", "sessionId": "x402_session_xyz", "batchItems": [ { "amount": 0.01, "resourceUrl": "https://api.example.com/v1", "paymentId": "pay_1", "responseCode": 200 }, { "amount": 0.02, "resourceUrl": "https://api.example.com/v2", "paymentId": "pay_2", "responseCode": 200 } ] }' ``` Use the flat top-level settlement fields shown above. For multiple micropayments, put the per-call details in `batchItems`; the record endpoint does not accept a top-level `payments` array. ## Querying Services View which x402 services your agent has used: ```bash GET /api/sdk/x402/services ``` ## Budget Tracking Check remaining budget and burn rate: ```bash GET /api/sdk/x402/budget ``` Pass `?sessionId=...` when you want the burn-rate and remaining-budget view scoped to a specific x402 session. Session spend is counted from recorded x402 transactions with the same `sessionId`, so generic payments do not reduce the protocol session budget. If an agent has an active approved budget request, `/pre-authorize` returns a `budgetRequest` snapshot and `/record` decrements the remaining budget automatically. ## Unified Machine Spend View If this agent also uses MPP or multiple paid services, use the shared machine-spend endpoints for a combined view: ```bash GET /api/sdk/service-spend/summary?protocol=x402 GET /api/sdk/service-spend/services?protocol=x402 ``` See [Machine Spend](https://conto.finance/docs/sdk/machine-spend) for the combined x402 + MPP analytics view. ## x402 Policy Rules Configure x402-specific policies to control micropayment behavior. The complete list of x402 rule types, value formats, and operators lives in [Advanced Policies > x402 Protocol Rules](https://conto.finance/docs/policies/advanced#x402-protocol-rules). ## Anomaly Detection Conto automatically monitors x402 spending patterns and creates alerts for: | Alert | Trigger | |-------|---------| | **Price Spike** | API suddenly charging more than usual | | **High Frequency** | Unusual burst of API calls | | **New Service** | Agent paying an API for the first time | | **Budget Burn** | Approaching per-service budget limit | | **Duplicate Payment** | Same amount + endpoint in quick succession | | **Failed Streak** | Repeated authorization failures | Configure alert thresholds in **Alerts** in the dashboard. ## Next Steps ### Advanced Policies Link: https://conto.finance/docs/policies/advanced Configure x402-specific policy rules ### Machine Spend Link: https://conto.finance/docs/sdk/machine-spend View unified x402 and MPP service spend ### Error Handling Link: https://conto.finance/docs/sdk/error-handling Handle x402 authorization errors --- # MPP (Machine Payment Protocol) Payments Conto supports the Machine Payment Protocol (MPP) for session-based micropayments on the Tempo blockchain. MPP enables agents to open payment sessions, make incremental charges, and settle when done. ## How It Works ``` Agent opens session → Makes requests (charges accrue) → Session closes → Settlement ``` 1. Agent calls an MPP-enabled service and receives a 402 challenge 2. Agent pre-authorizes the session deposit through Conto policies 3. Agent opens an MPP session with a deposit budget 4. Agent makes requests, each consuming part of the deposit 5. Session closes and unused deposit is returned ## Pre-Authorization Before opening an MPP session, validate against policies and budget limits: ```bash curl -X POST https://conto.finance/api/sdk/mpp/pre-authorize \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 10.00, "recipientAddress": "0xServiceAddress", "resourceUrl": "https://api.service.com/stream", "intent": "session", "depositAmount": 10.00 }' ``` Conto derives `serviceDomain` from `resourceUrl`, so you do not need to send it separately. **Response (Approved):** ```json { "authorized": true, "wallet": { "id": "cmm5b0wal000l49h7ckrtb11p", "address": "0xAgentWallet", "chainId": "42431", "availableBalance": 500.0 }, "reasons": ["Within MPP session budget", "Service domain allowed"] } ``` **Response (Denied):** ```json { "authorized": false, "error": "MPP pre-authorization denied", "code": "BUDGET_EXCEEDED", "reasons": ["MPP session deposit $10 exceeds maximum $5"], "violations": [ { "type": "MPP_MAX_SESSION_DEPOSIT", "limit": 5.00, "current": 10.00, "message": "Session deposit exceeds MPP budget" } ] } ``` ## Recording Transactions After MPP charges are settled, record them in Conto: ```bash curl -X POST https://conto.finance/api/sdk/mpp/record \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 3.50, "recipientAddress": "0xServiceAddress", "txHash": "0xabc123...", "resourceUrl": "https://api.service.com/stream", "sessionId": "mpp_session_xyz", "scheme": "mpp", "walletId": "cmm5b0wal000l49h7ckrtb11p", "chainId": "42431" }' ``` Use the flat top-level settlement fields for the aggregate payment. For multiple per-call charges, send those details in `batchItems`; the record endpoint does not accept a top-level `payments` array. If you settle multiple calls together, keep the top-level fields for the aggregate settlement and send per-call detail records in `batchItems`: ```bash curl -X POST https://conto.finance/api/sdk/mpp/record \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 3.50, "recipientAddress": "0xServiceAddress", "txHash": "0xsettlement123...", "resourceUrl": "https://api.service.com/stream", "sessionId": "mpp_session_xyz", "batchItems": [ { "amount": 1.00, "resourceUrl": "https://api.service.com/stream?chunk=1", "credentialId": "cred_1" }, { "amount": 2.50, "resourceUrl": "https://api.service.com/stream?chunk=2", "credentialId": "cred_2" } ] }' ``` ## Querying Services View MPP services your agent has used: ```bash GET /api/sdk/mpp/services ``` ## Budget Tracking Check remaining MPP budget: ```bash GET /api/sdk/mpp/budget ``` Pass `?sessionId=...` to inspect budget consumption for a specific MPP session. Session spend is counted from recorded MPP transactions with the same `sessionId`, not from unrelated wallet payments. If an agent has an active approved budget request, `/pre-authorize` returns a `budgetRequest` snapshot and `/record` decrements the remaining budget automatically. ## Unified Machine Spend View If this agent also uses x402 or multiple paid services, use the shared machine-spend endpoints for a combined view: ```bash GET /api/sdk/service-spend/summary?protocol=mpp GET /api/sdk/service-spend/services?protocol=mpp ``` See [Machine Spend](https://conto.finance/docs/sdk/machine-spend) for the combined x402 + MPP analytics view. ## MPP Policy Rules Configure MPP-specific policies to control session-based payments. The complete list of MPP rule types, value formats, and operators lives in [Advanced Policies > MPP Protocol Rules](https://conto.finance/docs/policies/advanced#mpp-protocol-rules). ## Supported Chain MPP payments are supported on the **Tempo** blockchain, on both testnet and mainnet. The examples in this guide use Tempo Testnet. | Property | Tempo Testnet | Tempo Mainnet | | -------- | ------------------------------------ | --------------------------- | | Chain ID | `42431` | `4217` | | Currency | `pathUSD` | `USDC.e` | | Explorer | `https://explore.moderato.tempo.xyz` | `https://explore.tempo.xyz` | ## Next Steps ### x402 Payments Link: https://conto.finance/docs/sdk/x402-payments HTTP 402 micropayments for APIs ### Machine Spend Link: https://conto.finance/docs/sdk/machine-spend View unified x402 and MPP service spend ### Advanced Policies Link: https://conto.finance/docs/policies/advanced Configure MPP-specific policy rules --- # Machine Spend Machine Spend gives you a unified read layer over paid service usage recorded through Conto's x402 and MPP flows. Use it to answer questions like: - Which paid services is this agent using most? - Which endpoints are driving the most spend? - Is spend concentrated in x402, MPP, or both? - Are there active x402 or MPP anomaly alerts for this agent? Info: Machine Spend is additive to existing x402 and MPP tracking. It does not replace protocol-specific endpoints like `/api/sdk/x402/services` or `/api/sdk/mpp/budget`; it gives you one combined view on top of them. ## What It Includes The machine-spend endpoints aggregate existing `A2S` transactions and protocol alerts into a shared view: - total spend and call volume - service-level breakdowns - endpoint-level breakdowns - x402 vs MPP split - micropayment counts - recent x402 / MPP anomaly alerts This is especially useful when one agent uses multiple paid APIs across both protocols. ## Authentication These endpoints use the normal **agent SDK key** flow: ```bash Authorization: Bearer conto_agent_xxx ``` Required scope: - `analytics:read` ## Get a Summary Returns a top-level summary plus recent machine-spend alerts for the authenticated agent. ```bash curl "https://conto.finance/api/sdk/service-spend/summary?period=30d&protocol=all" \ -H "Authorization: Bearer $CONTO_API_KEY" ``` ### Query Parameters | Parameter | Type | Default | Description | | ---------- | ------ | ------- | --------------------------------- | | `period` | string | `30d` | One of `24h`, `7d`, `30d`, `all` | | `protocol` | string | `all` | One of `all`, `x402`, `mpp` | | `limit` | number | `10` | Number of recent alerts to return | ### Example Response ```json { "filters": { "period": "30d", "protocol": "all", "agentId": "cmm5a1agt002n49h7bjqza33r", "startDate": "2026-03-18T00:00:00.000Z" }, "summary": { "totalSpend": 14.73, "totalCalls": 219, "activeServices": 6, "activeAgents": 1, "activeAlerts": 1, "micropaymentTransactions": 188, "x402Spend": 4.12, "x402Calls": 173, "mppSpend": 10.61, "mppCalls": 46 }, "recentAlerts": [ { "id": "cmm5j0alr000l49h7ktzbj11p", "protocol": "x402", "alertType": "X402_PRICE_SPIKE", "severity": "MEDIUM", "status": "ACTIVE", "title": "x402 price spike: api.example.com", "message": "api.example.com is charging more than its historical average", "createdAt": "2026-04-16T19:02:11.000Z", "organizationName": "Acme", "agentName": "research-agent" } ] } ``` ## List Services And Endpoints Returns the top service domains and endpoints for the authenticated agent. ```bash curl "https://conto.finance/api/sdk/service-spend/services?period=7d&protocol=x402&limit=20" \ -H "Authorization: Bearer $CONTO_API_KEY" ``` ### Query Parameters | Parameter | Type | Default | Description | | ---------- | ------ | ------- | ---------------------------------------- | | `period` | string | `30d` | One of `24h`, `7d`, `30d`, `all` | | `protocol` | string | `all` | One of `all`, `x402`, `mpp` | | `limit` | number | `10` | Number of services / endpoints to return | ### Example Response ```json { "filters": { "period": "7d", "protocol": "x402", "agentId": "cmm5a1agt002n49h7bjqza33r", "startDate": "2026-04-10T00:00:00.000Z" }, "services": [ { "protocol": "x402", "serviceDomain": "api.example.com", "totalSpend": 2.41, "totalCalls": 120, "avgPricePerCall": 0.0201, "minPricePerCall": 0.01, "maxPricePerCall": 0.05, "firstActivityAt": "2026-04-11T03:44:52.000Z", "lastActivityAt": "2026-04-16T21:08:17.000Z" } ], "endpoints": [ { "protocol": "x402", "resourceUrl": "https://api.example.com/search", "serviceDomain": "api.example.com", "totalSpend": 1.84, "totalCalls": 92, "avgPricePerCall": 0.02, "lastActivityAt": "2026-04-16T21:08:17.000Z" } ] } ``` ## When To Use Machine Spend vs Protocol-Specific Endpoints Use **Machine Spend** when you want a unified service view across both protocols. Use **protocol-specific endpoints** when you need details unique to one rail: - `/api/sdk/x402/services` for x402 service-specific stats - `/api/sdk/x402/budget` for x402 burn rate and policy limit views - `/api/sdk/mpp/services` for MPP service-specific stats - `/api/sdk/mpp/budget` for MPP session and budget views ## Dashboard View Conto also exposes this data in the dashboard, where you can: - filter by protocol and time window - compare top services and endpoints - inspect top agents and organizations - review recent x402 / MPP anomaly alerts ## Next Steps ### x402 Payments Link: https://conto.finance/docs/sdk/x402-payments Record and control pay-per-call API spend ### MPP Payments Link: https://conto.finance/docs/sdk/mpp-payments Track session-based micropayment usage --- # Error Handling The Conto SDK provides detailed error information to help you handle failures gracefully. ## ContoError Type All SDK errors include `code` and `status` properties alongside the standard `Error` fields: ```typescript interface ContoError extends Error { code: string; // Error code (e.g., 'PAYMENT_DENIED') status: number; // HTTP status code message: string; // Human-readable message } ``` `ContoError` is a TypeScript interface, not a class. The SDK attaches `code` and `status` to standard `Error` objects. Use property checks (`'code' in error`) instead of `instanceof` to detect SDK errors. ## Error Codes ### Authentication Errors | Code | Status | Description | Solution | |------|--------|-------------|----------| | `AUTH_FAILED` | 401 | Missing, invalid, inactive, revoked, or expired API key | Check key is correct and active | | `INSUFFICIENT_SCOPE` | 403 | Key lacks required permission | Use key with required scope | ### Payment Errors | Code | Status | Description | Solution | |------|--------|-------------|----------| | `PAYMENT_DENIED` | 403 | SDK `pay()` helper saw a denied request | Inspect the request response's `reasons` and `violations` | | `REQUIRES_APPROVAL` | 202 | SDK `pay()` helper saw an approval-required request | Wait for human approval | | `INSUFFICIENT_BALANCE` | 400 | Wallet has insufficient funds | Fund the wallet | | `EXPIRED` | 400 | Payment request expired | Request new approval | | `NOT_FOUND` | 404 | Request ID not found | Check the request ID | | `INVALID_STATUS` | 400 | Cannot execute in current status | Check payment status | | `NO_WALLET` | 400 | No wallet assigned | Link a wallet to the agent | | `LIMIT_EXCEEDED` | 400 | Spend limit or balance re-check failed at execution time | Re-request after reducing amount or freeing budget | | `WALLET_CONFIG_ERROR` | 400 | Wallet is misconfigured (e.g. missing custody provider) | Contact your admin | | `CUSTODY_NOT_CONFIGURED` | 503 | The custody provider is not configured on the server | Contact support | | `MANUAL_EXECUTION_REQUIRED` | 400 | External or smart contract wallets cannot be auto-executed | Use the approve/confirm flow instead | | `ALREADY_EXECUTED` | 409 | This payment request was already executed | Check transaction status instead | ### Validation Errors | Code | Status | Description | Solution | |------|--------|-------------|----------| | `VALIDATION_ERROR` | 400 | Invalid request body | Check request parameters | | `INVALID_AMOUNT` | 400 | Amount must be positive | Use a positive number | | `INVALID_ADDRESS` | 400 | Malformed wallet address | Use valid 0x address (EVM) or base58 address (Solana) | | `INVALID_JSON` | 400 | Malformed request body | Send valid JSON | ### System Errors | Code | Status | Description | Solution | |------|--------|-------------|----------| | `RATE_LIMITED` | 429 | Too many requests | Wait and retry | | `TIMEOUT` | 0 | Request timeout | Retry with longer timeout | | `INTERNAL_ERROR` | 500 | Server error | Retry or contact support | ## Handling Errors ### Basic Error Handling ```typescript import { Conto } from '@conto_finance/sdk'; import type { ContoError } from '@conto_finance/sdk'; try { const result = await conto.payments.pay({ amount: 100, recipientAddress: '0x...' }); } catch (error) { if (error instanceof Error && 'code' in error) { const sdkError = error as ContoError; console.error(`Error [${sdkError.code}]:`, sdkError.message); console.error('HTTP Status:', sdkError.status); } else { console.error('Unexpected error:', error); } } ``` ### Handling Specific Error Codes ```typescript try { await conto.payments.pay({ ... }); } catch (error) { if (error instanceof Error && 'code' in error) { switch (error.code) { case 'PAYMENT_DENIED': console.log('Payment was denied by policy'); // Check why it was denied break; case 'REQUIRES_APPROVAL': console.log('Payment needs human approval'); // Notify approvers break; case 'INSUFFICIENT_BALANCE': console.log('Wallet needs funding'); // Alert treasury team break; case 'LIMIT_EXCEEDED': console.log('Limit or balance changed before execution'); // Re-check setup and request a smaller payment break; case 'RATE_LIMITED': console.log('Too many requests. The SDK already retried automatically before throwing.'); // Back off before issuing more requests. break; default: console.error('Unhandled error:', error.code); } } } ``` ## Enriched Denial And Error Responses Some SDK responses include additional context to help agents recover programmatically. Policy denials from `POST /api/sdk/payments/request` are normal `200` responses with `status: "DENIED"`, plus `hint`, `context`, and `nextSteps` fields. Execution failures are non-2xx error responses with an `error` and `code`. ### Denial Response Structure ```typescript interface EnrichedDenial { requestId: string; status: 'DENIED'; reasons: string[]; violations?: object[]; hint?: string; context?: { wallets?: Array<{ id: string; address: string; chainId: string; custodyType: string; balance: number; }>; nextSteps?: string[]; }; } ``` ### Example: Manual Execution Required When trying to `/execute` a payment assigned to an external wallet: ```json { "error": "EXTERNAL wallets require manual execution. Execute the transfer from your custody provider and confirm with a txHash.", "code": "MANUAL_EXECUTION_REQUIRED" } ``` ### Example: Policy Denial With Recovery Context ```json { "requestId": "cmm...", "status": "DENIED", "reasons": ["Would exceed daily limit"], "hint": "Review the violations below. You may need to request a policy exception or adjust the payment parameters.", "context": { "nextSteps": [ "Reduce the payment amount", "Request a policy exception", "Use GET /api/sdk/setup to check current balances" ] } } ``` ### Handling Enriched Errors ```typescript const response = await fetch(`/api/sdk/payments/${id}/execute`, { method: 'POST', headers: { Authorization: `Bearer ${process.env.CONTO_API_KEY}` }, }); const body = await response.json(); if (!response.ok) { if (body.code === 'MANUAL_EXECUTION_REQUIRED') { // Execute with your own wallet and confirm with txHash. console.log('Use approve/confirm for this wallet'); } if (body.context?.nextSteps) { console.log('Suggested actions:', body.context.nextSteps); } throw new Error(body.error || 'Payment execution failed'); } ``` ### Using Request and Execute for Better Control The `pay()` method throws on denial. For more control, use separate request/execute: ```typescript // Request first (never throws for denied payments) const request = await conto.payments.request({ amount: 100, recipientAddress: '0x...' }); if (request.status === 'DENIED') { console.log('Denied reasons:', request.reasons); console.log('Violations:', request.violations); return null; } if (request.status === 'REQUIRES_APPROVAL') { console.log('Awaiting approval...'); return { pending: true, requestId: request.requestId }; } // Only execute if approved try { return await conto.payments.execute(request.requestId); } catch (error) { // Handle execution errors if (error.code === 'INSUFFICIENT_BALANCE') { // Balance changed between request and execute } } ``` ## Handling Rate Limits The SDK already handles rate limits for you before throwing (see [Retry Strategy](#retry-strategy) below for the exact behavior). `retryAfter` is consumed internally and is not exposed on the thrown error, so do not read `error.retryAfter`. If you need an additional application-level retry after the SDK has exhausted its own, wrap the call and back off on your own schedule: ```typescript async function payWithRetry(params: PaymentRequestInput) { const maxRetries = 3; for (let i = 0; i < maxRetries; i++) { try { return await conto.payments.pay(params); } catch (error) { const isRateLimited = error instanceof Error && 'code' in error && error.code === 'RATE_LIMITED'; if (isRateLimited && i < maxRetries - 1) { const waitTime = 2 ** i; // 1s, 2s, 4s console.log(`Still rate limited. Waiting ${waitTime}s...`); await new Promise((r) => setTimeout(r, waitTime * 1000)); continue; } throw error; } } } ``` ## Handling Timeouts For long-running requests, handle timeouts: ```typescript const conto = new Conto({ apiKey: process.env.CONTO_API_KEY!, timeout: 60000 // 60 seconds }); try { await conto.payments.pay({ ... }); } catch (error) { if (error.code === 'TIMEOUT') { console.log('Request timed out'); // Don't automatically retry payments - check status first! const status = await conto.payments.status(requestId); if (status.transaction) { console.log('Payment was actually submitted:', status.transaction.txHash); } } } ``` ## Retry Strategy ### Built-in Automatic Retry The SDK automatically retries transient failures with exponential backoff. You don't need to implement retry logic yourself for most cases. **Built-in behavior:** - Retries up to **3 times** on `429` (rate limited) and `5xx` (server errors) - Respects `Retry-After` headers from the server - Exponential backoff: 1s → 2s → 4s (capped at 10s) - **Does not retry** client errors (`4xx` except `429`) or auth failures ```typescript // The SDK handles retries automatically, just call the method const result = await conto.payments.pay({ amount: 100, recipientAddress: '0x...' }); // If the server returns 429 or 503, the SDK waits and retries automatically ``` ### Custom Retry for Application Logic For application-level retry logic (e.g., re-requesting after a denial), use a custom wrapper: ```typescript async function withRetry ( fn: () => Promise , maxRetries = 3, baseDelay = 1000 ): Promise { let lastError: Error; for (let i = 0; i < maxRetries; i++) { try { return await fn(); } catch (error) { lastError = error; // Don't retry certain errors if (error instanceof Error && 'code' in error) { const sdkError = error as ContoError; if (['AUTH_FAILED', 'PAYMENT_DENIED', 'VALIDATION_ERROR'].includes(sdkError.code)) { throw error; // Non-retryable } if (sdkError.code === 'RATE_LIMITED') { const delay = baseDelay * Math.pow(2, i); await new Promise(r => setTimeout(r, delay)); continue; } } // Exponential backoff for other errors const delay = baseDelay * Math.pow(2, i); await new Promise(r => setTimeout(r, delay)); } } throw lastError!; } // Usage for application-level retries const result = await withRetry(() => conto.payments.pay({ amount: 100, recipientAddress: '0x...' })); ``` ## Logging Errors ```typescript async function loggedPayment(params: PaymentRequestInput) { try { const result = await conto.payments.pay(params); console.log('Payment successful', { txHash: result.txHash, amount: result.amount }); return result; } catch (error) { const sdkError = error as ContoError; console.error('Payment failed', { code: sdkError.code, message: sdkError.message, params: { amount: params.amount, recipient: params.recipientAddress, purpose: params.purpose } }); throw error; } } ``` ## Best Practices Never let payment errors crash your application: ```typescript // Bad await conto.payments.pay({ ... }); // Good try { await conto.payments.pay({ ... }); } catch (error) { // Handle gracefully } ``` Don't just catch generic errors: ```typescript // Bad catch (error) { console.log('Something went wrong'); } // Good catch (error) { if (error.code === 'INSUFFICIENT_BALANCE') { // Specific handling } } ``` Be careful with retries on payment execution: ```typescript // Dangerous - might double-pay await withRetry(() => conto.payments.execute(requestId)); // Safe - check status first const status = await conto.payments.status(requestId); if (!status.transaction) { await conto.payments.execute(requestId); } ``` Always log error details for debugging: ```typescript catch (error) { console.error('Payment error', { code: error.code, status: error.status, message: error.message }); } ``` ## Next Steps ### Examples Link: https://conto.finance/docs/sdk/examples See complete integration examples ### API Reference Link: https://conto.finance/api-docs View the REST API (Swagger UI) --- # SDK Examples Complete examples for common integration patterns. ## Basic Payment ```typescript import { Conto } from '@conto_finance/sdk'; const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); // Simple one-step payment const result = await conto.payments.pay({ amount: 50.00, recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...', recipientName: 'OpenAI', purpose: 'GPT-4 API credits', category: 'AI_SERVICES' }); console.log('TX Hash:', result.txHash); ``` ## Two-Step Payment with Approval Handling ```typescript import { Conto } from '@conto_finance/sdk'; import type { ContoError } from '@conto_finance/sdk'; async function makePayment(params: { amount: number; recipient: string; purpose: string; }) { const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); // Step 1: Request authorization const request = await conto.payments.request({ amount: params.amount, recipientAddress: params.recipient, purpose: params.purpose }); // Step 2: Handle different statuses switch (request.status) { case 'APPROVED': const result = await conto.payments.execute(request.requestId); return { success: true, txHash: result.txHash }; case 'DENIED': return { success: false, error: 'Payment denied', reasons: request.reasons, violations: request.violations }; case 'REQUIRES_APPROVAL': return { success: false, pending: true, requestId: request.requestId, message: 'Awaiting manual approval' }; } } ``` ## LangChain Tool Integration ```typescript import { DynamicTool } from 'langchain/tools'; import { Conto } from '@conto_finance/sdk'; import type { ContoError } from '@conto_finance/sdk'; const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); export const paymentTool = new DynamicTool({ name: 'make_payment', description: `Make a stablecoin payment to a recipient. Input: JSON with amount, recipientAddress, recipientName, purpose. Returns: Transaction details or error message.`, func: async (input: string) => { try { const params = JSON.parse(input); const result = await conto.payments.pay({ amount: params.amount, recipientAddress: params.recipientAddress, recipientName: params.recipientName, purpose: params.purpose, category: params.category || 'OPERATIONS' }); return JSON.stringify({ success: true, transactionHash: result.txHash, amount: result.amount, explorerUrl: result.explorerUrl }); } catch (error) { // ContoError is an interface, not a class. Use a property check. const contoError = error as ContoError; if (contoError && typeof contoError === 'object' && 'code' in contoError) { return JSON.stringify({ success: false, error: contoError.message, code: contoError.code }); } return JSON.stringify({ success: false, error: 'Unexpected error' }); } } }); ``` ## OpenAI Function Calling ```typescript import OpenAI from 'openai'; import { Conto } from '@conto_finance/sdk'; const openai = new OpenAI(); const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); // Define the function const paymentFunction = { name: 'make_payment', description: 'Make a stablecoin payment to a vendor or service', parameters: { type: 'object', properties: { amount: { type: 'number', description: 'Amount in USDC' }, recipientAddress: { type: 'string', description: 'Ethereum address' }, recipientName: { type: 'string', description: 'Recipient name' }, purpose: { type: 'string', description: 'Payment purpose' } }, required: ['amount', 'recipientAddress', 'purpose'] } }; // Handle function calls async function handleFunctionCall(name: string, args: any) { if (name === 'make_payment') { const result = await conto.payments.pay({ amount: args.amount, recipientAddress: args.recipientAddress, recipientName: args.recipientName, purpose: args.purpose }); return { success: true, txHash: result.txHash }; } } ``` ## Express API Endpoint ```typescript import express from 'express'; import { Conto } from '@conto_finance/sdk'; import type { ContoError } from '@conto_finance/sdk'; const app = express(); const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); app.post('/api/payments', async (req, res) => { try { const { amount, recipientAddress, purpose } = req.body; // Validate input if (!amount || !recipientAddress) { return res.status(400).json({ error: 'Missing required fields' }); } // Make payment const result = await conto.payments.pay({ amount, recipientAddress, purpose }); res.json({ success: true, transactionId: result.transactionId, txHash: result.txHash, explorerUrl: result.explorerUrl }); } catch (error) { // ContoError is an interface, not a class. Use a property check. const contoError = error as ContoError; if (contoError && typeof contoError === 'object' && 'code' in contoError) { res.status(contoError.status ?? 500).json({ success: false, error: contoError.message, code: contoError.code }); } else { res.status(500).json({ success: false, error: 'Internal server error' }); } } }); ``` ## Python SDK Wrapper ```python import requests from typing import Optional, Dict, Any class ContoSDK: def __init__(self, api_key: str, base_url: str = "https://conto.finance"): self.api_key = api_key self.base_url = base_url self.headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } def request_payment( self, amount: float, recipient_address: str, recipient_name: Optional[str] = None, purpose: Optional[str] = None, category: Optional[str] = None ) -> Dict[str, Any]: payload = { "amount": amount, "recipientAddress": recipient_address } if recipient_name: payload["recipientName"] = recipient_name if purpose: payload["purpose"] = purpose if category: payload["category"] = category response = requests.post( f"{self.base_url}/api/sdk/payments/request", headers=self.headers, json=payload ) response.raise_for_status() return response.json() def execute_payment(self, request_id: str) -> Dict[str, Any]: response = requests.post( f"{self.base_url}/api/sdk/payments/{request_id}/execute", headers=self.headers ) response.raise_for_status() return response.json() def pay(self, amount: float, recipient_address: str, **kwargs) -> Dict[str, Any]: request = self.request_payment(amount, recipient_address, **kwargs) if request["status"] != "APPROVED": raise Exception(f"Payment denied: {request['reasons']}") return self.execute_payment(request["requestId"]) # Usage conto = ContoSDK("conto_agent_xxx") result = conto.pay( amount=50.00, recipient_address="0x1234...", recipient_name="OpenAI", purpose="API credits" ) print(f"Transaction hash: {result['txHash']}") ``` ## Single-Call Payment with autoExecute Skip the two-step flow entirely by using `autoExecute: true`, request authorization and execute the payment in one API call. ```typescript const response = await fetch('https://conto.finance/api/sdk/payments/request', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.CONTO_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 50.00, recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...', recipientName: 'OpenAI', purpose: 'GPT-4 API credits', category: 'AI_SERVICES', autoExecute: true }) }); const result = await response.json(); switch (result.status) { case 'EXECUTED': console.log('Payment complete in one call!'); console.log('TX Hash:', result.execution.txHash); console.log('Explorer:', result.execution.explorerUrl); console.log('Currency:', result.currency); console.log('Chain:', result.chain.chainName); break; case 'APPROVED': if (result.autoExecuteError) { // Auto-execute failed, fall back to manual execute console.log('Auto-execute failed:', result.autoExecuteError.error); const execResult = await fetch(result.executeUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.CONTO_API_KEY}` } }).then(r => r.json()); console.log('Manual execute TX:', execResult.txHash); } else { // autoExecute was silently ignored. This only happens when the key // lacks payments:execute (the standard preset includes it). // Execute manually const execResult = await fetch(result.executeUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.CONTO_API_KEY}` } }).then(r => r.json()); } break; case 'DENIED': console.log('Payment denied:', result.reasons); if (result.context?.nextSteps) { console.log('Suggested actions:', result.context.nextSteps); } break; case 'REQUIRES_APPROVAL': console.log('Awaiting manual approval'); break; } ``` ## Agent Bootstrap with Setup Endpoint Call `GET /api/sdk/setup` on startup to understand your agent's full configuration, wallets, policies, counterparties, and capabilities. ```typescript async function bootstrapAgent() { const config = await fetch('https://conto.finance/api/sdk/setup', { headers: { 'Authorization': `Bearer ${process.env.CONTO_API_KEY}` } }).then(r => r.json()); console.log('Agent:', config.agent.name, `(${config.agent.status})`); console.log('Scopes:', config.scopes.join(', ')); // Check capabilities if (config.capabilities.canAutoExecute) { console.log('Can auto-execute payments (single-call)'); } console.log('Max single payment:', config.capabilities.maxSinglePayment); console.log('Remaining daily budget:', config.capabilities.remainingDailyBudget); // List wallets for (const wallet of config.wallets) { console.log(`Wallet ${wallet.address} (${wallet.custodyType})`); console.log(` Chain: ${wallet.chainName} | Balance: ${wallet.balance} ${wallet.currency}`); console.log(` Executable: ${wallet.isExecutable}`); console.log(` Limits: $${wallet.limits.perTransaction}/tx, $${wallet.limits.daily}/day`); } // List known counterparties for (const cp of config.counterparties) { console.log(`Counterparty: ${cp.name} (${cp.trustLevel}) - ${cp.transactionCount} txns`); } return config; } ``` ## Programmatic Counterparty Creation Agents can create counterparties before making payments to new recipients. This avoids "unknown counterparty" policy denials. ```typescript async function ensureCounterparty(address: string, name: string, category?: string) { const response = await fetch('https://conto.finance/api/sdk/counterparties', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.CONTO_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name, address, type: 'VENDOR', category: category || 'OPERATIONS' }) }); const counterparty = await response.json(); console.log(`Counterparty ${counterparty.created ? 'created' : 'updated'}: ${counterparty.name}`); console.log(`Trust: ${counterparty.trustLevel} (${counterparty.trustScore})`); return counterparty; } // Usage: create counterparty then pay await ensureCounterparty('0x1234...', 'Anthropic', 'AI_SERVICES'); const result = await conto.payments.pay({ amount: 100, recipientAddress: '0x1234...', purpose: 'Claude API credits' }); ``` ## Requesting Policy Exceptions When a payment is denied by policy, agents can request an exception for human review instead of failing silently. ```typescript async function requestException(type: string, reason: string, details?: object) { const response = await fetch('https://conto.finance/api/sdk/policies/exceptions', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.CONTO_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ type, // ADD_TO_WHITELIST, INCREASE_SPEND_LIMIT, etc. reason, urgency: 'NORMAL', details }) }); const exception = await response.json(); console.log(`Exception ${exception.exceptionId} submitted (${exception.status})`); return exception; } // Example: payment denied, request whitelist addition const request = await conto.payments.request({ amount: 100, recipientAddress: '0xNewVendor...', purpose: 'New service subscription' }); if (request.status === 'DENIED') { const hasWhitelistViolation = request.violations?.some( v => v.type === 'WHITELIST_VIOLATION' ); if (hasWhitelistViolation) { await requestException('ADD_TO_WHITELIST', 'Need to pay new vendor for service subscription', { counterpartyAddress: '0xNewVendor...', counterpartyName: 'New Service Inc.', amount: 100 }); } } ``` ## Batch Payments ```typescript import { Conto } from '@conto_finance/sdk'; interface PaymentItem { recipient: string; amount: number; purpose: string; } async function batchPayments(items: PaymentItem[]) { const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); const results = []; for (const item of items) { try { const result = await conto.payments.pay({ amount: item.amount, recipientAddress: item.recipient, purpose: item.purpose }); results.push({ recipient: item.recipient, success: true, txHash: result.txHash }); } catch (error) { results.push({ recipient: item.recipient, success: false, error: error.message }); } // Rate limit: wait between requests await new Promise(r => setTimeout(r, 500)); } return results; } ``` ## Webhook Handler (Approval Notifications) ```typescript import express from 'express'; import { Conto } from '@conto_finance/sdk'; const app = express(); const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); // Store pending payments const pendingPayments = new Map void; }>(); // Request payment and wait for approval async function requestPaymentWithApproval(params: { amount: number; recipient: string; purpose: string; }) { const request = await conto.payments.request({ amount: params.amount, recipientAddress: params.recipient, purpose: params.purpose }); if (request.status === 'APPROVED') { return conto.payments.execute(request.requestId); } if (request.status === 'REQUIRES_APPROVAL') { // Wait for webhook callback return new Promise((resolve) => { pendingPayments.set(request.requestId, { amount: params.amount, recipient: params.recipient, resolve }); }); } throw new Error(`Payment denied: ${request.reasons.join(', ')}`); } // Webhook endpoint (called when payment is approved) app.post('/webhooks/conto', async (req, res) => { const { event, data } = req.body; const paymentId = data?.paymentId; if (event === 'payment.approved' && paymentId) { const pending = pendingPayments.get(paymentId); if (pending) { const result = await conto.payments.execute(paymentId); pending.resolve(result); pendingPayments.delete(paymentId); } } res.json({ received: true }); }); ``` ## MCP Server Configuration For Claude Desktop integration: ```json { "mcpServers": { "conto": { "command": "npx", "args": ["@conto_finance/mcp-server"], "env": { "CONTO_API_KEY": "conto_agent_xxx..." } } } } ``` Then Claude can make payments naturally: > "Pay $50 to 0x123... for API credits" ## Next Steps ### Policies Link: https://conto.finance/docs/policies/overview Configure spending policies ### API Reference Link: https://conto.finance/api-docs View the REST API (Swagger UI) --- # Agent Skills The Conto skill adds spending-policy enforcement to any AI agent built on [OpenClaw](https://github.com/openclaw/openclaw) or [Nous Hermes](https://hermes-agent.nousresearch.com/). It checks every payment against 40+ policy rule types before money leaves the wallet. Both frameworks use the same wrapper script (`conto-check.sh`) and the same Conto REST API. Only the install command and the config file location differ. Info: In the examples below, `pathUSD` refers to Tempo Testnet. For production wallets on Tempo Mainnet, use `USDC.e`. ## How it works ``` Agent wants to pay 50 pathUSD to 0xabc... | v Skill calls POST /api/sdk/payments/approve | v Conto evaluates all policy rules | +---> APPROVED: agent proceeds with payment +---> DENIED: agent stops, reports violations +---> REQUIRES_APPROVAL: agent pauses for human sign-off +---> VERIFICATION_REQUIRED: human completes AgentScore identity step-up, then Conto resumes ``` Conto supports two wallet modes: - **Integrated (PRIVY/SPONGE).** Your wallet provider holds the keys. Conto evaluates policies and orchestrates execution through the provider. - **External.** Agent holds the keys. Agent calls approve, transfers itself, then confirms. Both modes evaluate the same rule set. ### Which endpoint do I call? | | Integrated (PRIVY/SPONGE) | External | | ----------------- | --------------------------------------------------- | -------------------------------- | | Custody type | `PRIVY` or `SPONGE` | `EXTERNAL` | | Who holds keys | Wallet provider | Your agent | | Endpoint | `POST /api/sdk/payments/request` | `POST /api/sdk/payments/approve` | | Calls per payment | 1 (with `autoExecute: true` and `payments:execute`) | 3 (approve, transfer, confirm) | | Approval expiry | 5 minutes | 10 minutes | | `chainId` | Resolved from wallet | Required in request body | Most skill users register an existing wallet (e.g. through an MCP server like Sponge) as `EXTERNAL` and let Conto act as the policy gate. If you enable AgentScore-backed merchant gating, the integrated flow can also return `VERIFICATION_REQUIRED` before execution. In that case the human verifies identity through the provided URL, Conto re-runs policy evaluation with the merchant compliance result, and then the payment proceeds or fails normally. Info: The default **Standard SDK key** preset includes the payment scopes these flows need: `payments:execute`, `payments:approve`, and `payments:confirm`. Admin SDK keys are only required for the policy management commands covered later in this guide. ## Install Requirements: `conto-check.sh` uses `curl`, `jq`, and `python3`. Install `jq` via your package manager if missing (`brew install jq`, `apt install jq`). `python3` runs a short-lived localhost callback server during browser auth. Install from [ClawHub](https://clawhub.ai/kwattana/conto): ```bash npx clawhub install conto ``` You can inspect the raw skill manifest at [`conto.finance/skill.md`](https://conto.finance/skill.md). Use ClawHub for installation so the helper script is installed with the skill. Do not run `npm install @conto_finance/sdk`. The OpenClaw skill uses `conto-check.sh` (installed by ClawHub) to call the Conto REST API directly. The `@conto_finance/sdk` npm package is a separate TypeScript SDK and is not needed here. Install from the well-known endpoint: ```bash hermes skills install well-known:https://conto.finance/.well-known/skills/conto --force ``` This fetches `SKILL.md` and `conto-check.sh` and installs them into `~/.hermes/skills/conto/`. Current Hermes releases flag networked finance skills during install; `--force` is required after you review that this skill only talks to `https://conto.finance` and writes the SDK key you approve into `~/.hermes/.env`. Or copy the skill files directly: ```bash cp -r skills/conto-hermes ~/.hermes/skills/conto ``` ## Quick setup After installing, run setup with your agent name and wallet address: ```bash bash skills/conto/conto-check.sh setup "my-agent" "0xYourWalletAddress" EVM 42431 ``` This opens your browser for Conto login. After you approve, the agent is automatically provisioned with: - An agent record linked to your organization - Your wallet registered as `EXTERNAL` custody - Default spend limits ($100/tx, $500/day) - An SDK key written to the framework's config file (see below) | Argument | Default | Description | | ---------------- | -------- | -------------------------------------------------------------- | | `agent_name` | required | Name for your agent | | `wallet_address` | required | Your wallet address (`0x...` for EVM, base58 for Solana) | | `chain_type` | `EVM` | `EVM` or `SOLANA` | | `chain_id` | `42431` | Common: `8453` (Base), `42431` (Tempo Testnet), `1` (Ethereum) | Verify it works: ```bash bash skills/conto/conto-check.sh budget ``` For Hermes installs, use `bash ~/.hermes/skills/conto/conto-check.sh ...` instead of `bash skills/conto/conto-check.sh ...`. You can adjust spend limits, add policies, and manage the agent in the [Conto dashboard](https://conto.finance). ## Config file locations The skill writes the SDK key to a framework-specific path: `~/.openclaw/openclaw.json`: ```json { "skills": { "entries": { "conto": { "env": { "CONTO_SDK_KEY": "conto_agent_your_key_here", "CONTO_API_URL": "https://conto.finance" } } } } } ``` This must be valid JSON. Trailing commas or missing braces will make every OpenClaw command fail. Validate with `cat ~/.openclaw/openclaw.json | jq .`. `~/.hermes/.env`: ```bash CONTO_SDK_KEY=conto_agent_your_key_here CONTO_API_URL=https://conto.finance ``` ## Manual setup If browser-based setup doesn't work, configure manually: 1. **Connect your agent in Conto.** Sign in to the [Conto dashboard](https://conto.finance) and create the agent record. 2. **Link your wallet.** Go to **Agents > your agent > Wallets > Link Wallet**. Enter the address and chain. Set initial spending limits. 3. **Generate an SDK key.** Go to **Agents > your agent > SDK Keys > Generate New Key**. Pick **Standard** for payment flows; the preset includes the request, execute, approve, and confirm scopes this skill uses. Pick **Admin** only if you also want the skill to manage policies, agents, or wallets. 4. **Save the key** to the config path for your framework (above). ## Finding your wallet address How you obtain a wallet address depends on your setup. **Existing MCP wallet (Sponge, AgentCash).** Ask your agent or run the `get_balance` / `list_accounts` tool. Copy the address for the chain you want to use. **Create a wallet in Conto.** Dashboard > **Wallets > Create Wallet** > pick `PRIVY` or `SPONGE` custody > select chain > **Provision**. Conto creates the wallet onchain and shows the address. **Your own external wallet (hardware, MetaMask, etc.).** Register the address in Conto as `EXTERNAL` custody. Your agent handles the onchain transfer itself. `EXTERNAL` custody keeps full key control in your wallet stack. Conto can approve, deny, record, and alert on payments routed through Conto, but it cannot cryptographically block a direct transfer signed outside Conto. ## Usage ``` /conto list my policies /conto create a $200 per-transaction limit Send 50 pathUSD to 0x742d... on Tempo ``` CLI (OpenClaw example): ```bash openclaw agent --agent main -m "Send 50 pathUSD to 0x742d... on Tempo" ``` ## Standard vs Admin SDK keys | Capability | Standard | Admin | | -------------------------------- | -------- | ----- | | Request policy evaluation | Yes | Yes | | Execute approved payments | Yes | Yes | | Approve / confirm payments | Yes | Yes | | Pre-authorize x402 calls | Yes | Yes | | Create merchant acceptance gates | No | Yes | | Read policies and transactions | Yes | Yes | | Create/update/delete policies | No | Yes | | Manage agents and wallets | No | Yes | With an admin key, manage policies through natural language: ``` /conto create a policy that limits each transaction to 200 pathUSD /conto create a policy that only allows API_PROVIDER and CLOUD categories /conto block address 0xbad... from receiving payments /conto create a policy that requires approval for payments over 500 pathUSD /conto delete the blocklist policy ``` ## Supported policy types | Type | What it controls | | --------------------------------------------------- | -------------------------------- | | `MAX_AMOUNT` | Per-transaction cap | | `DAILY_LIMIT` / `WEEKLY_LIMIT` / `MONTHLY_LIMIT` | Cumulative spend caps | | `ALLOWED_CATEGORIES` / `BLOCKED_CATEGORIES` | Category allowlist/blocklist | | `ALLOWED_COUNTERPARTIES` / `BLOCKED_COUNTERPARTIES` | Address allowlist/blocklist | | `TIME_WINDOW` / `DAY_OF_WEEK` | Business hours, allowed days | | `BLACKOUT_PERIOD` | Maintenance windows | | `VELOCITY_LIMIT` | Transaction rate limiting | | `REQUIRE_APPROVAL_ABOVE` | Human approval threshold | | `GEOGRAPHIC_RESTRICTION` | Country / OFAC restrictions | | `CONTRACT_ALLOWLIST` | DeFi contract restrictions | | `X402_PRICE_CEILING` | Max per x402 API call | | `X402_ALLOWED_SERVICES` / `X402_BLOCKED_SERVICES` | x402 service allowlist/blocklist | | `X402_MAX_PER_SERVICE` | Per-service daily cap | See [Policy overview](https://conto.finance/docs/policies/overview) for the full canonical rule-type list. When the skill records x402 or MPP protocol payments, it sends the aggregate settlement fields at the top level and per-call details in `batchItems`. Do not wrap protocol records in a top-level `payments` array. ## End-to-end example: pay a vendor on Tempo Testnet This walks the full external-wallet flow: approve, transfer onchain, confirm back to Conto. ### Prerequisites - Conto account with the agent connected - Conto skill installed in OpenClaw or Hermes - SDK key configured (see [Config file locations](#config-file-locations)) - A wallet address (see [Finding your wallet address](#finding-your-wallet-address)) ### Step 1. Tempo Testnet details | Detail | Value | | -------- | ------------------------------------------------------------------ | | Network | Tempo Testnet | | Chain ID | `42431` | | Currency | `pathUSD` (TIP-20 stablecoin) | | Gas | Paid in `pathUSD` (no separate gas token) | | Explorer | [`explore.moderato.tempo.xyz`](https://explore.moderato.tempo.xyz) | ### Step 2. Get testnet funds - **Conto Privy wallets:** dashboard **Wallets > your wallet > Faucet**. - **Tempo faucet:** [`faucet.tempo.network`](https://faucet.tempo.network). - **Sponge MCP wallets:** ask your agent for the balance and swap or bridge if needed. You need enough `pathUSD` to cover the test payment plus a small amount for fees. ### Step 3. Register the wallet in Conto Dashboard > **Agents > your agent > Wallets > Link Wallet**. Set: - Chain: Tempo Testnet (`42431`) - Custody type: `EXTERNAL` (or `PRIVY` if you created one in Conto) - Per Transaction: 200 pathUSD - Daily: 1,000 pathUSD - Weekly: 5,000 pathUSD - Allowed days: all days by default Wallet-level limits act as a safety net on top of any policy you assign. ### Step 4. Create a policy ``` /conto create a policy that limits each transaction to 200 pathUSD ``` The helper calls `POST /api/policies` with your admin SDK key and returns the policy ID. Verify: ``` /conto list my policies ``` ### Step 5. Request a payment ``` Send 50 pathUSD to 0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18 on Tempo ``` Behind the scenes the skill calls: ```bash curl -X POST https://conto.finance/api/sdk/payments/approve \ -H "Authorization: Bearer $CONTO_SDK_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 50, "recipientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18", "senderAddress": "0x1a2b3c4d5e6f...", "chainId": 42431, "purpose": "Vendor payment" }' ``` If approved immediately, the response includes an `approvalId` and `approvalToken`. If policy requires manual approval and a workflow matches, the response includes `approvalRequestId` instead. Once that workflow approves the payment, the agent confirms the onchain transfer back to Conto with the final `txHash`. ### Step 6. Transfer onchain The agent transfers `pathUSD` itself using its own keys. The skill handles this for you. ### Step 7. Confirm back to Conto After the onchain transfer succeeds: ```bash curl -X POST https://conto.finance/api/sdk/payments/APPROVAL_ID/confirm \ -H "Authorization: Bearer $CONTO_SDK_KEY" \ -H "Content-Type: application/json" \ -d '{ "txHash": "0xabc123...", "approvalToken": "a1b2c3d4..." }' ``` Conto records the payment, updates spend counters, and the transaction appears in the dashboard. ### Step 8. Verify ``` /conto show my recent transactions ``` Or check **Transactions** in the dashboard for the explorer link. ### What happens when a policy blocks the payment? ``` Send 300 pathUSD to 0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18 on Tempo ``` The skill returns a denial with the specific violation. No onchain transfer occurs. The denied attempt appears under **Alerts** in the dashboard. ```json { "approved": false, "reasons": ["Amount 300 exceeds maximum of 200 per transaction"], "violations": [ { "type": "PER_TX_LIMIT", "limit": 200, "current": 300, "message": "Amount 300 exceeds maximum of 200 per transaction" } ], "requiresHumanApproval": false } ``` Common violation types: `PER_TX_LIMIT`, `DAILY_LIMIT`, `WEEKLY_LIMIT`, `MONTHLY_LIMIT`, `BLOCKED_COUNTERPARTY`, `TIME_WINDOW`, `CATEGORY_RESTRICTION`, `VELOCITY_LIMIT`. See [Advanced policies](https://conto.finance/docs/policies/advanced) for the full list. ## Rate limits | Endpoint type | Limit | | ------------------------------------------------------------------ | -------------------------- | | Payment endpoints (`/approve`, `/request`, `/execute`, `/confirm`) | 60 requests/min per agent | | Read endpoints (`/wallets`, `/policies`, `/transactions`, etc.) | 120 requests/min per agent | On `429`, the API returns a `Retry-After` header. The skill retries automatically. See the [Defaults](https://conto.finance/reference/defaults) page for all rate-limit and default values. ## Troubleshooting Verify `CONTO_API_URL` is correct. For the hosted platform, use `https://conto.finance`. For local dev, `http://localhost:3006`. Test: ```bash curl https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_SDK_KEY" ``` A valid JSON response means the URL is reachable. SDK keys are scoped to a single agent. Check that: - The key starts with `conto_agent_` (not `conto_`) - The key has not been revoked in **Agents > SDK Keys** - You're using the correct key for the correct agent Generate a new key under **Agents > your agent > SDK Keys > Generate New Key**. The denial response includes a `violations` array listing every rule that failed. Common causes: - Spend limit exceeded. Check daily/weekly/monthly counters in **Agents > Spend Tracking**. - Counterparty not on allowlist. If you have an `ALLOWED_COUNTERPARTIES` policy, the recipient must be listed. - Outside time window. `TIME_WINDOW` and `DAY_OF_WEEK` policy rules use the server's local time; wallet-level time windows support explicit IANA timezones. - Category mismatch. If `ALLOWED_CATEGORIES` is set and no `category` is provided, the allow rule denies because the category cannot be verified. `BLOCKED_CATEGORIES` skips when no category is present. Dry-run check without attempting a real payment: ``` /conto check if a 50 pathUSD payment to 0x742d... is allowed ``` In external wallet mode, Conto only enforces policy. The agent must transfer funds itself. If `/approve` succeeds but no transfer happens: - Check the agent has enough `pathUSD` in its wallet. - Check the agent logs for transfer errors. - Ensure the wallet address in Conto matches the agent's actual wallet. If the transfer succeeded but Conto doesn't show it, the `/confirm` call may have failed. Retry: ```bash curl -X POST https://conto.finance/api/sdk/payments/APPROVAL_ID/confirm \ -H "Authorization: Bearer $CONTO_SDK_KEY" \ -H "Content-Type: application/json" \ -d '{"txHash": "0x...", "approvalToken": "a1b2c3d4..."}' ``` Policy management requires an Admin SDK key. The default Standard preset covers the payment lifecycle (`payments:request`, `payments:execute`, `payments:approve`, `payments:confirm`) and reads, but not management scopes like `policies:write`. Check the key type in **Agents > SDK Keys** (scope column shows `standard` or `admin`). Policies must be assigned to the agent. Creating a policy alone doesn't activate it. Assign via the dashboard (**Policies > Assign to Agent**) or via the API: ```bash curl -X POST https://conto.finance/api/agents/AGENT_ID/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{"policyId": "POLICY_ID"}' ``` Verify the policy status is `ACTIVE`. If every OpenClaw command fails after a manual edit, the JSON file likely has a syntax error. Validate: ```bash cat ~/.openclaw/openclaw.json | jq . ``` If `jq` reports an error, fix the JSON or delete and re-run setup: ```bash rm ~/.openclaw/openclaw.json bash skills/conto/conto-check.sh setup "my-agent" "0xMyWalletAddress" EVM 42431 ``` --- ## Install & Run Run with `npx`: ```bash npx @conto_finance/create-conto-agent ``` Or install globally: ```bash npm install -g @conto_finance/create-conto-agent create-conto-agent ``` The wizard provisions everything your agent needs: a wallet (custody chosen by the server, Privy on the hosted instance), a spending policy, and an SDK key. No manual dashboard steps required. The package exposes both the `create-conto-agent` and `conto` bins. The wizard installs itself into your project as a dev dependency, so `npx conto ` resolves to the real Conto CLI from inside the project directory. Outside a project with that dependency, use the full package name (`npx @conto_finance/create-conto-agent `) or a global install; a bare `npx conto` would fetch an unrelated npm package that happens to own that name. ## Headless And Agent Runs The wizard needs an interactive terminal and a browser. For CI, scripts, and autonomous agents, use one of the noninteractive modes instead: ```bash # Anonymous test-mode sandbox: no account, no browser, no prompts. # Expires after 7 days. Payments execute in simulated mode. npx @conto_finance/create-conto-agent --sandbox --json # Existing organization: authenticate with an org API key instead of the browser. npx @conto_finance/create-conto-agent --api-key conto_xxx --name my-agent --json ``` Both modes write the same `.env.local`, `conto.config.json`, and `example.ts` files as the wizard. `--json` prints a machine-readable result to stdout. Without a TTY and without one of these flags, the CLI exits with an error that lists them instead of hanging on a prompt. `--help` and `--version` work in any terminal, TTY or not. ## What Happens Choose your agent name, type, daily spending limit, and network. The CLI opens a browser window to `conto.finance/cli-auth`. Sign in with your Conto account (or create one). The browser redirects the token back to the CLI automatically. The wizard creates a wallet on your chosen chain, registers the agent, links the wallet with spend limits, creates a default spending policy, and generates an SDK key. Three files are written to your current directory: - `.env.local`: SDK key and configuration - `conto.config.json`: Agent metadata - `example.ts`: Runnable payment example The wizard also adds `@conto_finance/create-conto-agent` as a dev dependency (creating a minimal `package.json` if the directory has none) so `npx conto ` works. Pass `--no-install` to skip this. ## Supported Networks | Network | Currency | Chain ID | Notes | | ------------- | -------- | -------------- | ---------------------------------------- | | **Tempo** | USDC.e | 4217 | Recommended (preselected by the wizard) | | Tempo Testnet | pathUSD | 42431 | Platform default; auto-funded via faucet | | Base | USDC | 8453 | | | Solana | USDC | solana-mainnet | | The wizard lists every chain returned by `/api/chains` (including Ethereum, Arbitrum, Polygon, Base Sepolia, and Solana Devnet); the table above covers the most common choices. Tempo is recommended because it's stablecoin-native (no ETH needed), has sub-second finality, and negligible gas costs. Tempo Mainnet uses `USDC.e`; Tempo Testnet uses `pathUSD`. Info: On Tempo Testnet, the wizard automatically funds your wallet via faucet, no manual funding needed. ## Run the Example ```bash npx tsx example.ts # Check setup + request a test payment (no funds move) npx tsx example.ts --execute # Also execute the payment if policies approve it ``` The example prints your agent, key scopes, and wallet from `GET /api/sdk/setup`, then requests a $0.01 payment through the policy engine. Without `--execute` it stops after the policy decision. ## Next Steps After setup, use the `conto` CLI for day-to-day operations (from the project directory): ```bash npx conto doctor # Verify auth, scopes, wallet, chain, balance, base URL npx conto status # Agent info and spending summary npx conto pay --dry-run 0x... 10 # Test a payment against policies npx conto pay 0x... 10 # Request + execute a payment npx conto mcp # Start the MCP server for Claude ``` ### Commands Reference Link: https://conto.finance/docs/cli/commands Full list of CLI commands and flags ### Policy Management Link: https://conto.finance/docs/cli/policies Create and manage spending policies from the CLI --- ## Global Options All commands support these flags: | Flag | Description | | ----------- | ----------------------------------- | | `--json` | Output in JSON format for scripting | | `--help` | Show help for any command | | `--version` | Show CLI version | ## Agent & Status ```bash conto doctor # Diagnose setup: auth, scopes, wallet, chain, balance, base URL conto status # Agent info, wallet balances, spending progress conto balance # Wallet balance table conto config # Show current configuration conto config # Update a config value ``` Info: `conto doctor` calls `GET /api/sdk/setup` with your SDK key and reports each check, including whether the key has `payments:request` and `payments:execute` and whether the wallet can execute real transfers. It exits non-zero when a hard check fails, so you can use it in scripts. ## Payments ```bash conto pay
# Request and execute payment conto pay
--dry-run # Policy check without executing conto pay
--purpose "reason" # Add a purpose string conto pay
--wallet # Use a specific wallet conto pay
--category "API" # Tag with spend category ``` Info: `--dry-run` runs the full policy evaluation (all rules, all policies) and returns APPROVED, DENIED, or REQUIRES_APPROVAL without sending any transaction. ## Transactions ```bash conto transactions # List recent transactions (default: 10) conto transactions --limit 50 # List more transactions conto transactions # View transaction details ``` ## Wallets ```bash conto wallets # List all wallets with balances conto fund # Show chain-aware funding instructions ``` ## Spending Limits ```bash conto limits # Daily/weekly/monthly limits with progress bars ``` ## Alerts ```bash conto alerts # List all alerts conto alerts --unread # Unread alerts only ``` ## Policies See [Policy Management](https://conto.finance/docs/cli/policies) for full CRUD documentation. ```bash conto policies # List agent policies ([agent] vs [org-wide]) conto policies all # List all org policies conto policies create # Interactive policy builder conto policies update # Update name, priority, active status conto policies delete # Delete with confirmation conto policies assign # Assign policy to current agent conto policies unassign # Remove policy from agent conto policies add-rule # Add a rule to a policy conto policies remove-rule # Remove a rule ``` ## Authentication ```bash conto login # Re-authenticate (opens browser) conto login --base-url # Authenticate against a specific server conto logout # Clear stored credentials ``` ## MCP Server ```bash conto mcp # Start the Conto MCP server for Claude ``` ## Documentation ```bash conto docs # Open the CLI quickstart docs conto docs commands # Open the commands reference conto docs policies # Open the policy docs conto docs sdk # Open the SDK installation guide conto docs api # Open the public API reference ``` ## Init Wizard ```bash create-conto-agent # Run the setup wizard (interactive) conto init # Same as above # Non-interactive with flags: create-conto-agent --base-url https://conto.finance --name my-agent --type ANTHROPIC_CLAUDE --limit 500 --chain 42431 # Skip the local CLI install (npx conto will not resolve without it): create-conto-agent --no-install ``` Info: `--chain` expects the chain ID returned by `GET /api/chains`, for example `42431`, `4217`, `8453`, or `solana-mainnet`. ## JSON Mode Every command supports `--json` for machine-readable output: ```bash conto status --json | jq '.agent.name' conto pay --dry-run 0x... 10 --json | jq '.status' conto policies --json | jq '.[].name' ``` ## Configuration Files | File | Location | Purpose | | ---------------------- | -------- | ------------------------------------- | | `~/.conto/config.json` | Global | API keys, agent ID, server URL | | `.env.local` | Project | SDK key, chain config, wallet address | | `conto.config.json` | Project | Agent metadata (generated by init) | The CLI reads project-level `.env.local` first, then falls back to global `~/.conto/config.json`. --- ## Overview The CLI provides full CRUD for spending policies. When you list policies, each one is tagged as `[agent]` (directly assigned) or `[org-wide]` (inherited from your organization). ```bash conto policies ``` ## Create a Policy The interactive builder walks you through each step with descriptions: ```bash conto policies create ``` You'll be prompted for: 1. **Policy name**. A descriptive label. 2. **Policy type**. 14 types available, each with an explanation. 3. **Priority**. Higher numbers are evaluated first. Use 0-100. Default is 50. 4. **Rules**. Optionally add the first rule immediately. 5. **Assignment**. Assign to the current agent or leave org-wide. ## Policy Types | Type | Description | |------|-------------| | Spend Limit | Cap per-transaction, daily, weekly, or monthly totals | | Approval Threshold | Require human approval above a dollar amount | | Counterparty | Allow or block specific wallet addresses | | Category | Restrict which spend categories are permitted | | Geographic | Block transactions involving sanctioned countries | | Budget Allocation | Set a total budget cap for a time period | | Expiration | Policy only active within a date range | | Merchant | Allow or block specific merchants by address | | Time Window | Restrict transactions to specific hours or days | | Velocity | Rate limit: max transactions per time period | | Whitelist | Only pre-approved addresses can receive payments | | Composite | Combine multiple conditions with AND/OR logic | | Contract Allowlist | Restrict to approved smart contract addresses | | Blackout Period | Block all transactions during specific time windows | ## Add Rules Add rules to an existing policy: ```bash conto policies add-rule ``` The rule builder prompts for: - **Rule type**: Context-aware options based on the policy type - **Operator**: `<=`, `>=`, `in list`, `not in list`, `between`, etc. - **Value**: With smart placeholders (dollar amounts for limits, JSON arrays for lists, country codes for geographic rules) - **Action**: Allow, Deny, or Require Approval ### Value Examples by Rule Type | Rule Type | Example Value | Format | |-----------|--------------|--------| | Daily Limit | `500` | Dollar amount | | Allowed Counterparties | `["0xabc...","0xdef..."]` | JSON array of addresses | | Geographic Restriction | `["CU","IR","KP","SY"]` | JSON array of country codes | | Trust Score | `50` | Number (0-100) | | Date Range | `{"start":"2025-01-01","end":"2025-12-31"}` | JSON with ISO dates | | Velocity Limit | `5` | Max transactions per window | ## Update & Delete ```bash # Update name, priority, or active status conto policies update # Delete (with confirmation prompt) conto policies delete # Remove a specific rule from a policy conto policies remove-rule ``` ## Assign & Unassign Control which policies apply to your agent: ```bash # Assign an org policy to your agent conto policies assign # Remove a policy from your agent conto policies unassign ``` Org-wide policies (tagged `[org-wide]`) cannot be unassigned, they apply to all agents in the organization. To remove them, either delete the policy or set it to inactive with `conto policies update `. ## List All Org Policies To see every policy in the organization (not just your agent's): ```bash conto policies all ``` This shows the policy ID, agent count, rules, and active status for all policies. ## JSON Output All policy commands support `--json`: ```bash conto policies --json conto policies all --json conto policies create --json # Returns created policy as JSON ``` --- ## What is MCP? MCP (Model Context Protocol) is an open protocol that allows AI agents to connect to external tools and data sources. Conto's MCP server gives Claude and other MCP-compatible agents the ability to manage wallets, make payments, track transactions, and query analytics, with custody-aware policy controls across managed and external-wallet flows. ## MCP vs AI Assistant vs Conto Pay Conto has three natural-language surfaces. They differ by who acts, how you reach them, and whether they move funds onchain: | Surface | Who acts | Reach it via | Auth | Onchain execution | | ------- | -------- | ------------ | ---- | ----------------- | | **MCP Server** | Your own external AI agent (Claude Desktop, Claude Code, other MCP clients) | An MCP client wired to your agent | Agent SDK key (`conto_agent_...`) | Yes, with custody-aware policy checks before execution | | **[AI Assistant](https://conto.finance/docs/assistant/overview)** (Conto AI) | You, working in the dashboard | Dashboard chat panel | Dashboard login | No. It configures agents, wallets, and policies. Payments still run through the SDK or agent flow | | **[Conto Pay](https://conto.finance/docs/conto-pay/overview)** | A Conto-hosted payment agent | Dashboard chat workspace | Dashboard login | Yes, through the normal request, approval, and execution flow | ## Package Install from npm: ```bash npm install @conto_finance/mcp-server ``` Or run directly with npx: ```bash npx @conto_finance/mcp-server ``` ## Quick Start See [Install MCP server](https://conto.finance/docs/mcp/install) for setup instructions covering Claude Desktop (macOS, Windows) and Claude Code (CLI). ## Getting an Agent SDK Key 1. Sign in to [Conto](https://conto.finance) 2. Go to **Agents** and create or select an agent 3. Generate an SDK key from the agent's detail page 4. Use the `conto_agent_...` key as `CONTO_API_KEY` Info: MCP uses an agent SDK key, not an organization API key. If your backend also provisions agents or repairs ownership, use a separate `CONTO_ORG_API_KEY` for that work. ## How It Works 1. **User requests an action**: A user asks Claude to make a payment, check balances, or perform another financial operation in natural language. 2. **Policy evaluation**: Claude calls Conto MCP tools. The server evaluates the request against your organization's spending policies (limits, time windows, counterparty rules, etc.). 3. **Execution**: If approved, the action is executed onchain and Claude reports the result with transaction details. ## Environment Variables The server reads `CONTO_API_KEY` (required) and `CONTO_BASE_URL` (optional). See the [configuration reference](https://conto.finance/docs/mcp/install#configuration-reference) in the install guide for defaults and details. ## Available Tools The MCP server exposes tools for payments, wallets, limits, budgets, trust checks, alerts, analytics, and setup reads. See the [full tools reference](https://conto.finance/docs/mcp/tools) for details. | Category | Tools | Description | | ------------------------- | ----- | ---------------------------------------------- | | Payments | 6 | Request, execute, and monitor payments | | Wallets and limits | 3 | Query balances and spending limits | | Budget requests | 2 | Request and check temporary budget increases | | Transactions | 3 | List, fetch, retry transactions | | x402 protocol | 4 | Pre-authorize and track x402 API micropayments | | MPP protocol | 4 | Pre-authorize and track MPP payments | | Card payments | 2 | Approve and confirm card transactions | | Agent-to-agent | 6 | Send and manage inter-agent payments | | Trust and counterparties | 4 | Trust scores and counterparty management | | Alerts and approvals | 4 | Manage alerts and pending approval requests | | Policies | 3 | Read and request policy exceptions | | Agent info | 2 | Get agent profile and full data snapshot | | Setup, audit, rate limits | 3 | Bootstrap config, audit log, rate-limit status | | Analytics | 1 | Spending analytics | --- # Install the Conto MCP server The same `@conto_finance/mcp-server` package works in both **Claude Desktop** and **Claude Code**. Already ran `npx @conto_finance/create-conto-agent`? Then `npx conto mcp` starts the MCP server with the SDK key and base URL from your generated config. No manual environment setup needed. The tabs below are for wiring the server into Claude Desktop or Claude Code directly. ## Prerequisites - [Claude Desktop](https://claude.ai/download) or [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed - A Conto agent SDK key. Format `conto_agent_...`. See the [Quickstart](https://conto.finance/docs/quickstart/setup) to generate one. The MCP server always uses `CONTO_API_KEY=conto_agent_...`. Do not use an organization API key (`conto_...`) or `CONTO_ORG_API_KEY` here. If your backend also provisions agents or repairs ownership, do that separately with an organization API key and `ContoAdmin`. Add Conto as an MCP server in one command: ```bash claude mcp add conto \ --env CONTO_API_KEY=conto_agent_xxx... \ --env CONTO_BASE_URL=https://conto.finance \ -- npx @conto_finance/mcp-server ``` Environment flags must come before the `--`. Everything after `--` is the command Claude Code runs for the server, so flags placed there would be passed to `npx` instead. Replace `conto_agent_xxx...` with your actual SDK key. ### Verify Start a new Claude Code session: ``` > What are my wallet balances? ``` Claude will invoke the `get_wallets` tool. ### Manage the server ```bash claude mcp list # list configured MCP servers claude mcp remove conto ``` Edit `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json { "mcpServers": { "conto": { "command": "npx", "args": ["@conto_finance/mcp-server"], "env": { "CONTO_API_KEY": "conto_agent_xxx...", "CONTO_BASE_URL": "https://conto.finance" } } } } ``` Replace `conto_agent_xxx...` with your actual SDK key. ### Verify 1. Restart Claude Desktop. 2. Look for the tools icon in the chat input. Conto's tools should appear in the list. 3. Ask: "What are my wallet balances?" Edit `%APPDATA%\Claude\claude_desktop_config.json`: ```json { "mcpServers": { "conto": { "command": "npx", "args": ["@conto_finance/mcp-server"], "env": { "CONTO_API_KEY": "conto_agent_xxx...", "CONTO_BASE_URL": "https://conto.finance" } } } } ``` Replace `conto_agent_xxx...` with your actual SDK key. ### Verify 1. Restart Claude Desktop. 2. Look for the tools icon in the chat input. 3. Ask: "What are my wallet balances?" ## Configuration reference | Env var | Default | Required | | ---------------- | ----------------------- | ---------------------------------------------------------- | | `CONTO_API_KEY` | none | Yes. Agent SDK key, format `conto_agent_...`. | | `CONTO_BASE_URL` | `https://conto.finance` | No. Override for local dev (e.g. `http://localhost:3006`). | ## Next steps ### MCP tool reference Link: https://conto.finance/docs/mcp/tools Full tool list, parameters, and responses ### MCP overview Link: https://conto.finance/docs/mcp/overview What MCP is and why Conto uses it --- Info: All MCP server API requests have a **30-second timeout** and all user-supplied parameters are sanitized before URL interpolation to prevent path injection. ## Payments (6) | Tool | Description | | -------------------------- | ------------------------------------------------------------ | | `pay` | Request and execute a payment in one step | | `request_payment` | Request payment authorization (check policies first) | | `execute_payment` | Execute a previously approved payment | | `check_payment_status` | Check status of a payment request | | `approve_external_payment` | Request approval for an external (agent-held) wallet payment | | `confirm_external_payment` | Confirm an externally-executed payment with tx hash | ### pay Request and execute a payment in one step. Combines `request_payment` + `execute_payment`. Fails if the payment is denied or requires manual approval. **Parameters:** | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | ----------------------------- | | `amount` | number | Yes | Amount in USDC | | `recipientAddress` | string | Yes | Recipient wallet address | | `recipientName` | string | No | Human-readable recipient name | | `purpose` | string | No | Why this payment is needed | | `category` | string | No | Spend category for analytics | | `sessionId` | string | No | Session/correlation ID | ### request_payment Request authorization for a payment. Evaluates spending policies and returns whether the payment is approved, denied, or requires manual approval. **Parameters:** Same as `pay`. **Returns:** `requestId`, `status` (`APPROVED` / `DENIED` / `REQUIRES_APPROVAL`), `wallet`, `reasons`, and `violations`. ### execute_payment Execute a previously approved payment request. | Parameter | Type | Required | Description | | ----------- | ------ | -------- | ------------------------------------ | | `requestId` | string | Yes | The requestId from `request_payment` | ### approve_external_payment Request approval for a payment from an external (agent-held) wallet. | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | ------------------------------------------------------ | | `amount` | number | Yes | Amount in USDC | | `recipientAddress` | string | Yes | Recipient wallet address | | `senderAddress` | string | Yes | Sender wallet address (agent-held) | | `recipientName` | string | No | Recipient name | | `purpose` | string | No | Payment purpose | | `category` | string | No | Spend category | | `context` | object | No | Additional context metadata | | `chainId` | string | Yes | Chain ID as a string (e.g. `"42431"` for Tempo Testnet) | ### confirm_external_payment Confirm an externally-executed payment was completed onchain. | Parameter | Type | Required | Description | | --------------- | ------ | -------- | ---------------------------------------------- | | `requestId` | string | Yes | Payment request ID from approval | | `txHash` | string | Yes | Onchain transaction hash | | `approvalToken` | string | Yes | Approval token from `approve_external_payment` | --- ## Wallets & Limits (3) | Tool | Description | | --------------------- | -------------------------------------------------- | | `get_wallets` | List all wallets linked to this agent | | `get_wallet` | Get details of a specific wallet | | `get_spending_limits` | Get current spending limits and remaining balances | ### get_wallet | Parameter | Type | Required | Description | | ---------- | ------ | -------- | ----------- | | `walletId` | string | Yes | Wallet ID | --- ## Budget Requests (2) | Tool | Description | | -------------------- | ------------------------------------------------- | | `request_budget` | Request a spending budget for human approval | | `get_budget_request` | Check budget request status and remaining balance | ### request_budget Request a spending budget for payments. Submits a request for human approval. Only one active budget request per agent at a time. Applies to all payment types (standard, x402, MPP). | Parameter | Type | Required | Description | | ---------- | ------ | -------- | --------------------------------------------------- | | `amount` | number | Yes | Requested budget in USDC | | `purpose` | string | Yes | What this budget is for (shown to reviewer) | | `category` | string | No | Spend category (e.g., API_PROVIDER, INFRASTRUCTURE) | | `metadata` | object | No | Additional context | ### get_budget_request Check status and remaining balance of your budget requests. Use to poll for approval after submitting a request, and to monitor remaining budget during spending. | Parameter | Type | Required | Description | | ----------------- | ------ | -------- | ------------------------------------------------------- | | `budgetRequestId` | string | No | Specific budget request ID | | `status` | string | No | Filter: PENDING, APPROVED, REJECTED, EXPIRED, EXHAUSTED | --- ## Transactions (3) | Tool | Description | | ------------------- | --------------------------------------- | | `list_transactions` | List transactions with optional filters | | `get_transaction` | Get details of a specific transaction | | `retry_transaction` | Retry a failed transaction | ### list_transactions | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------------------- | | `status` | string | No | Filter: PENDING, CONFIRMED, FAILED | | `from` | string | No | Start date (ISO string) | | `to` | string | No | End date (ISO string) | | `limit` | number | No | Results per page (max 100) | | `offset` | number | No | Pagination offset | --- ## x402 Protocol (4) | Tool | Description | | -------------------- | -------------------------------------------------- | | `x402_get_budget` | Check remaining x402 budget and burn rate | | `x402_pre_authorize` | Pre-authorize an x402 API payment against policies | | `x402_record` | Record a completed x402 payment (single or batch) | | `x402_list_services` | List x402 services with spend and pricing stats | ### x402_pre_authorize | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | ----------------------------- | | `amount` | number | Yes | Payment amount | | `recipientAddress` | string | Yes | Facilitator/recipient address | | `resourceUrl` | string | Yes | URL of the API endpoint | | `facilitator` | string | No | x402 facilitator address | | `walletId` | string | No | Preferred wallet ID | | `sessionId` | string | No | Session ID for grouping calls | | `category` | string | No | Spend category | `serviceDomain` is derived automatically from `resourceUrl`. ### x402_record | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | ------------------------------------------ | | `amount` | number | Yes | Payment amount | | `recipientAddress` | string | Yes | Recipient address | | `resourceUrl` | string | Yes | API endpoint URL | | `txHash` | string | No | Onchain transaction hash | | `batchItems` | array | No | Array of micropayments for batch recording | ### x402_list_services | Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------------------------------------------------ | | `period` | string | No | Time period: '24h', '7d', '30d', '90d' (default: '7d') | | `limit` | number | No | Max results (default: 50) | --- ## MPP Protocol (4) | Tool | Description | | ------------------- | ------------------------------------------------ | | `mpp_get_budget` | Check remaining MPP budget and burn rate | | `mpp_pre_authorize` | Pre-authorize an MPP payment against policies | | `mpp_record` | Record a completed MPP payment (single or batch) | | `mpp_list_services` | List MPP services with spend and pricing stats | ### mpp_pre_authorize | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | --------------------- | | `amount` | number | Yes | Payment amount | | `recipientAddress` | string | Yes | Recipient address | | `resourceUrl` | string | Yes | API endpoint URL | | `walletId` | string | No | Preferred wallet ID | | `intent` | string | No | 'charge' or 'session' | | `sessionId` | string | No | Session ID | | `paymentMethod` | string | No | Payment method | | `depositAmount` | number | No | Deposit for session intent | | `category` | string | No | Spend category | ### mpp_record | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | ----------------------------------------- | | `amount` | number | Yes | Aggregate payment amount | | `recipientAddress` | string | Yes | Recipient address | | `resourceUrl` | string | Yes | API endpoint URL | | `txHash` | string | No | Onchain settlement transaction hash | | `credentialId` | string | No | MPP credential ID | | `paymentReceipt` | string | No | Payment receipt payload | | `batchItems` | array | No | Per-call detail records for batch settlement | --- ## Card Payments (2) | Tool | Description | | -------------- | ---------------------------------------------------- | | `card_approve` | Request approval for a card payment against policies | | `card_confirm` | Confirm a card payment was completed | ### card_approve | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | ------------------------------ | | `cardId` | string | Yes | Card ID | | `amount` | number | Yes | Transaction amount | | `currency` | string | No | Currency code (default: "USD") | | `merchantName` | string | No | Merchant name | | `merchantCategory` | string | No | MCC code | | `purpose` | string | No | Purchase purpose | ### card_confirm | Parameter | Type | Required | Description | | --------------- | ------ | -------- | -------------------------------------- | | `requestId` | string | Yes | Payment request ID from `card_approve` | | `approvalToken` | string | Yes | Approval token from `card_approve` | | `externalTxId` | string | No | External transaction ID | | `authorizationCode` | string | No | Authorization code from card processor | | `actualAmount` | number | No | Actual charged amount | --- ## Agent-to-Agent (6) | Tool | Description | | --------------------- | -------------------------------------------- | | `a2a_send_request` | Send a payment request to another agent | | `a2a_list_requests` | List incoming/outgoing A2A requests | | `a2a_respond` | Approve or reject an A2A request | | `a2a_execute` | Execute an approved A2A payment | | `a2a_resolve_address` | Check if an address belongs to a Conto agent | | `a2a_get_stats` | Get A2A payment statistics | ### a2a_send_request | Parameter | Type | Required | Description | | --------------------- | ------ | -------- | -------------------------------------------- | | `amount` | number | Yes | Amount in USDC | | `targetAgentId` | string | No | Target agent ID (or use targetWalletAddress) | | `targetWalletAddress` | string | No | Target wallet address | | `purpose` | string | No | Why this payment is requested | | `invoiceId` | string | No | Invoice reference ID | ### a2a_respond | Parameter | Type | Required | Description | | ----------- | ------ | -------- | ------------------------- | | `requestId` | string | Yes | A2A request ID | | `action` | string | Yes | `'approve'` or `'reject'` | | `reason` | string | No | Optional rejection reason | --- ## Trust & Intelligence (4) | Tool | Description | | --------------------- | -------------------------------------------------- | | `check_address_trust` | Get trust score and risk info for a wallet address | | `list_counterparties` | List known counterparties with trust levels | | `get_counterparty` | Get counterparty details and transaction history | | `create_counterparty` | Create or update a counterparty | ### create_counterparty | Parameter | Type | Required | Description | | ------------- | ------ | -------- | ------------------------ | | `name` | string | Yes | Counterparty name | | `address` | string | Yes | Wallet address | | `type` | string | No | Type (default: 'VENDOR') | | `category` | string | No | Category | | `description` | string | No | Description | --- ## Monitoring (4) | Tool | Description | | ----------------------- | ------------------------------------ | | `list_alerts` | List active alerts and notifications | | `get_alert` | Get details of a specific alert | | `respond_to_alert` | Acknowledge or resolve an alert | | `get_approval_requests` | List pending approval requests | ### list_alerts | Parameter | Type | Required | Description | | ---------- | ------ | -------- | -------------------------------------------- | | `status` | string | No | Filter: `ACTIVE`, `ACKNOWLEDGED`, `RESOLVED` | | `severity` | string | No | Filter: `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` | | `limit` | number | No | Results per page (max 100) | | `offset` | number | No | Pagination offset | ### get_alert | Parameter | Type | Required | Description | | --------- | ------ | -------- | ----------- | | `alertId` | string | Yes | Alert ID | ### respond_to_alert | Parameter | Type | Required | Description | | ------------ | ------ | -------- | -------------------------- | | `alertId` | string | Yes | Alert ID | | `action` | string | Yes | 'acknowledge' or 'resolve' | | `resolution` | string | No | Resolution notes | --- ## Analytics & Info (7) | Tool | Description | | -------------------------- | --------------------------------------------- | | `get_analytics` | Get spending analytics and trends | | `get_policies` | List spending policies assigned to this agent | | `request_policy_exception` | Request an exception to a spending policy | | `list_policy_exceptions` | List policy exception requests | | `get_agent_info` | Get information about this agent | | `get_all` | Get comprehensive agent data in one call | | `get_setup` | Get agent setup and configuration | ### request_policy_exception | Parameter | Type | Required | Description | | --------- | ------ | -------- | ----------------------------------------------------------------------------------- | | `type` | string | Yes | ADD_TO_WHITELIST, INCREASE_SPEND_LIMIT, EXTEND_TIME_WINDOW, ADD_CATEGORY, or CUSTOM | | `reason` | string | Yes | Why this exception is needed | | `urgency` | string | No | LOW, NORMAL, HIGH, or CRITICAL | | `details` | object | No | Exception details (address, limit, etc.) | ### get_all | Parameter | Type | Required | Description | | ----------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------- | | `include` | string | No | Comma-separated sections: agent, wallets, policies, counterparties, transactions, alerts, analytics, capabilities, endpoints | | `analyticsPeriod` | string | No | 'day', 'week', 'month', or 'year' | --- ## Audit & Rate Limits (2) | Tool | Description | | ----------------- | ------------------------------------------- | | `get_audit_logs` | Get audit logs of agent actions | | `get_rate_limits` | Get current API rate limit status and usage | ### get_audit_logs | Parameter | Type | Required | Description | | ---------- | ------ | -------- | -------------------------- | | `action` | string | No | Filter by action type | | `resource` | string | No | Filter by resource type | | `from` | string | No | Start date (ISO string) | | `to` | string | No | End date (ISO string) | | `limit` | number | No | Results per page (max 100) | | `offset` | number | No | Pagination offset | --- # AI Assistant The AI Assistant (Conto AI) is a conversational assistant built into the dashboard that lets you manage your entire agent payment infrastructure using natural language. Instead of navigating forms and tables, you can type what you want and the assistant handles the rest. ## AI Assistant vs Conto Pay vs MCP Conto has three natural-language surfaces that differ by who acts, how you reach them, and whether they move funds onchain. The AI Assistant is the one where **you** act, from the dashboard chat panel: it configures agents, wallets, and policies, but does not execute payments onchain. The other two are [Conto Pay](https://conto.finance/docs/conto-pay/overview) (a Conto-hosted payment agent) and the [MCP Server](https://conto.finance/docs/mcp/overview) (your own external AI agent authenticated with an agent SDK key). See the [three-surface comparison table](https://conto.finance/docs/mcp/overview#mcp-vs-ai-assistant-vs-conto-pay) for the full breakdown. ## Opening the Assistant There are three ways to open the assistant panel: - **Floating button**: Click the purple sparkle button in the bottom-right corner of any dashboard page - **Sidebar link**: Click "Assistant" in the left navigation sidebar - **Keyboard shortcut**: Press `Cmd+J` (Mac) or `Ctrl+J` (Windows/Linux) from any page The assistant opens as a slide-out panel on the right side. You can continue using the dashboard while the panel is open. ## What You Can Do The assistant registry currently exposes **82 tools** across **8 categories**. That includes the core dashboard admin and read tools plus **39 hosted Conto Pay tools** that appear when the assistant is operating a Conto Pay workspace. ### Query Data Ask questions about your organization's state: ``` "How many agents do I have?" "Show me all transactions over $500 this week" "Are there any critical alerts?" "What's the trust score for our OpenAI counterparty?" "Give me a spending overview for all agents" "Explain what the overnight-guardrail policy actually does" ``` ### Manage Agents Create, configure, and control agents: ``` "Create an agent called Payment Bot of type OpenAI Assistant" "Pause the Marketing Agent" "Assign the spending-limit policy to the DevOps agent" "Generate an SDK key for the Research Agent" "Link the Operations wallet to Payment Bot with a $500 daily limit" ``` ### Configure Wallets Create wallets and manage spend limits: ``` "Create a new EVM wallet called Treasury" "Set the daily spend limit to $1000 for Payment Bot's wallet" "Freeze the compromised wallet" "What's the balance on all my wallets?" ``` ### Create Policies Describe rules in plain English and the assistant translates them into the correct policy type and rules: ``` "Create a policy that blocks spending over $500 per day" "Make a rule that only allows transactions Monday through Friday 9am-5pm EST" "Block all transactions to addresses not on the whitelist" "Require manual approval for any transaction over $1000" "Create a policy that denies gambling category transactions" ``` The assistant infers the correct `policyType`, `ruleType`, `operator`, and `action` from your description. If your description is ambiguous, it will ask for clarification. ### Manage Counterparties Track vendors and manage trust: ``` "Add a new counterparty called Stripe with type VENDOR" "Block the suspicious counterparty" "Verify the AWS counterparty" "Recalculate trust scores for all counterparties" ``` ### Handle Approvals Review and act on pending approval requests: ``` "Show me all pending approval requests" "Approve request clxyz123, looks legitimate" "Deny that request, the amount is too high" "Create an approval workflow that requires 2 approvals for transactions over $5000" ``` ### Bulk Operations Act on multiple entities at once: ``` "Pause all agents that have exceeded their daily limit" "Assign the new security policy to all active agents" "Set a $200 per-transaction limit for all agents" ``` ### Operate Conto Pay When the assistant is working inside a hosted Conto Pay workspace, it follows the normal hosted payment lifecycle: draft, authorize, approve when needed, then send. ``` "Show my Conto Pay workspace and payment draft" "Create a Conto Pay request link for 250 pathUSD with memo Invoice INV-100" "Search Conto Pay for Vendor Org and add it as a network recipient" "Approve the latest Conto Pay payment" "Send the approved Conto Pay payment now" ``` ### Detect Anomalies Proactive risk analysis: ``` "Are there any unusual spending patterns?" "Which counterparties have low trust scores?" "Show me all failed transactions this week" ``` ## Confirmation for Dangerous Actions The assistant won't silently execute high-impact actions. Depending on the risk level, you'll see an inline confirmation card before the action proceeds. ### Destructive Actions (Red) These require explicit confirmation with details about the impact: - Deleting an agent or policy - All bulk operations (pause all agents, assign policy to all, etc.) ### High-Impact Actions (Amber) These show a confirmation with a single "Confirm" button: - Suspending an agent - Freezing a wallet - Blocking a counterparty - Approving or denying payment requests - Generating SDK keys - Unlinking wallets or removing policies ### Preview Actions (Green) Creation tools show a preview card of what will be created, informational, not blocking: - Creating agents, wallets, policies, counterparties - Linking wallets to agents - Assigning policies - Updating spend limits (shows before/after) ## How It Works The assistant turns your request into the right Conto actions and streams the results back in the UI. When you send a message: 1. Your message is sent to the streaming endpoint 2. The assistant analyzes your intent and selects the appropriate action(s) 3. Requests run against your organization's data with normal permission checks 4. Results stream back in real-time with progress indicators 5. The assistant summarizes the results in natural language All assistant actions are scoped to your organization and recorded in the audit log. ## Limitations - **Authentication required**: The assistant only works for logged-in dashboard users. It cannot be accessed via API or SDK. - **Organization-scoped**: All operations are restricted to your current organization. You cannot query or modify data in other organizations. - **No raw blockchain execution**: The dashboard assistant can create wallets and manage configurations, but it does not expose arbitrary direct onchain sends. Hosted Conto Pay payment tools still run through the normal draft, authorization, approval, and send flow inside Conto Pay. - **Rate limited**: 30 messages per minute per user. If you hit the limit, wait a moment and retry. - **Message length**: Individual messages are limited to 4,096 characters. - **Session persistence**: Conversation history is saved in your browser and persists across page navigations and tab closures. Clearing browser data clears the history. - **No file uploads**: The assistant works with text only. You cannot upload CSVs or documents. - **Policy inference**: While the assistant is good at translating natural language to policies, complex multi-rule policies may need adjustment. Always review created policies in the Policies page. ## Tips - **Be specific**: "Create an agent called Research Bot of type Anthropic Claude" works better than "make an agent." - **Reference by name**: "Pause the Marketing Agent" is clearer than "pause agent clxyz123." The assistant searches by name. - **Ask for help**: "What can you do?" or "How do I set up a spending limit?" and the assistant will guide you. - **Review after bulk ops**: After bulk operations, check the affected entities in the dashboard to verify the changes. - **Use Cmd+J**: The keyboard shortcut is the fastest way to toggle the assistant from any page. --- # Assistant Tools Reference The AI Assistant currently exposes 82 tools organized into 8 categories. This page documents the core dashboard assistant tools plus the hosted Conto Pay workspace tools that appear when the assistant is operating a Conto Pay flow. ## Read Tools (10) These tools query data and never modify anything. No confirmation required. ### get_dashboard_summary Returns a high-level overview of your organization: agent counts by status, total wallet balance, transaction volume (last 7 days), active alerts, and counterparty risk. **Example prompts:** - "Give me an overview" - "What's the status of my organization?" --- ### list_agents Lists all agents with status, type, wallet balance, and transaction count. | Parameter | Type | Description | |-----------|------|-------------| | `status` | `ACTIVE \| PAUSED \| SUSPENDED \| ALL` | Filter by status | **Example prompts:** - "Show me all agents" - "Which agents are paused?" --- ### list_wallets Lists all wallets with balance, chain info, and linked agents. | Parameter | Type | Description | |-----------|------|-------------| | `chain_type` | `EVM \| SOLANA \| ALL` | Filter by blockchain | | `status` | `ACTIVE \| FROZEN \| CLOSED \| ALL` | Filter by status | --- ### list_policies Lists all policies with their rules and assigned agents. | Parameter | Type | Description | |-----------|------|-------------| | `policy_type` | `SPEND_LIMIT \| MERCHANT \| TIME_WINDOW \| ...` | Filter by type | | `is_active` | `boolean` | Filter by active status | --- ### list_transactions Lists recent transactions with filtering. | Parameter | Type | Description | |-----------|------|-------------| | `days` | `number` | Lookback period (default: 7) | | `agent_name` | `string` | Filter by agent name | | `min_amount` | `number` | Minimum amount | | `status` | `CONFIRMED \| FAILED \| PENDING \| REJECTED \| ALL` | Filter by status | | `limit` | `number` | Max results (default: 50, max: 100) | --- ### explain_policy Explains a policy in plain operator language, including what it allows, blocks, or escalates for approval. | Parameter | Type | Description | |-----------|------|-------------| | `policy_id` | `string` | Exact policy ID | | `policy_name` | `string` | Policy name (exact or partial match) | Provide either `policy_id` or `policy_name`. **Example prompts:** - "What does the vendor-protection policy do?" - "Explain policy cmm5c1pol001m49h7dmsuc22q in plain English" --- ### list_alerts Lists active alerts and warnings. | Parameter | Type | Description | |-----------|------|-------------| | `severity` | `CRITICAL \| HIGH \| MEDIUM \| LOW \| ALL` | Filter by severity | | `status` | `ACTIVE \| ACKNOWLEDGED \| RESOLVED \| ALL` | Filter by status | --- ### list_counterparties Lists counterparties with trust scores and verification status. | Parameter | Type | Description | |-----------|------|-------------| | `trust_level` | `TRUSTED \| VERIFIED \| UNKNOWN \| SUSPICIOUS \| BLOCKED \| ALL` | Filter by trust | --- ### get_agent_details Returns detailed information about a single agent, including linked wallets with spend limits, assigned policies with rules, and recent transactions. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` | `string` | Agent ID | | `agent_name` | `string` | Agent name (partial match) | Provide either `agent_id` or `agent_name`. The assistant searches by name if ID is not provided. --- ### detect_anomalies Analyzes recent activity for unusual patterns. Returns large transactions, failed transactions, low-trust counterparty interactions, and critical alerts. **Example prompts:** - "Any unusual activity?" - "Are there security concerns I should know about?" --- ## Agent Management Tools (11) ### create_agent Creates a new agent. Checks plan limits before creation. | Parameter | Required | Type | Description | |-----------|----------|------|-------------| | `name` | Yes | `string` | Agent name (1-100 chars) | | `agent_type` | Yes | `OPENAI_ASSISTANT \| ANTHROPIC_CLAUDE \| LANGCHAIN \| AUTOGPT \| CUSTOM` | Agent type | | `description` | No | `string` | Description (max 500 chars) | **Confirmation:** Preview card shown --- ### update_agent Updates an agent's name, description, or allowed contexts. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` or `agent_name` | `string` | Identify the agent | | `name` | `string` | New name | | `description` | `string` | New description | | `allowed_contexts` | `string[]` | Allowed contexts list | --- ### pause_agent / activate_agent Pause or reactivate an agent. Pausing temporarily stops all transactions. Both are reversible. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` or `agent_name` | `string` | Identify the agent | **Confirmation:** None (reversible) --- ### suspend_agent Suspends an agent, blocking all transactions until manually reactivated. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` or `agent_name` | `string` | Identify the agent | **Confirmation:** Amber (high impact) --- ### delete_agent Permanently deletes an agent (soft delete). The agent and its data become inaccessible. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` or `agent_name` | `string` | Identify the agent | **Confirmation:** Red (destructive) --- ### link_wallet_to_agent Links a wallet to an agent with delegation type and optional spend limits. | Parameter | Required | Type | Description | |-----------|----------|------|-------------| | `wallet_id` | Yes | `string` | Wallet to link | | `agent_id` or `agent_name` | Yes | `string` | Target agent | | `delegation_type` | No | `FULL \| LIMITED \| VIEW_ONLY \| PREAPPROVED \| ALLOWLIST` | Default: LIMITED | | `spend_limit_daily` | No | `number` | Daily limit in USD | | `spend_limit_per_tx` | No | `number` | Per-transaction limit | --- ### unlink_wallet_from_agent Removes a wallet from an agent. The agent loses access to that wallet's funds. **Confirmation:** Amber (high impact) --- ### assign_policy_to_agent / remove_policy_from_agent Assign or remove a policy from an agent. Accepts policy by ID or name. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` or `agent_name` | `string` | Target agent | | `policy_id` or `policy_name` | `string` | Target policy | **Confirmation:** Remove = Amber. Assign = Preview. --- ### generate_sdk_key Generates an SDK key for an agent to authenticate with the Conto SDK. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` or `agent_name` | `string` | Target agent | | `key_name` | `string` | Label (default: "Default") | | `scopes` | `string[]` | Permissions (default: payments:request, payments:execute, wallets:read) | **Confirmation:** Amber (security). The full key is shown only once. This assistant path creates a **custom-scoped standard SDK key** rather than using the dashboard or API presets. If you omit `scopes`, the assistant defaults to `payments:request`, `payments:execute`, and `wallets:read`. Keys created here still follow the platform's default expiration window. Use the [SDK Authentication](https://conto.finance/docs/sdk/authentication) flow if you want the full standard preset or the `admin` preset instead. --- ## Wallet Tools (4) ### create_wallet Creates a new wallet on EVM (Base) or Solana. External wallets are watch-only. | Parameter | Required | Type | Description | |-----------|----------|------|-------------| | `name` | Yes | `string` | Wallet name | | `chain_type` | No | `EVM \| SOLANA` | Default: EVM | | `custody_type` | No | `SPONGE \| EXTERNAL` | Default: SPONGE | | `import_address` | No | `string` | Required for EXTERNAL | --- ### update_wallet Renames a wallet. --- ### freeze_wallet Freezes a wallet, blocking all linked agents from transacting through it. **Confirmation:** Amber (high impact) --- ### update_agent_wallet_limits Updates spend limits on an agent-wallet link. | Parameter | Type | Description | |-----------|------|-------------| | `agent_id` or `agent_name` | `string` | Target agent | | `wallet_id` | `string` | Target wallet | | `spend_limit_daily` | `number` | New daily limit (0 = unlimited) | | `spend_limit_weekly` | `number` | New weekly limit | | `spend_limit_monthly` | `number` | New monthly limit | | `spend_limit_per_tx` | `number` | New per-tx limit | --- ## Policy Tools (5) ### create_policy Creates a new policy with rules. The assistant can infer the correct policy type and rules from natural language. | Parameter | Required | Type | Description | |-----------|----------|------|-------------| | `name` | Yes | `string` | Policy name | | `policy_type` | Yes | `SPEND_LIMIT \| MERCHANT \| TIME_WINDOW \| CATEGORY \| VELOCITY \| GEOGRAPHIC \| APPROVAL_THRESHOLD \| COUNTERPARTY \| WHITELIST \| EXPIRATION \| AGENT_IDENTITY \| COUNTERPARTY_IDENTITY` | Type | | `rules` | Yes | `array` | Array of rule objects | | `priority` | No | `number` | 0-100 (default: 50) | | `agent_ids` | No | `string[]` | Assign immediately | Each rule object has: `rule_type`, `operator`, `value`, `action` (ALLOW/DENY/REQUIRE_APPROVAL). **Natural language mapping:** | You say | Policy type | Rule type | |---------|-------------|-----------| | "limit to $500/day" | `SPEND_LIMIT` | `DAILY_LIMIT` | | "block over $1000" | `SPEND_LIMIT` | `MAX_AMOUNT` | | "Mon-Fri 9-5 only" | `TIME_WINDOW` | `TIME_WINDOW` + `DAY_OF_WEEK` | | "require approval above $5000" | `APPROVAL_THRESHOLD` | `REQUIRE_APPROVAL_ABOVE` | | "only allow these addresses" | `COUNTERPARTY` | `ALLOWED_COUNTERPARTIES` | | "block gambling" | `CATEGORY` | `BLOCKED_CATEGORIES` | See [Policy overview](https://conto.finance/docs/policies/overview) for the full canonical rule-type list. --- ### update_policy Updates a policy's name, description, priority, or replaces all rules. --- ### delete_policy Deletes a policy and removes it from all assigned agents. **Confirmation:** Red (destructive) --- ### activate_policy / deactivate_policy Toggle a policy's active state. Deactivated policies remain assigned but are not enforced. --- ## Counterparty Tools (5) ### create_counterparty Adds a new counterparty to track. | Parameter | Required | Type | Description | |-----------|----------|------|-------------| | `name` | Yes | `string` | Name | | `type` | No | `VENDOR \| EXCHANGE \| PROTOCOL \| DAO \| INDIVIDUAL \| OTHER` | Default: VENDOR | | `address` | No | `string` | Wallet address | | `domain` | No | `string` | Domain | | `category` | No | `string` | Category label | --- ### update_counterparty / verify_counterparty / block_counterparty / recalculate_trust - **update**: Modify name, type, category, description - **verify**: Mark as verified (sets trust score to 0.75) - **block**: Block counterparty and suspend all relationships (**Confirmation: Amber**) - **recalculate_trust**: Recalculate trust scores for all counterparties --- ## Approval Tools (5) ### list_approval_requests Lists pending approval requests with their status, amounts, and decisions. | Parameter | Type | Description | |-----------|------|-------------| | `status` | `PENDING \| APPROVED \| REJECTED \| EXPIRED \| ALL` | Default: PENDING | --- ### approve_request / deny_request Approve or deny a pending request. | Parameter | Required | Type | Description | |-----------|----------|------|-------------| | `request_id` | Yes | `string` | Request ID | | `comment` | No | `string` | Reason | **Confirmation:** Amber (high impact) for both --- ### create_approval_workflow Creates an approval workflow with trigger conditions. | Parameter | Required | Type | Description | |-----------|----------|------|-------------| | `name` | Yes | `string` | Workflow name | | `amount_threshold` | No | `number` | Trigger above this USD amount | | `required_approvals` | No | `number` | Approvals needed (default: 1) | | `timeout_hours` | No | `number` | Expiry (default: 24) | | `approver_roles` | No | `string[]` | Roles (default: OWNER, ADMIN) | | `new_recipients` | No | `boolean` | Trigger for unknown recipients | --- ### update_approval_workflow Updates a workflow's name, required approvals, timeout, or active state. --- ## Bulk Tools (3) All bulk operations require **destructive (red) confirmation** with a summary of affected entities. ### bulk_assign_policy Assigns a policy to multiple agents. | Parameter | Type | Description | |-----------|------|-------------| | `policy_id` or `policy_name` | `string` | Policy to assign | | `agent_ids` | `string[]` | Specific agents | | `all_active` | `boolean` | Assign to all active agents | --- ### bulk_pause_agents Pauses multiple agents. | Parameter | Type | Description | |-----------|------|-------------| | `agent_ids` | `string[]` | Specific agents | | `over_daily_limit` | `boolean` | Pause agents over daily spend limit | | `all_active` | `boolean` | Pause all active agents | --- ### bulk_update_limits Updates spend limits for multiple agent-wallet pairs. | Parameter | Type | Description | |-----------|------|-------------| | `agent_ids` | `string[]` | Specific agents (or `all_active: true`) | | `all_active` | `boolean` | Apply to all | | `spend_limit_daily` | `number` | New daily limit | | `spend_limit_per_tx` | `number` | New per-tx limit | --- ## Conto Pay Tools (39) These tools are available when the assistant is working inside a hosted Conto Pay workspace. They do not bypass Conto Pay controls; payment execution still follows the normal hosted draft, authorization, approval, and send path. For workflow guidance and operator prompts, see [Using the Assistant](https://conto.finance/docs/conto-pay/assistant-workflow). ### Workspace & Profile (10) | Tool | What it does | |------|--------------| | `get_conto_pay_status` | Returns the hosted workspace status, wallet readiness, active draft, recipients, and pending approvals. | | `get_conto_pay_profile` | Shows the hosted Conto Pay profile, handle, public links, listing state, and current readiness. | | `get_conto_pay_launch_evidence` | Returns the customer-safe launch evidence and support packet used for rollout and live-review prep. | | `create_conto_pay_profile_checkout_link` | Creates a tracked hosted pay or request checkout link from the Conto Pay profile. | | `update_conto_pay_profile` | Updates the public Conto Pay profile name, description, and directory-listing state. | | `refresh_conto_pay_wallet_balance` | Refreshes hosted wallet balance and readiness before a payment is authorized or sent. | | `request_conto_pay_testnet_funds` | Requests Tempo sandbox funds for the hosted wallet in test environments. | | `list_conto_pay_controls` | Shows the current hosted approval threshold and wallet spend controls. | | `set_conto_pay_approval_threshold` | Updates the hosted approval threshold used for Conto Pay payments. | | `set_conto_pay_wallet_limits` | Updates hosted wallet limits such as per-payment or daily caps. | ### Contacts, Recipients & Directory (13) | Tool | What it does | |------|--------------| | `list_conto_pay_recipients` | Lists saved hosted recipients available for the current workspace draft. | | `list_conto_pay_contacts` | Lists saved and recent Conto Pay contacts with aliases, favorites, defaults, and trust state. | | `prepare_conto_pay_contact_payment` | Starts a payment draft from a saved contact and its defaults. | | `rename_conto_pay_contact` | Renames a saved contact alias without changing the verified Conto Pay handle. | | `set_conto_pay_contact_payment_defaults` | Sets default amount, memo, or invoice details for a saved contact. | | `set_conto_pay_contact_payment_limits` | Sets contact-specific payment caps, approval requirements, and request permissions. | | `review_conto_pay_contact_trust` | Reviews and accepts the latest public profile state as the trusted snapshot for a contact. | | `set_conto_pay_contact_favorite` | Marks or unmarks a contact as a favorite. | | `search_conto_pay_directory` | Searches the hosted Conto Pay directory by handle, organization, or agent identity. | | `resolve_conto_pay_network_payee` | Resolves another hosted Conto Pay workspace before it is added as a network recipient. | | `prepare_conto_pay_network_payment` | Starts a payment draft to a resolved Conto Pay network payee. | | `add_conto_pay_network_recipient` | Adds a verified hosted Conto Pay workspace as a saved network recipient. | | `add_conto_pay_recipient` | Adds a manual recipient to the hosted allowlist for future payment drafts. | ### Requests, Drafting & Authorization (7) | Tool | What it does | |------|--------------| | `create_conto_pay_payment_request` | Creates a hosted request asking another Conto Pay workspace to pay you. | | `list_conto_pay_payment_requests` | Lists incoming and outgoing hosted Conto Pay payment requests. | | `prepare_conto_pay_request_payment` | Loads a hosted request into the current payment draft so the payer can review and act on it. | | `set_conto_pay_recipient` | Sets or replaces the current recipient on the hosted payment draft. | | `set_conto_pay_amount` | Sets the amount on the hosted payment draft. | | `set_conto_pay_purpose` | Sets the memo, purpose, or invoice context on the hosted payment draft. | | `authorize_conto_pay_payment` | Runs the hosted Conto Pay authorization step before approval or send. | ### Activity, Recovery & Hosted Approvals (9) | Tool | What it does | |------|--------------| | `list_conto_pay_activity` | Shows the hosted activity inbox across payments, requests, receipts, and next actions. | | `list_conto_pay_payments` | Lists hosted Conto Pay payments for the current workspace. | | `get_conto_pay_payment` | Returns the current state of a specific hosted Conto Pay payment or the latest one in context. | | `cancel_conto_pay_payment` | Cancels a hosted Conto Pay payment that should no longer proceed. | | `retry_conto_pay_payment` | Retries a failed hosted Conto Pay payment after the operator fixes the blocker. | | `list_conto_pay_approval_requests` | Lists Conto Pay approval requests that are still pending operator review. | | `approve_conto_pay_payment` | Approves a pending hosted Conto Pay payment. | | `deny_conto_pay_payment` | Denies a pending hosted Conto Pay payment. | | `send_conto_pay_payment` | Sends a hosted Conto Pay payment after it is authorized and approved. | --- # Trust & Risk Providers Conto integrates with external providers to enrich trust scores, screen for sanctions, and assess wallet reputation. These providers feed into the [trust score calculation](https://conto.finance/docs/introduction/concepts#trust-score-factors) (via the **Verification** factor, weighted at 20%) and the [policy rule engine](https://conto.finance/docs/policies/advanced#supported-rule-types). Reputation providers (like Fairscale) follow a **fail-open** design: if unavailable, Conto logs a warning and continues without blocking transactions. Sanctions screening providers follow a **fail-closed** design: if Chainalysis or TRM Labs is unavailable, the address is treated as sanctioned to prevent compliance gaps. ## Fairscale (Solana Reputation) [Fairscale](https://fairscale.xyz) provides composable reputation scoring for Solana wallets. It analyzes onchain behavioral signals, token holdings, transaction patterns, staking activity, and social connections, to produce a 0-100 reputation score. ### What it provides | Signal | Description | | ----------------- | ------------------------------------------------------------------------------------------------- | | **Score** (0-100) | Composite reputation score | | **Tier** | `bronze`, `silver`, or `gold` | | **Pillars** | Six scored dimensions: verification, reliability, social, track record, economic stake, ecosystem | | **Badges** | Behavioral badges (e.g. "LST Staker", "No Instant Dumps") | ### How Conto uses it - **Trust score enrichment**: For Solana counterparties with no existing network data, Fairscale scores are normalized (0-100 to 0.0-1.0) and used as the network trust score - **Cold-start enrichment**: Unknown Solana addresses get real trust scores instead of blank `UNKNOWN` defaults - **Policy rules**: Use `TRUST_SCORE` with the normalized 0.0-1.0 trust score to gate payments ### Policy rule Require a normalized trust score before allowing payments: ```json { "ruleType": "TRUST_SCORE", "operator": "GTE", "value": "0.5", "action": "ALLOW" } ``` Avoid `FAIRSCALE_MIN_SCORE` for production policy gates until the payment evaluator wires Fairscale context directly into rule evaluation. Fairscale enrichment still contributes through the normalized `TRUST_SCORE` path for unknown Solana counterparties. ### Availability Fairscale is **supported when the Conto deployment is configured with a `FAIRSCALE_API_KEY`**. If Fairscale is not configured, Conto skips reputation enrichment and continues without blocking the request. Note: Fairscale is **Solana-only**. It is automatically skipped for EVM addresses, and Conto also skips it when the provider is unavailable. ### SDK API response When querying trust data for a Solana address via the SDK, Fairscale data is included: ```json { "address": "CKs1E69a2e9TmH4mKKLrXFF8kD3ZnwKjoEuXa6sz9WqX", "fairscale": { "score": 8, "tier": "bronze", "confidence": 0.3, "isVerified": true, "pillars": { "verification": 0, "reliability": 8, "social": 14, "track_record": 0, "economic_stake": 41, "ecosystem": 5 }, "badges": [ { "id": "lst_staker", "label": "LST Staker", "tier": "gold" }, { "id": "no_dumper", "label": "No Instant Dumps", "tier": "silver" } ] } } ``` --- ## Sanctions Screening Conto screens wallet addresses against sanctions lists to support compliance requirements. Screening checks known sanctioned addresses (Tornado Cash, Lazarus Group, Garantex, etc.) and can be extended with enterprise providers for deeper risk analysis. ### Providers | Provider | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Local OFAC** (default) | Built-in OFAC SDN list, screens against known sanctioned wallet addresses. No API key needed. | | **Chainalysis** | Enterprise-grade blockchain risk scoring via the [Chainalysis KYT API](https://www.chainalysis.com/). Identifies sanctions exposure through cluster analysis. | | **TRM Labs** | Blockchain intelligence and compliance via the [TRM Labs Screening API](https://www.trmlabs.com/). Screens addresses for sanctions risk indicators. | ### Availability **Local OFAC** screening is **built into Conto**, no configuration needed. All organizations on [conto.finance](https://conto.finance) automatically get OFAC sanctions screening against known sanctioned addresses. For enterprise compliance needs, **Chainalysis** and **TRM Labs** provide deeper risk analysis. Contact [support](https://conto.finance) to enable enterprise sanctions screening for your organization. Note: Sanctions screening is **fail-closed** for enterprise providers: if Chainalysis or TRM Labs is unavailable, the address is treated as sanctioned to prevent compliance gaps. Local OFAC screening is always available since it uses a built-in address list. ### Policy rules Block transactions to sanctioned countries using `GEOGRAPHIC_RESTRICTION`: ```json { "ruleType": "GEOGRAPHIC_RESTRICTION", "operator": "IN_LIST", "value": "[\"CU\", \"IR\", \"KP\", \"SY\", \"RU\"]", "action": "DENY" } ``` See the [OFAC compliance section](https://conto.finance/docs/policies/advanced#geographic-restrictions-ofac) for the full list of sanctioned countries. Always consult legal counsel for compliance requirements. This is not legal advice. --- ## Network Intelligence In addition to external providers, Conto's built-in **Network Intelligence** aggregates anonymized trust signals across all organizations on the platform: - Cross-organization address flagging - Collective fraud detection - Automatic trust score adjustments based on network-wide behavior Note: Network Intelligence data is anonymized. Organizations share aggregate trust signals, not transaction details. --- ## Provider priority When multiple sources have data for an address, Conto applies them in this order: 1. **Conto Network Intelligence**: on-platform transaction history and cross-org signals 2. **Fairscale** (Solana only), external reputation scoring 3. **Sanctions screening**: compliance blocklists (always enforced regardless of trust score) Network Intelligence scores take precedence because they're based on real transaction history. Fairscale is used for cold-start enrichment when no network data exists. Sanctions screening operates independently and can block transactions regardless of trust score. ## Implementation Trust scoring is split into two complementary services: - **Per-organization trust** (`trust-score.ts`), your org's local view of a counterparty derived from your own transaction history with them. - **Network trust** (`network-trust-service.ts`), the cross-organization "credit bureau" view aggregated across all Conto customers. Most policies that reference a `TRUST_SCORE` rule consult the per-org service first and fall back to the network score for unknown addresses. See [Trust Scoring](https://conto.finance/docs/guides/trust-scoring) for the full data model. --- # Notification Channels Notification channels send approval requests and webhook lifecycle events to external platforms. Approvers can approve or reject directly from their email inbox, Slack workspace, Telegram chat, or WhatsApp conversation. Webhook channels can also receive machine-readable payment execution and Conto Pay request events for agents and back-office systems. ## How It Works ``` Payment triggers approval workflow → Conto generates secure, one-time action tokens → Notifications sent to all configured channels → Approver clicks Approve/Reject → Token is validated and consumed → Same approval logic as the dashboard ``` Every external decision uses the same `submitApprovalDecision()` path. Audit logs, atomic counters, webhook delivery, and race-condition safety all apply regardless of channel. ## Supported Channels | Channel | Delivery | How Approvers Act | | -------- | ------------------------------ | --------------------------------- | | Email | Rich HTML via Resend | Click Approve/Reject button links | | Slack | Block Kit message with buttons | Click interactive action buttons | | Telegram | Message with inline keyboard | Tap inline keyboard buttons | | WhatsApp | Interactive button message | Tap reply buttons | | Webhook | JSON POST with tokens | POST tokens back to Conto API | ## Setting Up Channels Go to **Settings** > **Channels** in the Conto dashboard, or use the REST API. Click **Add Channel** and select the platform: Email, Slack, Telegram, WhatsApp, or Webhook. Each channel type requires different configuration: | Channel | Required Config | |---------|----------------| | Email | Comma-separated recipient email addresses | | Slack | Bot token (`xoxb-...`) and channel ID | | Telegram | Bot token, chat ID, and optional webhook secret token | | WhatsApp | Phone number ID, access token, recipient numbers | | Webhook | HTTPS URL and a signing secret (`secret` in config) | Webhook targets must resolve to public addresses. Conto rejects loopback, private, link-local, and other internal-only destinations. In production, webhook channels must use HTTPS. Choose which events trigger notifications: | Event | When It Fires | Notes | |-------|--------------|-------| | `approval.requested` | New payment needs approval | Available on all channel types | | `approval.decided` | Someone approved or rejected | Available on all channel types | | `approval.escalated` | Request escalated after timeout | Available on all channel types | | `approval.expired` | Request expired without resolution | Available on all channel types | | `payment.executed` | Payment is submitted onchain | `WEBHOOK` channels only | | `conto_pay.request.received` | A hosted Conto Pay request is sent to the payer | `WEBHOOK` channels only | | `conto_pay.request.paid` | A hosted Conto Pay request is paid | `WEBHOOK` channels only | | `conto_pay.request.rejected` | A hosted Conto Pay request is rejected | `WEBHOOK` channels only | | `conto_pay.request.expired` | A hosted Conto Pay request expires | `WEBHOOK` channels only | Click the test button to send a sample notification and verify your configuration. ## Channel Configuration Details Uses Resend to deliver rich HTML emails. Each eligible approver receives their own email with unique Approve and Reject buttons. **Config fields:** - `recipients` - List of email addresses. Only addresses matching eligible approvers receive actionable emails. Clicking a button opens a browser, validates the token, submits the decision, and shows a confirmation page. Requires a Slack app with the `chat:write` bot scope. Messages use Block Kit with payment details and interactive Approve/Reject buttons. **Config fields:** - `botToken` - Your Slack app's bot token (`xoxb-...`) - `channelId` - The Slack channel ID to post messages to **Setup:** 1. Create a Slack app at [api.slack.com/apps](https://api.slack.com/apps) 2. Add the `chat:write` bot scope 3. Install the app to your workspace 4. Set the interactivity request URL to `https://conto.finance/api/webhooks/slack` 5. Set `SLACK_SIGNING_SECRET` in your Conto environment When an approver clicks a button, Slack sends the interaction to Conto. The message is updated to show the result. Uses the Telegram Bot API to send messages with inline keyboard buttons. **Config fields:** - `botToken` - Your Telegram bot token from [@BotFather](https://t.me/BotFather) - `chatId` - The chat or group ID to send messages to - `secretToken` - Optional webhook secret. When set, Conto requires Telegram to send the matching `x-telegram-bot-api-secret-token` header on every callback. **Setup:** 1. Create a bot via @BotFather 2. Set the webhook URL: `https://api.telegram.org/bot{token}/setWebhook?url=https://conto.finance/api/webhooks/telegram` 3. If you configure `secretToken`, include Telegram's `secret_token` option when calling `setWebhook` 4. Add the bot to your group chat Conto only accepts interactive callbacks for the configured `chatId`. If `secretToken` is set, Telegram callbacks must also include the matching secret header before approval tokens are processed. When an approver taps a button, the message updates to show the result. Uses the WhatsApp Cloud API to send interactive button messages. **Config fields:** - `phoneNumberId` - Your WhatsApp Business phone number ID - `accessToken` - Permanent access token from Meta - `recipientNumbers` - Phone numbers in international format (e.g., `+1234567890`) **Setup:** 1. Register at [developers.facebook.com](https://developers.facebook.com) 2. Create a WhatsApp Business app 3. Set the webhook URL to `https://conto.finance/api/webhooks/whatsapp` 4. Set `WHATSAPP_APP_SECRET` and `WHATSAPP_VERIFY_TOKEN` in your Conto environment 5. Subscribe to the `messages` webhook field Sends a signed JSON payload to any HTTPS endpoint. Use this for custom integrations that need to review and submit approval decisions. **Config fields:** - `url` - Your HTTPS endpoint URL - `secret` - Signing secret for HMAC verification (required; `signingSecret` and `webhookSecret` are accepted aliases) Every delivery is signed: the `X-Conto-Signature` header carries an HMAC-SHA256 of `${timestamp}.${rawBody}` computed with your channel secret. Verify it before trusting the payload. **Validation rules:** - The destination must resolve to a public IP address - Private, loopback, link-local, and `.internal` / `.local` hosts are rejected - In production, only `https://` webhook targets are accepted **Payload format:** ```json { "event": "approval.requested", "approvalRequestId": "clxyz123...", "paymentDetails": { "amount": 500, "currency": "USDC", "recipientAddress": "0x5678...", "agentName": "Treasury Agent" }, "tokens": { "approve": "base64url-token", "reject": "base64url-token" }, "actionUrl": "https://conto.finance/api/approvals/action", "timestamp": "2026-04-06T12:00:00Z" } ``` To submit a decision, POST the token back to the `actionUrl`: ```bash curl -X POST https://conto.finance/api/approvals/action \ -H "X-Action-Token: base64url-token" \ -H "Content-Type: application/json" \ -d '{"comment": "Approved via external review system"}' ``` ## Conto Pay Lifecycle Webhooks Webhook channels can subscribe to hosted Conto Pay request lifecycle events: `conto_pay.request.received`, `conto_pay.request.paid`, `conto_pay.request.rejected`, and `conto_pay.request.expired`. The `received` event is delivered to the payer organization. Terminal outcomes (`paid`, `rejected`, and `expired`) are delivered to both the payer and payee organizations when they have matching active webhook channels. Each Conto Pay webhook payload includes absolute hosted links for the request review page and the payer action page. These match the copyable links shown in the Conto Pay activity inbox and hosted request review screens, so external systems and human operators can refer to the same URL. ```json { "event": "conto_pay.request.paid", "request": { "id": "ipr_...", "status": "PAID", "amount": 250, "currency": "pathUSD", "purpose": "Invoice INV-100", "invoiceId": "INV-100", "dueDate": "2026-06-30T00:00:00.000Z", "expiresAt": "2026-07-01T00:00:00.000Z", "createdAt": "2026-06-14T12:00:00.000Z", "updatedAt": "2026-06-14T12:05:00.000Z", "direction": "incoming" }, "payer": { "agentId": "agent_payer", "agentName": "Buyer AP Agent", "agentSlug": "accounts-payable", "organizationId": "org_buyer", "organizationName": "Buyer Inc", "organizationSlug": "buyer-inc", "handle": "@buyer-inc/accounts-payable" }, "payee": { "agentId": "agent_payee", "agentName": "Vendor AR Agent", "agentSlug": "accounts-receivable", "organizationId": "org_vendor", "organizationName": "Vendor LLC", "organizationSlug": "vendor-llc", "handle": "@vendor-llc/accounts-receivable" }, "links": { "requestUrl": "https://conto.finance/pay-requests/ipr_...", "payerActionUrl": "https://conto.finance/conto-pay?request=ipr_..." }, "recipientOrganizationId": "org_buyer", "transaction": { "id": "tx_...", "txHash": "0xabc123", "status": "CONFIRMED" }, "timestamp": "2026-06-14T12:05:00.000Z" } ``` Use `request.direction` to render the event from the receiving organization's point of view: `incoming` means the organization is the payer, while `outgoing` means the organization created the request and is waiting on the payer. ## REST API Manage channels programmatically: ```bash # List channels curl https://conto.finance/api/notification-channels \ -H "Authorization: Bearer $API_KEY" # Create a channel curl -X POST https://conto.finance/api/notification-channels \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "channelType": "SLACK", "name": "Treasury Channel", "config": { "botToken": "xoxb-...", "channelId": "C012345" }, "eventTypes": ["approval.requested", "approval.decided", "payment.executed"] }' # Test a channel curl -X POST https://conto.finance/api/notification-channels/{id}/test \ -H "Authorization: Bearer $API_KEY" # Delete a channel curl -X DELETE https://conto.finance/api/notification-channels/{id} \ -H "Authorization: Bearer $API_KEY" ``` ## Action Token Security Action tokens are the core security mechanism for external approvals. - **32 bytes of cryptographic randomness**, base64url-encoded - **Protected at rest**. Plaintext tokens are not retained after issuance - **One-time use**. Tokens cannot be reused after a decision is recorded - **Time-limited**. Tokens expire when the approval request expires (default 24 hours) - **Per-user, per-action**. Each approver gets separate Approve and Reject tokens - **Full audit trail**. Every decision records the channel, token ID, IP address, and user agent ## Environment Variables | Variable | Required For | Description | | ----------------------- | ------------ | -------------------------------------------------- | | `RESEND_API_KEY` | Email | Resend API key for sending emails | | `SLACK_SIGNING_SECRET` | Slack | Slack app signing secret for webhook verification | | `WHATSAPP_APP_SECRET` | WhatsApp | Meta app secret for webhook signature verification | | `WHATSAPP_VERIFY_TOKEN` | WhatsApp | Token for Meta webhook verification challenge | ## Webhook Payload Validation Inbound webhook payloads from Slack, Telegram, and WhatsApp are validated against typed Zod schemas before processing. Malformed payloads are rejected with a `400` response and never reach handler logic. Signature verification (HMAC) still runs first for all three providers regardless of payload shape. ## Delta Verification Channel (pilot) Delta is a guided pilot that routes payment approvals through an external invoice-verification service. It is not a self-serve channel type: Conto activates it for your organization during onboarding as a standard `WEBHOOK` channel with additional Delta configuration. For access, onboarding inputs, and activation details, see [Delta Verification Setup](https://conto.finance/docs/guides/delta-setup); to validate the live flow end to end, see [Delta Smoke Test](https://conto.finance/docs/guides/delta-smoke-test). Two things differ from a standard webhook channel: **1. Enriched payloads.** When `approval.requested` fires for a Delta-enabled channel, the outbound payload carries the full payment context in `paymentDetails` (`paymentRequestId`, `senderAddress`, `chainId`, `category`, `memo`, `executionMode`, `walletId`, `context`, `metadata`, and timestamps, in addition to the standard fields) plus invoice context from the typed `PaymentRequest` invoice record when present, with a fallback to legacy `context.invoice` data for older requests. It also includes the counterparty record and a pair of pre-minted single-use action tokens so the pilot verification service can call back immediately. Abbreviated: ```json { "event": "approval.requested", "approvalRequestId": "ar_...", "paymentDetails": { /* full payment context, plus: */ "counterparty": { "id": "cp_...", "name": "Vendor LLC", "address": "0x...", "trustLevel": "TRUSTED", "approvalStatus": "APPROVED" } }, "invoice": { "vendorId": "...", "vendorAddress": "0x...", "invoiceId": "INV-1042", "invoiceHash": "...", "invoiceSourceUrl": "https://...", "invoicePayload": { /* raw invoice */ }, "expectedAmount": "12345", "currency": "USDC", "dueDate": "2026-06-01" }, "actionToken": { "approveToken": "", "rejectToken": "", "expiresAt": "...", "callbackUrl": "https://app.example/api/approvals/action" }, "dashboardUrl": "https://app.example/dashboard?approvalRequestId=ar_...", "timestamp": "..." } ``` If the same Delta channel also subscribes to `payment.executed`, Conto sends an execution webhook after the payment is submitted onchain, with the same invoice enrichment plus a `transaction` block (`transactionId`, `transactionHash`, `explorerUrl`, `executedAt`), so the verifier can mark its invoice row `PAID` without polling. Non-Delta `WEBHOOK` channels keep the standard payload shape; this enrichment only appears for organizations that Conto has enabled for Delta. HMAC signing is identical to the standard webhook channel (`X-Conto-Signature: sha256(${X-Conto-Timestamp}.${rawBody})`). **2. Signed decision callback.** For production verification services, prefer the signed callback route to record the decision and (optionally) attach a proof reference: ```bash POST /api/internal/approval-requests/{approvalRequestId}/decide X-Conto-Timestamp: 2026-05-26T18:00:00Z X-Conto-Signature: Content-Type: application/json { "decision": "APPROVED", "comment": "Verified against template invoice_payment_guard", "verification": { "proofType": "delta_signed", "proofRef": "https://delta.example/proofs/abc", "templateId": "...", "intentUuid": "...", "evidenceHash": "...", "reason": "OK" } } ``` The `actionToken.callbackUrl` in the webhook payload remains the backwards-compatible demo path: POST the `approveToken` or `rejectToken` to `/api/approvals/action` with the same optional `verification {}` block. Both routes persist the same verification data, and proof material surfaces on the **Delta** tab in the dashboard once your organization has Delta enabled. ## Next Steps ### Approval Workflows Link: https://conto.finance/docs/policies/advanced Configure multi-approval workflows with escalation and sequential approvals ### Securing Agents Link: https://conto.finance/docs/guides/securing-agents Set up spending limits and approval thresholds for your agents --- # Choose Your Integration If you are deciding between the Conto SDK, the OpenClaw skill, the Hermes skill, x402, and MPP, start here. The right path usually comes down to three questions: 1. Where does your agent run? 2. Who holds the wallet keys? 3. Are you making one-off payments or repeated protocol-native API payments? ## Quick Decision Matrix | Situation | Best fit | Why teams pick it | Start here | | ------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | You are building your own backend, tool runner, or agent service | **Conto SDK / REST API** | Maximum control over payment, policy, and approval flows | [/sdk/installation](https://conto.finance/docs/sdk/installation) | | You already run agents in OpenClaw or Nous Hermes | **Agent Skill** | Fastest path to policy enforcement inside the OpenClaw and Hermes ecosystems | [/sdk/skills](https://conto.finance/docs/sdk/skills) | | You want operator workflows from Claude or another MCP client | **MCP Server** | Gives humans and assistant tools a shared control center for agents, policies, and trust checks | [/mcp/overview](https://conto.finance/docs/mcp/overview) | | Your agent pays for APIs one request at a time | **x402** | Best fit for pay-per-call API commerce with explicit `402 Payment Required` flows | [/guides/x402-api-payments](https://conto.finance/docs/guides/x402-api-payments) | | Your agent will make many charges against one service in a single session | **MPP** | Better economics and ergonomics for repeated or streaming usage | [/guides/mpp-session-payments](https://conto.finance/docs/guides/mpp-session-payments) | | You need human review, dual control, or escalation | **Approval workflows** | Adds four-eyes review without blocking every low-risk payment | [/guides/approval-workflows](https://conto.finance/docs/guides/approval-workflows) | | You need to route based on recipient risk and reputation | **Trust scoring** | Adds counterparty-aware controls before money leaves the wallet | [/guides/trust-scoring](https://conto.finance/docs/guides/trust-scoring) | | You need to prove the human behind an agent is compliant before purchase | **Conto SDK + AgentScore** | Adds verified-human, KYC, sanctions, and jurisdiction gating before settlement | [/guides/recipes#accept-agent-payments-through-a-merchant-gate](https://conto.finance/docs/guides/recipes#accept-agent-payments-through-a-merchant-gate) | ## Choose the Control Surface First ### Conto SDK / REST API Choose the SDK or REST API when you own the agent runtime and want the most direct integration. - Best for custom backends, agent orchestration services, LangChain/OpenAI wrappers, and custom tools. - Works well with both managed wallets and agent-held external wallets. - Gives you the cleanest path to custom approval handling, policy creation, analytics, and audit automation. ### OpenClaw Skill Choose OpenClaw when your agent already lives inside OpenClaw and typically uses an external wallet or wallet MCP tools. - Install is fast through ClawHub (`npx clawhub install conto`), which installs the helper script with the skill. - The most common pattern is `approve -> transfer -> confirm`. - Requires `curl`, `jq`, and `python3` on `PATH` for the helper; invoke it with `bash skills/conto/conto-check.sh`. - Best when you want Conto to be the policy gate while your existing OpenClaw wallet stack keeps execution. ### Hermes Skill Choose the [Nous Hermes](https://hermes-agent.nousresearch.com/) skill when your agent is already running on Hermes and you want Conto policy enforcement to feel native in that workflow. - Installs through Hermes well-known skill discovery (`hermes skills install well-known:... --force`) after you review the install scan. - Good fit for natural-language policy management and wallet-aware agent operations. - Requires `curl`, `jq`, and `python3` on `PATH` for the helper; invoke it with `bash ~/.hermes/skills/conto/conto-check.sh`. - Supports the same underlying Conto approval and policy engine as the SDK flow. ### MCP Server Choose MCP when a human operator, analyst, or assistant needs to inspect trust, policies, alerts, and agent state alongside the runtime integrations above. - Good fit for finance, ops, and security teams. - Complements SDK, OpenClaw, and Hermes rather than replacing them. ## Then Choose the Payment Rail | Rail | Best for | Typical execution pattern | Primary controls | | ---------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------- | | **Standard onchain payment** | Vendor payouts, treasury actions, direct wallet transfers | `request -> execute` or `approve -> confirm` | Spend limits, approvals, trust rules, time windows | | **x402** | Paid APIs where each request is separately priced | `402 challenge -> pre-authorize -> pay -> retry -> record` | Price ceilings, service allowlists, endpoint velocity, service budgets | | **MPP** | Repeated requests to one service, streaming, session-based work | `pre-authorize -> open session -> charge -> close -> record` | Session budgets, max concurrent sessions, max duration, service allowlists | Info: You can mix these choices. For example, a Hermes or OpenClaw agent can still use x402 or MPP; the framework choice decides the control surface, while x402 and MPP decide the payment rail. For x402 and MPP record calls, send aggregate settlement fields at the top level and per-call details in `batchItems`. Session budget checks use the recorded `sessionId`, so use a stable session identifier for the lifetime of one paid API session. ## Wallet Model: Integrated vs External | Wallet model | Best fit | What changes | Can Conto block a direct spend outside Conto? | | ------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------- | | **Integrated wallet** (`PRIVY` or `SPONGE`) | Teams that want Conto to orchestrate execution after policy approval | Usually one Conto call can both authorize and execute | **Yes** | | **External wallet** (`EXTERNAL`) | Agents that already control their own keys or use external wallet tools | Agent asks Conto for approval, executes transfer itself, then confirms back | **No** | If your agent already has wallet tools in OpenClaw or Hermes, the external model is often the fastest adoption path. If you want fewer moving parts, integrated wallets are usually the cleanest production setup. Note: External wallets can still use the same policy engine, approval workflows, and audit trail. The difference is that Conto governs the flow that goes through Conto. It does not cryptographically block a direct transfer your signer makes outside Conto. ## Canonical Examples ### 1. Custom agent with managed execution - Runtime: custom backend - Wallet model: integrated - Rail: standard onchain payment - Flow: `POST /api/sdk/payments/request` with `autoExecute: true` - Best for: vendor payments, infra spend, low-latency production flows ### 2. OpenClaw agent with external wallet controls - Runtime: OpenClaw - Wallet model: external - Rail: standard onchain payment - Flow: `POST /api/sdk/payments/approve -> transfer -> POST /api/sdk/payments/{id}/confirm` - Best for: teams that already have wallet MCP tools and want to add guardrails without re-architecting ### 3. Hermes agent paying APIs with x402 - Runtime: Hermes - Wallet model: usually external - Rail: x402 - Flow: `402 challenge -> /api/sdk/x402/pre-authorize -> pay -> retry -> /api/sdk/x402/record` - Best for: controlled pay-per-call API buying ### 4. SDK integration for high-frequency MPP sessions - Runtime: custom backend - Wallet model: integrated or external - Rail: MPP - Flow: `pre-authorize deposit -> open session -> repeated charges -> close session -> record settlement` - Best for: repeated calls to the same service where per-call onchain settlement would be wasteful ### 5. AgentScore-gated merchant checkout - Runtime: custom backend or skill-driven agent - Wallet model: usually integrated - Rail: standard onchain payment - Flow: `request -> VERIFICATION_REQUIRED (if needed) -> human verifies -> auto resume -> execute` - Best for: agent purchases that must prove the human behind the agent passed merchant compliance checks ## Decision Tree ```mermaid flowchart TD A["Where does the agent run?"] --> B["OpenClaw"] A --> C["Hermes"] A --> D["Custom runtime"] A --> E["Operator assistant / MCP client"] B --> F["Use OpenClaw skill"] C --> G["Use Hermes skill"] D --> H["Use Conto SDK or REST API"] E --> I["Use MCP server"] F --> J["Who holds keys?"] G --> J H --> J J --> K["Integrated wallet"] J --> L["External wallet"] K --> M["Prefer request + autoExecute"] L --> N["Prefer approve + confirm"] M --> O["Need paid API calls?"] N --> O O --> P["One request at a time: x402"] O --> Q["Many requests in one session: MPP"] O --> R["Direct transfers: standard onchain flow"] ``` ## Related Guides ### Architecture Patterns Link: https://conto.finance/docs/guides/architecture-patterns See the core payment, approval, x402, and MPP diagrams ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste commands for SDK, OpenClaw, Hermes, x402, MPP, approvals, and trust ### Approval Workflows Link: https://conto.finance/docs/guides/approval-workflows Add four-eyes review and escalation paths ### Trust Scoring Link: https://conto.finance/docs/guides/trust-scoring Understand counterparty risk, verification, and trust-based controls --- # Developer Tooling Use this page when you want a working integration, not just conceptual docs. Start with the CLI, verify the runtime with setup probes, then add API docs, MCP tools, webhooks, and audit trails as you move toward production. ## Fastest First Run ```bash npx @conto_finance/create-conto-agent ``` The CLI provisions an agent, wallet, policy, SDK key, and local config. Choose **Tempo Testnet** for the first run so you can fund with free `pathUSD` and exercise the real request and execute flow without real funds. After the wizard completes, run the generated example: ```bash npx tsx example.ts ``` ## Toolbelt | Tool | Use it for | Link | | --------------- | ------------------------------------------------- | ----------------------------------------------- | | CLI quickstart | One-command agent, wallet, policy, and key setup | [CLI quickstart](https://conto.finance/docs/cli/quickstart) | | SDK setup probe | Verify agent status, wallets, scopes, and limits | [`GET /api/sdk/setup`](https://conto.finance/docs/sdk/installation) | | OpenAPI | Generate clients and inspect request schemas | [API reference](https://conto.finance/api-docs) | | MCP server | Give Claude/Codex/Cursor agent tools access | [Install MCP server](https://conto.finance/docs/mcp/install) | | Webhooks | Receive signed payment and agent lifecycle events | [Webhooks](https://conto.finance/docs/guides/webhooks) | | Audit logs | Review policy decisions and sensitive actions | [Audit logs](https://conto.finance/docs/guides/audit-logs) | | Policy testing | Dry-run and validate policy behavior | [Policy testing](https://conto.finance/docs/guides/policy-testing) | ## Setup Probe Before making a payment, call the setup endpoint with the same SDK key your agent will use: ```bash curl https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_API_KEY" ``` The CLI wraps the same endpoint with pass/fail checks: ```bash npx conto doctor ``` Check these fields in the response: - `agent.status` is `ACTIVE` - at least one wallet is linked and funded - `scopes` includes `payments:request` - execute-capable flows include `payments:execute` - limits and policies match the agent's expected spending envelope ## Generated Clients The OpenAPI document is the contract for generated clients: ```bash curl https://conto.finance/api/openapi > conto-openapi.json ``` Use it with your preferred generator or import it into tools like Postman, Bruno, or an internal API portal. The interactive reference is available at [conto.finance/api-docs](https://conto.finance/api-docs). ## Production Readiness Before giving an autonomous agent production funds, confirm: - SDK keys are named by environment and agent, for example `prod-research-agent` - each runtime uses the narrowest key type and scopes it needs - webhook signature verification uses the raw request body - testnet policy results match the production policy envelope - organization API keys are stored only in backend or CI systems - agent SDK keys are rotated after demos, contractor access, or leaked logs - audit logs are reviewed after the first live payment ## Useful Next Reads ### Choose Your Integration Link: https://conto.finance/docs/guides/choose-your-integration Decide between SDK, REST, MCP, OpenClaw, Hermes, x402, and MPP. ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste API, SDK, skill, and payment examples. ### Authentication Link: https://conto.finance/docs/sdk/authentication Understand SDK keys, org API keys, key types, and scopes. ### Testing Payments Link: https://conto.finance/docs/guides/testing-payments Safely test with Tempo Testnet before moving money in production. --- # Conto Hybrid Integration Use this pattern when your app already owns the runtime, wallet flow, or provider settlement path and you want Conto to enforce policy before money moves. In a hybrid integration: - your app decides when a paid action is about to happen - Conto approves, denies, or routes that payment to review - your app executes the actual settlement - your app records the final spend back to Conto ## What hybrid means In managed execution, Conto both authorizes and orchestrates payment through an integrated wallet. In hybrid execution, Conto stays in the control center while your app stays in the execution path. That makes hybrid a strong fit when you already have: - an existing wallet or treasury layer - custom routing or fallback logic - provider-specific settlement code - x402 or MPP payment handling in your own runtime The main rule is simple: Conto should make the authorization decision before your app executes the payment. If your app settles first and reports later, Conto becomes an analytics mirror instead of a real spend-control layer. ## When to use hybrid Choose hybrid when: - you want to keep your current runtime architecture - paid actions are embedded inside a larger workflow - you need policy checks before API calls, machine payments, or provider settlements - you want Conto controls without moving all execution into Conto-managed wallets Hybrid is especially useful for agent platforms, AI orchestration products, marketplaces, and machine-payment systems. ## Responsibility split ### Your app owns - the user experience - workflow and routing logic - provider selection and fallback behavior - execution timing - the settlement call itself - app-specific state and reporting ### Conto owns - spend policies - approval thresholds - allowlists and counterparties - budget controls - runtime authorization - audit visibility - spend analytics ## Canonical flow ```mermaid flowchart LR App["Your app"] --> Context["Build payment context"] Context --> Authorize["Conto authorization"] Authorize --> Gate{"Decision"} Gate -->|"Approved"| Execute["Your app executes payment"] Gate -->|"Requires review"| Review["Approval workflow"] Gate -->|"Denied"| Stop["Do not settle"] Review -->|"Approved"| Execute Review -->|"Rejected"| Stop Execute --> Record["Record final spend back to Conto"] Record --> Audit["Audit logs, analytics, budgets"] ``` ## Recommended integration steps 1. Keep the product-facing controls in your app. 2. Provision a Conto agent for each managed actor. 3. Create and protect a runtime credential for that actor. 4. Sync supported controls into Conto policy objects. 5. Call Conto before the paid action executes. 6. Execute the payment in your own runtime only if approved. 7. Record the settled spend back to Conto. ## Common policy mappings | Product control | Conto primitive | | --- | --- | | Max spend per action | `SPEND_LIMIT` | | Budget per session or run | `BUDGET_ALLOCATION` | | Allowed providers or vendors | `COUNTERPARTY` or `WHITELIST` | | Human review threshold | `APPROVAL_THRESHOLD` | | Time-based restrictions | Time or blackout-related policy types | ## Verification checklist Use this checklist after setup: - each managed actor gets a dedicated Conto binding - runtime credentials stay server-side and encrypted at rest - policy changes update Conto objects - pre-authorization happens before settlement - denied payments never reach the execution layer - successful payments are recorded back to Conto - operators can see runtime status and recent events ## Related guides ### Choose Your Integration Link: https://conto.finance/docs/guides/choose-your-integration Compare SDK, OpenClaw, Hermes, x402, and MPP paths ### Architecture Patterns Link: https://conto.finance/docs/guides/architecture-patterns See the core managed, external wallet, x402, and MPP diagrams ### x402 API Payments Link: https://conto.finance/docs/guides/x402-api-payments Govern pay-per-call API payments before execution ### MPP Session Payments Link: https://conto.finance/docs/guides/mpp-session-payments Control repeated charges inside a session budget --- # Custody Modes Before you link a wallet, decide which custody mode you want. In Conto, these are two separate questions: 1. **Custody**. Who can sign the transfer? 2. **Enforcement**. Can Conto actually stop the transfer, or only govern the path that goes through Conto? ## Quick Comparison | Mode | Keys held by | Typical flow | Can Conto block a direct spend signed outside Conto? | Best for | | -------------------------------------- | ------------------------------------- | ---------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------ | | **Managed** (`PRIVY`, `SPONGE`) | The custody provider | `request -> execute` | **Yes.** Conto stays in the execution path. | Teams that want Conto-orchestrated execution | | **External / Watch-Only** (`EXTERNAL`) | You, your agent, or your wallet stack | `approve -> transfer -> confirm` | **No.** Conto only controls payments routed through Conto. | Self-custody, MPC wallets, existing wallet tools | | **Smart Contract** (`SMART_CONTRACT`) | Onchain wallet contract | `request -> contract execute -> confirm` | **Yes.** Transfers require the contract + Conto signature path. | Strongest onchain enforcement model | ## What Policies Mean In Each Mode ### Managed Wallets With `PRIVY` or `SPONGE`, the wallet provider holds the keys and Conto stays in the execution path. This is the strongest standard setup for policy enforcement. - Conto evaluates the payment. - If approved, Conto orchestrates execution. - If denied, the payment does not execute through Conto. - The agent uses the standard `request -> execute` flow. For `PRIVY`, you now have two setup options: - **Create a new Privy wallet through Conto** and let Conto mint the wallet record for you. - **Attach an existing Privy-backed wallet** by creating the Conto wallet with `custodyType=PRIVY`, `externalWalletId=`, and `address=`. Attach requests are idempotent per `externalWalletId + chainId` or `address + chainId` inside the organization, so you can safely retry provisioning calls from your backend. This existing-Privy attach flow only works when the wallet is visible to the same Privy app Conto is configured to use for managed execution. If the wallet lives in a different Privy app or a different wallet stack, register it as `EXTERNAL` instead. ## External / Watch-Only Wallets When you import a wallet, Conto registers it as `EXTERNAL` custody. You keep the keys, and your agent or wallet stack signs the transaction. - Conto can still evaluate policies before the transfer. - Conto can still require approval, record the payment, and keep the audit trail. - The agent uses the `approve -> transfer -> confirm` flow. - Conto **cannot cryptographically block** a direct transfer signed outside Conto. You can register an external wallet directly with `custodyType=EXTERNAL` plus `address`, or use the existing watch-only import flow. Both end up as `EXTERNAL` custody inside Conto. That means external wallets are best described as **self-custody with policy gating**, not as fully Conto-controlled execution. External wallets can have policies. Those policies are enforced when the payment goes through Conto. They are not a guarantee against a direct self-signed transfer outside Conto. ## Smart Contract Wallets Smart contract wallets are the strongest enforcement option. - Funds stay in an onchain contract wallet. - Transfers require the approved contract path and Conto's signature. - This gives you cryptographic enforcement without giving Conto direct key custody. ## Which Flow Should My Agent Use? | Wallet model | Endpoints to use | | ------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | **Managed** (`PRIVY`, `SPONGE`) | `POST /api/sdk/payments/request` then `POST /api/sdk/payments/{id}/execute` | | **External** (`EXTERNAL`) | `POST /api/sdk/payments/approve` then your signer/wallet transfer, then `POST /api/sdk/payments/{id}/confirm` | | **Smart Contract** (`SMART_CONTRACT`) | Request approval, execute through the contract path, then confirm | ## How To Choose - Pick **Managed** if you want the cleanest production path and want Conto to stay in the execution flow. - Pick **External** if you already have a wallet stack, MPC signer, or agent-held wallet and want to keep that setup. - Pick **Smart Contract** if you want the strongest onchain enforcement model. ## Related Guides ### Choose Your Integration Link: https://conto.finance/docs/guides/choose-your-integration Compare SDK, OpenClaw, Hermes, x402, and MPP ### Payments API Link: https://conto.finance/docs/sdk/payments See the managed and external payment flows --- # Delta Verification Setup Use this guide when you want Conto to route your organization's payment approvals through the pilot Delta verification service. Delta sits in the approval step for this pilot. When a matching payment request is created, Conto opens an approval request, sends the pilot Delta verification service a signed webhook with payment and invoice context, and waits for Delta's decision before the payment continues. Info: Delta is currently a guided rollout, not a self-serve dashboard toggle. If you want Delta access, contact [sales@conto.finance](mailto:sales@conto.finance) and Conto will activate it for your organization. ## How To Get Access If you want Delta enabled for your organization: 1. Contact [sales@conto.finance](mailto:sales@conto.finance) or your Conto contact. 2. Share the organization you want to enroll and whether you want Delta scoped to specific agents. 3. Share the public webhook URL for the pilot Delta verification service and the HMAC secret you want Conto to use. 4. Conto activates Delta for your organization and confirms when it is ready for testing. ## What Conto Activates For You When Conto enables Delta for an organization, we set up Delta for that org: - Turns on Delta for the organization - Sets up the approver identity Delta uses for verification decisions - Creates or updates the `delta` approval workflow - Creates or updates the Delta webhook notification channel You do not need to provision those pieces manually. ## What You Need To Provide For most onboardings, Conto only needs: - The organization you want activated - The public pilot verification service webhook URL, for example `https://delta-verifier.example/webhooks/conto/approval` - A shared HMAC secret - Optional agent IDs if you want Delta limited to a subset of agents - The vendor / invoice scenario you want to test first This is the public endpoint of your own verification service, the URL Conto sends approval webhooks to for Delta decisions. Delta webhook targets must resolve to a public address. Loopback, private, and internal-only hosts are rejected by Conto's webhook safety checks. ## How To Know Delta Is Active After Conto activates Delta: - The organization's **Delta** tab appears in the main dashboard sidebar - Matching payment requests return `REQUIRES_APPROVAL` with an `approvalRequestId` - The pilot Delta verification service receives the signed `approval.requested` webhook for matching requests - Proof metadata appears in the Delta detail view after a Delta verification decision If Delta does not appear to be active, contact your Conto onboarding contact or [sales@conto.finance](mailto:sales@conto.finance). ## Recommended Setup Before Testing Before running a payment through Delta, make sure the target organization also has: - An agent that is either in the scoped agent list or intentionally left unscoped - A managed wallet or external wallet flow you plan to test - An approved counterparty matching the vendor address - Payment requests that include `context.invoice` For the end-to-end test flow, see [Delta Smoke Test](https://conto.finance/docs/guides/delta-smoke-test). ## Related Docs ### Delta Smoke Test Link: https://conto.finance/docs/guides/delta-smoke-test Run the managed-wallet and external-wallet Delta flows end to end ### Notification Channels Link: https://conto.finance/docs/integrations/notification-channels Delta webhook payload format, action tokens, and callback contract ### External Approvals Link: https://conto.finance/docs/guides/external-approvals Review the generic approval-channel callback flow and verification block ### Payments API Link: https://conto.finance/docs/sdk/payments See the SDK request shape, `approvalRequestId`, and invoice context --- # Delta Smoke Test This guide validates the live Conto ↔ Delta flow after Conto has activated Delta for your organization. Info: Delta access is currently enabled by Conto during onboarding. If your organization does not already have Delta, contact [sales@conto.finance](mailto:sales@conto.finance) before using this guide. The goal is to prove four things: 1. Conto creates a real approval request when the Delta workflow matches 2. Conto sends the signed `approval.requested` webhook to the pilot Delta verification service 3. Delta calls back with an approval or rejection plus proof metadata 4. Conto records the result and continues the payment flow correctly ## Prerequisites Conto has activated Delta for the target organization The organization's dashboard shows the Delta tab The pilot Delta verification service is running and reachable at a public HTTPS URL The pilot Delta verification service and Conto share the same HMAC secret Your test vendor is allowlisted in the pilot Delta verification service Your Conto organization has an approved counterparty for the same vendor address ## Invoice Context Required by Delta To trigger the pilot Delta verification service meaningfully, send invoice details in `context.invoice`. ```json { "invoice": { "id": "ACME-1003", "hash": "acme-1003-sha256-demo", "vendorId": "acme-supplies", "vendorAddress": "0x1111111111111111111111111111111111111111", "expectedAmount": "45", "currency": "pathUSD", "payload": { "invoiceNumber": "ACME-1003", "lineItems": [ { "description": "Demo office supplies", "amount": "45" } ] } } } ``` ## Managed Wallet Flow Use this flow when Conto executes the payment onchain. ### Step 1: Request the payment ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_AGENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 45, "recipientAddress": "0x1111111111111111111111111111111111111111", "recipientName": "Acme Supplies", "purpose": "Invoice ACME-1003", "category": "SUPPLIES", "walletId": "wallet_id", "idempotencyKey": "delta-smoke-acme-1003", "context": { "invoice": { "id": "ACME-1003", "hash": "acme-1003-sha256-demo", "vendorId": "acme-supplies", "vendorAddress": "0x1111111111111111111111111111111111111111", "expectedAmount": "45", "currency": "pathUSD", "payload": { "invoiceNumber": "ACME-1003" } } } }' ``` ### Expected response When the Delta workflow matches, expect: - `status = "REQUIRES_APPROVAL"` - `approvalRequestId` present - No `executeUrl` yet Example: ```json { "requestId": "pr_...", "status": "REQUIRES_APPROVAL", "approvalRequestId": "ar_...", "reasons": ["Approval required by workflow \"delta\""] } ``` ### Step 2: Verify Delta receives the webhook Delta should receive `approval.requested` with: - `approvalRequestId` - `paymentDetails` - `invoice` - `actionToken.approveToken` - `actionToken.rejectToken` ### Step 3: Verify the callback After Delta approves, Conto should: - Keep the same `approvalRequestId` - Record proof metadata on the Delta verification record - Move the payment request out of `PENDING_APPROVAL` ### Step 4: Execute the managed-wallet payment Once approved, call execute: ```bash curl -X POST https://conto.finance/api/sdk/payments/{requestId}/execute \ -H "Authorization: Bearer $CONTO_AGENT_KEY" ``` ### Step 5: Verify completion After execution: - The payment request is executed successfully - Conto emits `payment.executed` - Delta can mark the invoice as paid without polling ## External Wallet Flow Use this flow when the agent or operator controls the signing keys. ### Step 1: Approve the payment request ```bash curl -X POST https://conto.finance/api/sdk/payments/approve \ -H "Authorization: Bearer $CONTO_AGENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 45, "chainId": "42431", "senderAddress": "0xabc123def456789abc123def456789abc123def4", "recipientAddress": "0x1111111111111111111111111111111111111111", "recipientName": "Acme Supplies", "purpose": "Invoice ACME-1003", "category": "SUPPLIES", "context": { "invoice": { "id": "ACME-1003", "hash": "acme-1003-sha256-demo", "vendorId": "acme-supplies", "vendorAddress": "0x1111111111111111111111111111111111111111", "expectedAmount": "45", "currency": "pathUSD" } } }' ``` ### Expected response When the Delta workflow matches, expect: - `status = "REQUIRES_APPROVAL"` - `approvalRequestId` present ### Step 2: Wait for Delta approval Delta should receive the same `approval.requested` webhook and submit its decision back to Conto. ### Step 3: Send the onchain transfer externally After approval, submit the transfer with your own signer or wallet integration. ### Step 4: Confirm the transfer in Conto ```bash curl -X POST https://conto.finance/api/sdk/payments/{requestId}/confirm \ -H "Authorization: Bearer $CONTO_AGENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "txHash": "0x..." }' ``` ## Duplicate Invoice Test After a successful first approval, resubmit the same vendor invoice ID or invoice hash. Expected result: - Delta rejects the request - Conto records the rejection on the same approval request / Delta verification trail - The payment does not proceed to execution ## Where To Verify In The Dashboard Check these areas in Conto: - **Alerts & Approvals**: the payment should show a real approval request - **Delta** tab: the verification row should appear with status and proof reference - **Delta detail view**: invoice context, proof metadata, and approval timeline ## Common Failure Modes | Symptom | Likely Cause | | --------------------------------------------------------- | --------------------------------------------------------------- | | No webhook reaches Delta | Webhook URL is private, wrong, or blocked by network policy | | Webhook reaches Delta but is rejected | Shared HMAC secret does not match | | Request returns `APPROVED` instead of `REQUIRES_APPROVAL` | Delta workflow did not match the org, agent, or payment context | | Delta rejects immediately | Vendor not allowlisted or invoice failed verifier guardrails | | No completion event after execution | `payment.executed` delivery is not configured on the Delta side | ## Related Docs ### Delta Verification Setup Link: https://conto.finance/docs/guides/delta-setup Request Delta onboarding and prepare your organization for activation ### Payments API Link: https://conto.finance/docs/sdk/payments Request, approve, execute, and confirm payment flows ### Notification Channels Link: https://conto.finance/docs/integrations/notification-channels Review the Delta pilot webhook payload and verification callback contract ### External Approval Channels Link: https://conto.finance/docs/guides/external-approvals General approval-channel behavior outside the Delta-specific flow --- # Testing Payments Safely Before going to production, you need confidence that your agent integration handles every scenario safely. This guide covers the testing **environments** (agent sandbox and Tempo Testnet), counterparty and time-window scenarios, and the migration to production. For policy semantics and the amount-threshold trio (APPROVED / REQUIRES_APPROVAL / DENIED), run the three-tier threshold test in [Testing Spending Policies](https://conto.finance/docs/guides/policy-testing). ## Prerequisites An agent with an SDK key ([Quickstart](https://conto.finance/docs/quickstart/setup)), or an agent sandbox (below) For testnet scenarios: a funded Tempo Testnet wallet linked to your agent ## Choose Your Environment ### Fastest Lane: Agent Sandbox The quickest way to test the payment lifecycle is the agent sandbox: `POST /api/agents/sandbox` creates a test-mode organization, agent, Tempo Testnet wallet, and SDK keys in one call, with no email verification or human approval. Sandbox payments execute in **simulated** mode: policy evaluation, spend tracking, receipts, and audit logs are real, but no onchain transfer happens, so you don't need a signer or a funded wallet. See the [Agent Sandbox Quickstart](https://conto.finance/docs/quickstart/agent-sandbox) for the full flow, including claiming the sandbox later. ### Tempo Testnet When you want real onchain transactions, use Tempo Testnet: | | Tempo Testnet | Production (Tempo / Base / Solana) | |---|---|---| | **Token** | pathUSD (free) | USDC.e on Tempo or USDC on Base / Solana | | **Gas fees** | None | Covered by Conto | | **Onchain** | Yes, real blockchain transactions | Yes | | **Policies** | Fully enforced | Fully enforced | | **Best for** | Integration testing, policy validation | Live agent operations | Tempo Testnet gives you real onchain transactions with real policy enforcement, using free test tokens. Your code stays the same when you switch to production. Only the wallet and chain change. The [Quickstart](https://conto.finance/docs/quickstart/setup) covers creating and funding a testnet wallet. ## Test Plan This guide walks through two scenarios beyond the amount thresholds: | # | Scenario | Expected Result | |---|----------|-----------------| | 1 | Payment to blocked counterparty | DENIED | | 2 | Payment outside time window | DENIED | For amount-based outcomes: a `REQUIRES_APPROVAL` payment appears in **Pending Approvals** in the dashboard, where a human can approve or reject it; after approval, the agent can execute it (poll for the status change, or use [webhooks](https://conto.finance/docs/guides/webhooks) to get notified). For handling `DENIED` and `REQUIRES_APPROVAL` statuses in code, see [Error Handling](https://conto.finance/docs/sdk/error-handling#using-request-and-execute-for-better-control). ## Scenario 1: Blocked Counterparty First create and assign the policy: Go to **Policies** → **New Policy**. | Field | Value | |-------|-------| | Name | Test: Blocked Address | | Policy Type | COUNTERPARTY | | Field | Value | |-------|-------| | Rule Type | BLOCKED_COUNTERPARTIES | | Value | `0xBLOCKED0000000000000000000000000000dead` | | Action | DENY | Add it in the **Permissions** tab. Then send a $5 payment to the blocked address: ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 5, "recipientAddress": "0xBLOCKED0000000000000000000000000000dead", "purpose": "Test: blocked recipient" }' ``` **Verify:** - Response `status` is `"DENIED"` - `violations` reference the blocked counterparty policy - Amount doesn't matter. The address itself is blocked ## Scenario 2: Time Window Restriction To test time-based restrictions, temporarily add a time window policy: | Field | Value | |-------|-------| | Name | Test: Business Hours Only | | Policy Type | TIME_WINDOW | | Rule Type | TIME_WINDOW | | Start Time | 09:00 | | End Time | 17:00 | | Action | ALLOW | Add it in the **Permissions** tab. If it's currently outside 9am-5pm in your timezone, any payment request will be denied with a time window violation. If it's during business hours, you can temporarily set the window to a past range (e.g., 02:00-03:00) to trigger the denial. Remove the time window policy after testing to avoid blocking your other tests. Info: Policy-rule time windows use the server's local time. If you need to test a specific IANA timezone, configure a wallet-level time window instead. ## Checking Results in Bulk After running your scenarios, review everything in one place: ### Transactions Page Go to **Transactions** in the dashboard. You should see: - Confirmed transactions from approved-and-executed payments - Denied/rejected entries from the blocked-counterparty and time-window scenarios - A pending-approval entry for any payment that required approval ### Audit Logs Go to **Audit Logs** to see the policy evaluation trail for every request. Each entry shows: - Which policies were evaluated - Which rules matched - The final decision and reasoning ### Via API ```bash # List recent transactions curl https://conto.finance/api/sdk/transactions \ -H "Authorization: Bearer $CONTO_API_KEY" ``` ## Testing x402 Micropayments If your agent uses x402 protocol payments (paying for APIs), test the pre-authorize → record flow the same way. The request and response shapes are documented in the [x402 SDK reference](https://conto.finance/docs/sdk/x402-payments); the [x402 guide](https://conto.finance/docs/guides/x402-api-payments) covers the end-to-end flow. ## Moving to Production Once your scenarios pass: 1. Create a production wallet on **Base** (USDC) or **Solana** (USDC) 2. Fund it with real stablecoins 3. Link it to your agent with production-appropriate limits 4. Adjust policies for production thresholds (the test policies can remain as-is) 5. Your integration code stays the same, no code changes needed Info: You can keep your testnet wallet and policies active alongside production. Many teams run test agents permanently for regression testing. ## Troubleshooting For unexpected policy outcomes (DENIED when you expected REQUIRES_APPROVAL, the wrong policy triggering, org policies overriding agent policies), see the [policy troubleshooting accordions](https://conto.finance/docs/guides/policy-testing#troubleshooting). Check the **Permissions** tab on the agent detail page. Policies must be explicitly assigned to the agent. Creating a policy doesn't automatically apply it. Double-check the timezone setting on the policy. If your local timezone doesn't match the policy timezone, the enforcement window may be offset. The wallet balance was sufficient at request time but dropped before execution. This can happen if other transactions executed between request and execute. Re-fund the testnet wallet. ## Next Steps ### Secure Your Agent Link: https://conto.finance/docs/guides/securing-agents Production-ready policy configurations ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste solutions for specific tasks ### Error Handling Link: https://conto.finance/docs/sdk/error-handling Handle every error code gracefully ### Policy Reference Link: https://conto.finance/docs/policies/overview All policy types and rule operators --- # Securing Agents with Policies An agent without policies is an open wallet. This guide walks through configuring the policies, alerts, and controls that make Conto valuable in production, from basic spend caps to x402 micropayment budgets. ## Prerequisites An active agent with a linked wallet Familiarity with the payment request/execute flow ([Quickstart](https://conto.finance/docs/quickstart/setup)) ## How Policies Work Before diving in, three rules to remember: 1. **AND logic**: All assigned policies are evaluated. The most restrictive outcome wins. 2. **First deny stops**: If any policy returns DENY, evaluation stops immediately. 3. **Wallet limits first**: Wallet-level per-transaction/daily/weekly/monthly limits are checked before policy rules. ``` Payment Request → Wallet Limits (per-tx, daily, weekly, monthly) → Org-Level Policies → Agent-Level Policies → Result: APPROVED / DENIED / REQUIRES_APPROVAL ``` ## Layer 1: Spending Limits The foundation. Every production agent should have spend caps. ### Daily Budget Prevents a runaway agent from draining the wallet in a single day. Go to **Policies** → **New Policy**. | Field | Value | |-------|-------| | Name | Daily Budget: $100 | | Policy Type | SPEND_LIMIT | | Field | Value | |-------|-------| | Rule Type | DAILY_LIMIT | | Operator | LTE | | Value | 100 | | Action | ALLOW | The agent can spend up to $100 per day across all transactions. Resets at midnight UTC. Go to the agent's **Permissions** tab and assign this policy. ### Per-Transaction Cap Prevents any single large transaction, even if the daily budget has room. | Field | Value | |-------|-------| | Rule Type | MAX_AMOUNT | | Operator | LTE | | Value | 25 | | Action | ALLOW | Add this as a second rule in the same policy, or create a separate policy. Both approaches work. Conto evaluates all rules regardless. ### Human Approval for Large Payments Automatically escalate payments above a threshold for human review. | Field | Value | |-------|-------| | Name | Approval Above $50 | | Policy Type | APPROVAL_THRESHOLD | | Rule Type | REQUIRE_APPROVAL_ABOVE | | Operator | GREATER_THAN | | Value | 50 | | Action | REQUIRE_APPROVAL | Payments over $50 show up in **Pending Approvals** in the dashboard. The agent receives `REQUIRES_APPROVAL` and can poll or use webhooks to check status. Info: A common pattern: set MAX_AMOUNT to $200 (hard deny above) and REQUIRE_APPROVAL_ABOVE to $50 (human review in the middle). Payments under $50 flow automatically, $50-$200 need approval, and above $200 are blocked outright. ## Layer 2: Counterparty Controls Control *who* your agent can pay, not just *how much*. ### Allowlist Known Recipients Only permit payments to pre-approved addresses. | Field | Value | |-------|-------| | Name | Approved Recipients Only | | Policy Type | COUNTERPARTY | | Field | Value | |-------|-------| | Rule Type | ALLOWED_COUNTERPARTIES | | Value | Comma-separated list of addresses | | Action | ALLOW | Only addresses in this list can receive payments. All others are denied. ### Block Specific Addresses Alternatively, allow all recipients except specific blocked ones: | Field | Value | |-------|-------| | Rule Type | BLOCKED_COUNTERPARTIES | | Value | `0xSuspiciousAddress1, 0xSuspiciousAddress2` | | Action | DENY | ### Trust Score Threshold Require counterparties to have a minimum trust score before receiving payments: | Field | Value | |-------|-------| | Rule Type | TRUST_SCORE | | Operator | GTE | | Value | 0.5 | | Action | ALLOW | New, unknown counterparties start with a low trust score. As transaction history builds, their score increases. See [Trust Providers](https://conto.finance/docs/integrations/trust-providers) for how scoring works. ## Layer 3: Time Controls Restrict *when* your agent can make payments. ### Business Hours Only ``` Allow payments Monday-Friday, 9am-6pm in the policy evaluator's local time ``` | Field | Value | |-------|-------| | Name | Business Hours Only | | Policy Type | TIME_WINDOW | | Field | Value | |-------|-------| | Rule Type | TIME_WINDOW | | Start Time | 09:00 | | End Time | 18:00 | | Action | ALLOW | | Field | Value | |-------|-------| | Rule Type | DAY_OF_WEEK | | Value | `["Mon", "Tue", "Wed", "Thu", "Fri"]` | | Action | ALLOW | Both rules must pass (AND logic). Payments outside business hours or on weekends are denied. Info: Policy-rule time windows use the server's local time. Use wallet-level time windows when you need an explicit IANA timezone such as `America/New_York`. ### Blackout Periods Block payments during specific date ranges (holidays, maintenance windows): | Field | Value | |-------|-------| | Rule Type | BLACKOUT_PERIOD | | Start Date | 2025-12-24 | | End Date | 2025-12-26 | | Action | DENY | ## Layer 4: x402 Micropayment Controls If your agent pays for APIs using the [x402 protocol](https://conto.finance/docs/sdk/x402-payments), add dedicated micropayment policies. ### Cap Per API Call Prevent a single expensive API call from draining the budget: | Field | Value | |-------|-------| | Rule Type | X402_MAX_PER_REQUEST | | Operator | LTE | | Value | 0.10 | | Action | ALLOW | No single x402 payment can exceed $0.10. ### Budget Per Service Limit total spending on a specific API service: | Field | Value | |-------|-------| | Rule Type | X402_MAX_PER_SERVICE | | Operator | LTE | | Value | `{"maxAmount": 50, "period": "DAILY"}` | | Action | ALLOW | Total spend per service domain cannot exceed $50. ### Allowlist Approved Services Only allow x402 payments to known API providers: | Field | Value | |-------|-------| | Rule Type | X402_ALLOWED_SERVICES | | Operator | IN_LIST | | Value | `["api.example.com", "data.provider.io"]` | | Action | ALLOW | Payments to any other x402 service domain are denied. ## Layer 5: Alerts Policies prevent bad transactions. Alerts tell you when something interesting happens. ### Recommended Alert Configuration Go to **Alerts** in the sidebar and configure: | Alert Type | Threshold | Why | |------------|-----------|-----| | High-Value Transaction | $50+ | Know when large payments execute | | Spend Limit Warning | 80% of daily limit | React before the agent hits its cap | | Low Balance | $50 remaining | Top up before payments start failing | | Policy Violation | Any | Track what the agent is trying to do that gets blocked | | New Counterparty | First transaction | Know when the agent pays someone new | ### x402-Specific Alerts If using x402 micropayments, also enable: | Alert Type | Why | |------------|-----| | Price Spike | API suddenly charging more than usual | | High Frequency | Agent making unusually many API calls | | New Service | Agent paying a service for the first time | | Budget Burn Rate | Approaching x402 budget limits | ## Putting It Together: Example Configuration Here's a production-ready policy stack for a typical AI agent: | Policy | Rules | Effect | |--------|-------|--------| | **Spend Controls** | MAX_AMOUNT ≤ $50, DAILY_LIMIT ≤ $200 | Hard caps on individual and daily spending | | **Human Review** | REQUIRE_APPROVAL_ABOVE $25 | Manager reviews payments $25-$50 | | **Known Recipients** | ALLOWED_COUNTERPARTIES: [list] | Only pays approved addresses | | **Business Hours** | TIME_WINDOW 9-18, DAY_OF_WEEK M-F | No weekend/overnight payments | | **x402 Guardrails** | MAX_PER_REQUEST ≤ $0.10, MAX_PER_SERVICE ≤ $20 | Micropayment safety net | With this stack, the agent can: - Automatically pay up to $25 to known recipients during business hours - Request human approval for $25-$50 payments - Never exceed $50 in a single transaction or $200/day - Pay for x402 APIs up to $0.10/call and $20/service ## Verifying Your Policies After setting up, verify with the setup endpoint: ```bash curl https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_API_KEY" ``` The `policies` array shows all active policies and their rules. Run a few [test transactions](https://conto.finance/docs/guides/testing-payments) to confirm enforcement before going live. ## Troubleshooting Policies must be assigned to the agent in the **Permissions** tab. Creating a policy doesn't apply it automatically. Also verify the policy status is ACTIVE (not DRAFT or DISABLED). Policies stack with AND logic. If you have 5 restrictive policies, the agent must pass all of them. Review each policy's rules and consider loosening thresholds or removing redundant policies. Organization-level policies apply to all agents and stack with agent policies. If an org policy caps transactions at $25, an agent-level policy allowing $100 won't override it. Check with your org admin. Wallet-level limits (set when linking a wallet) are checked first and separately from policies. If the wallet per-transaction limit is $10 but your policy allows $50, the wallet limit wins. Edit wallet limits from the agent detail page. ## Next Steps ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste policy configurations for common scenarios ### Advanced Policies Link: https://conto.finance/docs/policies/advanced x402, MPP, geographic, and DeFi policy rules ### Trust Providers Link: https://conto.finance/docs/integrations/trust-providers Counterparty trust scoring and verification ### Policy Testing Link: https://conto.finance/docs/guides/policy-testing Step-by-step policy enforcement testing --- # Approval Workflows for Agent Payments Approval workflows let you keep low-risk agent payments fast while routing exceptional cases through human review. In Conto, approvals are part of the payment control center, not an afterthought layered on later. ## When to Use Approval Workflows Approval workflows are a strong fit when you need any of the following: - Payments above a finance threshold - New recipients that have not built trust yet - Category-specific review, such as treasury or vendor onboarding flows - Role-based approvals for finance, ops, or compliance - Dual control or sequential review for larger transfers ## How the Flow Works ```mermaid flowchart TD Payment["Agent requests payment"] --> Policy["Policy engine + workflow matching"] Policy --> Match{"Workflow matched?"} Match -->|"No"| Continue["Normal approval / deny path"] Match -->|"Yes"| Create["Create approval request"] Create --> Notify["Send notifications to external channels"] Notify --> Decision["Approver decisions"] Decision --> Approved{"Required approvals reached?"} Decision --> Rejected{"Any rejection?"} Approved -->|"Yes"| Execute["Payment status moves to APPROVED"] Approved -->|"No"| Pending["Stay pending"] Rejected -->|"Yes"| Deny["Payment status moves to DENIED"] Rejected -->|"No"| Pending Execute --> Audit["Audit log + webhook + channel record"] Deny --> Audit ``` ## How Conto Matches a Workflow Conto evaluates active workflows in priority order and picks the first workflow whose trigger conditions match the payment context. Workflow matching runs for every non-denied payment. That means a workflow can deliberately hold an otherwise policy-approved request, which is how verifier pilots such as Delta act as an approval gate without becoming the settlement layer. ### Supported trigger conditions | Trigger | What it matches | | ------------------------ | ------------------------------------------------------------- | | `amountThreshold` | Amounts at or above a threshold | | `currency` | Currency-specific review | | `categories` | Category-based review, such as vendor or infrastructure spend | | `agentIds` | A specific set of agent IDs inside the organization | | `agentTypes` | Specific agent frameworks or classes | | `newRecipients` | First-time recipients | | `counterpartyTrustLevel` | Low-trust or unknown counterparties | This makes approval workflows a good complement to trust scoring and counterparty rules. For example, you can auto-approve trusted vendors while forcing review for unknown recipients. `agentIds` is especially useful for staged rollouts and verifier pilots. It lets you bind a workflow to one or two agents in a mixed org without turning on the same review path for every other agent. ## Workflow Settings That Matter | Setting | What it does | | -------------------- | --------------------------------------------------------- | | `priority` | Higher-priority workflows match first | | `requiredApprovals` | Number of approvals needed before a payment moves forward | | `timeoutHours` | Expiration window for pending requests | | `allowSelfApproval` | Whether the initiator can approve their own request | | `approverRoles` | Role-based access, such as `OWNER` or `ADMIN` | | `specificApprovers` | Explicit user allowlist for a workflow | | `sequentialApproval` | Enforces approval order when specific approvers are set | Info: Any rejection ends the workflow immediately. Approvals accumulate until the required approval count is reached. ## External Approval Channels Approval requests can be delivered to external channels so finance or ops teams can act without logging into Conto for every review. Supported channels include: - Slack - Email - Telegram - WhatsApp - Webhook Each decision records the acting channel, and Conto keeps an audit trail of who approved, when they approved, and how the request was resolved. For step-by-step setup, see [/guides/external-approvals](https://conto.finance/docs/guides/external-approvals). ## Recommended Patterns ### Pattern 1: Single approval for large payments | Setting | Example | | ------------------ | --------------------------------------------------------- | | Trigger | `amountThreshold = 100` | | Required approvals | `1` | | Approver roles | `OWNER`, `ADMIN` | | Best for | Day-to-day spend that only needs review above a threshold | ### Pattern 2: Review first-time recipients | Setting | Example | | ------------------ | ------------------------------------------------------------------------ | | Trigger | `newRecipients = true` | | Required approvals | `1` | | Approver roles | `ADMIN` | | Best for | Preventing agents from sending funds to unknown addresses without review | ### Pattern 3: Dual control for sensitive transfers | Setting | Example | | ------------------ | ---------------------------------------------------- | | Trigger | `amountThreshold = 5000` | | Required approvals | `2` | | Self approval | `false` | | Best for | Treasury, vendor onboarding, or high-value transfers | ### Pattern 4: Sequential approval for finance + security | Setting | Example | | ------------------- | ----------------------------------------------------------------- | | Specific approvers | `finance lead`, then `security lead` | | Sequential approval | `true` | | Best for | Controls that require ordered sign-off from multiple stakeholders | ### Pattern 5: Scoped verifier pilot in a shared org | Setting | Example | | ------------------ | ----------------------------------------------------- | | Trigger | `amountThreshold = 0`, `agentIds = ["agent_ap_demo"]` | | Required approvals | `1` | | Best for | Running a verifier like Delta against one agent first | ## Pair Approval Workflows with Trust Scoring One of the highest-signal combinations is: 1. Use trust scoring to classify counterparties. 2. Let trusted or verified recipients flow normally. 3. Route unknown or deteriorating counterparties into approval workflows. That gives you a fast path for established counterparties and a controlled path for new or risky ones. ## Canonical Approval Architecture The most common production stack looks like this: - Policy engine blocks clearly disallowed payments outright. - Trust scoring enriches the recipient before the payment is evaluated. - Approval workflows catch the gray area between auto-approve and hard deny. - External channels deliver requests to the real stakeholders. - Audit logs and webhooks make the outcome visible to finance and operations systems. ## Related Guides ### External Approvals Link: https://conto.finance/docs/guides/external-approvals Connect Slack, email, Telegram, WhatsApp, or webhooks ### Trust Scoring Link: https://conto.finance/docs/guides/trust-scoring Use counterparty trust as an approval trigger ### Securing Agents Link: https://conto.finance/docs/guides/securing-agents See where approvals fit in a layered policy model ### Architecture Patterns Link: https://conto.finance/docs/guides/architecture-patterns Visual reference for approval and payment flows --- # External Approval Channels This guide walks through setting up approval notifications so your team can approve or reject payments from wherever they already work. This is the setup walkthrough. For the concepts (when to use approval workflows, trigger conditions, patterns), see [Approval workflows](https://conto.finance/docs/guides/approval-workflows). For the channel API reference (endpoints, request shapes), see [Notification channels](https://conto.finance/docs/integrations/notification-channels). If you are using the pilot Delta verification flow specifically, see [Delta Verification Setup](https://conto.finance/docs/guides/delta-setup) and [Delta Smoke Test](https://conto.finance/docs/guides/delta-smoke-test). Delta access is currently enabled by Conto during onboarding; if you want access, contact [sales@conto.finance](mailto:sales@conto.finance). ## Prerequisites An active organization with at least one agent An approval workflow configured ([Securing Agents](https://conto.finance/docs/guides/securing-agents)) Admin or Owner role in your organization ## What You'll Build By the end of this guide, your approval flow will look like this: ``` Agent requests $500 payment → Approval workflow triggers → Approver gets a Slack message with Approve/Reject buttons → Approver clicks "Approve" in Slack → Payment is approved and executed → Audit log records: who, when, which channel ``` ## Step 1: Set Up an Approval Workflow If you haven't already, create an approval workflow that triggers on the conditions you care about. Go to **Policies** in the dashboard. Create a new Approval Workflow with: | Field | Example Value | |-------|--------------| | Name | Large Payment Review | | Amount Threshold | $100 | | Required Approvals | 1 | | Timeout | 24 hours | | Approver Roles | OWNER, ADMIN | Request a payment above your threshold and confirm it enters `PENDING_APPROVAL` status. SDK payment requests and external-wallet `/api/sdk/payments/approve` calls with a matching workflow also return an `approvalRequestId`, which is handy when you are testing external verifier flows end to end. ## Step 2: Add a Notification Channel Channels"> Click **Add Channel** and choose your platform. Fill in the platform-specific fields. **For Slack:** - Bot Token: `xoxb-...` (from your Slack app) - Channel ID: `C0123456789` **For Email:** - Recipients: `cfo@company.com, finance@company.com` **For Telegram:** - Bot Token: from @BotFather - Chat ID: your group chat ID At minimum, enable `approval.requested`. Consider also enabling: - `approval.escalated` for time-sensitive visibility - `approval.expired` so nothing falls through the cracks - `payment.executed` on `WEBHOOK` channels if your verifier needs to mark invoices as paid Click the test button. You should receive a sample notification on your platform. ## Step 3: Test the Full Flow Use the SDK or dashboard to request a payment above your approval threshold. ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $SDK_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 500, "recipientAddress": "0x...", "purpose": "Test approval" }' ``` Within a few seconds, you should receive a notification on your configured channel with payment details and Approve/Reject buttons. Complete the approval from the email confirmation page or the Conto dashboard. The payment should move to `APPROVED` status and execute automatically if you are using Conto-managed wallets. Go to **Audit Logs** in the dashboard. You should see the approval decision with the channel recorded (e.g., `SLACK`, `EMAIL`). ## Multiple Channels You can configure multiple channels simultaneously. When an approval request is created, notifications are sent to all active channels that subscribe to the `approval.requested` event. The first approver to act from any channel resolves the request. Info: Each channel delivers independently via background jobs. If one channel fails (e.g., Slack API is down), other channels still deliver. Failed deliveries retry up to 3 times with exponential backoff. ## Webhook Integration for Custom Systems If you already have your own approval system, use the Webhook channel type to receive approval requests and hand the final decision off to an authenticated Conto approver. ```bash # 1. Configure a webhook channel pointing to your system # 2. Your system receives a signed payload with `eligibleApprovers` and `dashboardUrl` # 3. Notify the right approver or open your own review UI # 4. Send the user to `dashboardUrl` to complete the approval in Conto ``` The response confirms the decision: ```json { "success": true, "message": "Payment request approved.", "finalStatus": "APPROVED", "channel": "WEBHOOK" } ``` ### Attaching verification metadata Programmatic approvers can optionally attach a `verification {}` block to the decision call. Conto persists it alongside the approval decision when the consumed token was issued for a `WEBHOOK` channel. The Delta verification pilot uses this to return its proof reference alongside the APPROVE/REJECT decision. ```bash curl -X POST https://app.example/api/approvals/action \ -H "Content-Type: application/json" \ -d '{ "token": "", "comment": "Verified against invoice_payment_guard", "verification": { "proofType": "delta_signed", "proofRef": "https://delta.example/proofs/abc", "templateId": "...", "intentUuid": "...", "evidenceHash": "...", "reason": "OK" } }' ``` The `verification` block is strict: only the documented keys are accepted; unknown keys cause a `400`. `proofType` accepts `delta_signed` (signed JSON receipt) or `delta_mandate_sp1` (SP1 zk proof). ### Preferred service-to-service callback For long-running pilot verification services, prefer the HMAC-authenticated internal decision endpoint instead of the token callback. It uses the same `secret` configured on the Delta pilot webhook channel and signs the exact string `${X-Conto-Timestamp}.${rawBody}` with HMAC-SHA256. ```bash timestamp="$(date -u +%Y-%m-%dT%H:%M:%SZ)" body='{ "decision": "APPROVED", "comment": "Verified against invoice_payment_guard", "verification": { "proofType": "delta_signed", "proofRef": "https://delta.example/proofs/abc", "templateId": "...", "intentUuid": "...", "evidenceHash": "...", "reason": "OK" } }' signature="$(printf '%s.%s' "$timestamp" "$body" | \ openssl dgst -sha256 -hmac "$DELTA_WEBHOOK_SECRET" -hex | sed 's/^.* //')" curl -X POST https://app.example/api/internal/approval-requests/ar_123/decide \ -H "Content-Type: application/json" \ -H "X-Conto-Timestamp: $timestamp" \ -H "X-Conto-Signature: $signature" \ -d "$body" ``` This route is the long-term external-verifier contract. The token-based `/api/approvals/action` flow remains available for demos, email-style click throughs, and simple webhook integrations. For SDK-driven payment requests and external-wallet `/api/sdk/payments/approve` calls, Conto automatically opens the approval request when a workflow matches and returns the resulting `approvalRequestId` in the initial API response. That ID is the same one used in the callback route above. ## Troubleshooting 1. Check that the channel is **active** (toggle is on) in Settings > Channels 2. Check the `lastError` field on the channel for API errors 3. Verify your bot token or credentials are correct 4. For Slack, confirm the bot is invited to the target channel 5. For Telegram, confirm the webhook URL is set correctly Action tokens are one-time use and expire with the approval request. If the approval request has already been resolved (by another approver or from the dashboard), the token is no longer valid. Confirm your Slack app's interactivity request URL is set to `https://conto.finance/api/webhooks/slack` and that `SLACK_SIGNING_SECRET` is configured in your environment. ## Next Steps ### Channel Reference Link: https://conto.finance/docs/integrations/notification-channels Full configuration reference for all channel types ### Policy Testing Link: https://conto.finance/docs/guides/policy-testing Test your approval workflows before going to production --- # Trust Scoring and Counterparty Controls Trust scoring is how Conto turns recipient history, verification, and network intelligence into a practical control surface for agent payments. It helps answer a simple question before money moves: > How comfortable should this agent be paying this address right now? ## Two Layers of Trust Conto maintains two complementary trust scoring layers: - **Per-organization trust**: your org's local view of a counterparty based on your own transaction history with them. - **Network trust**: a cross-organization view of a counterparty across all Conto customers, treating signals like a credit bureau. Policies can use either layer. The per-org score is most relevant for repeat counterparties; the network score is most useful for cold-start decisions on addresses you have not transacted with before. ## What Feeds the Trust Score Conto calculates trust with four weighted components: | Component | Weight | What it reflects | | ---------------- | ------ | ---------------------------------------------------------- | | **History** | `30%` | Transaction count, volume, and relationship depth | | **Reliability** | `30%` | Success rate, failed transactions, flagged activity | | **Activity** | `20%` | Account age, recency, and consistency of behavior | | **Verification** | `20%` | Manual verification, network data, and external enrichment | This means trust is not based on a single signal. A new counterparty can improve over time through successful activity, while a once-safe counterparty can degrade if failure or alert signals appear. ## How Trust Levels Are Assigned Internally, Conto calculates a score on a `0.0` to `1.0` scale and then maps it to a trust level. | Internal score | Trust level | Notes | | -------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `< 0.2` | `UNKNOWN` or `BLOCKED` | Counterparties with low scores only become `BLOCKED` when there are actual negative signals, such as failed or flagged transactions | | `0.2 - 0.49` | `UNKNOWN` | Limited history or weak signal quality | | `0.5 - 0.74` | `VERIFIED` | Reasonable confidence, but not yet a fully trusted recipient | | `>= 0.75` | `TRUSTED` | High-confidence recipient, assuming verification requirements are satisfied | Note: Low data is not the same as malicious behavior. Conto treats many new counterparties as `UNKNOWN` rather than auto-blocking them. ## External Enrichment and Compliance Signals ### Conto Network Intelligence Conto aggregates anonymized network signals across organizations to improve counterparty evaluation. This data takes precedence when it exists because it reflects real payment behavior on the platform. Operators can now inspect that network layer directly in the dashboard, not just infer it from a policy result. The Network workspace exposes detailed entity views, trust lookups, alert context, and network-wide strength summaries so teams can see why an address is unknown, verified, trusted, or blocked. ### Fairscale for Solana For Solana addresses with no existing network trust score, Conto can enrich the counterparty with Fairscale data. - Used for cold-start reputation on Solana - Normalized into Conto's `0.0 - 1.0` trust scale - Fail-open design: enrichment helps, but provider unavailability does not automatically block ### Sanctions Screening Sanctions and compliance checks are separate from trust scoring. - Local OFAC screening is built in - Chainalysis and TRM Labs can be layered on for enterprise use - Compliance checks are fail-closed for enterprise screening providers That means a counterparty can be high-trust from a behavior standpoint and still be blocked for compliance reasons. ## How Trust Becomes a Control Trust data feeds directly into policy evaluation. Common trust-aware controls include: - `TRUST_SCORE` thresholds - Counterparty status and trust-level rules - New-recipient approval workflows - Auto-freeze and alert thresholds when trust drops sharply For more on provider inputs, see [/integrations/trust-providers](https://conto.finance/docs/integrations/trust-providers). For policy rule details, see [/policies/counterparties](https://conto.finance/docs/policies/counterparties). ## Canonical Patterns ### 1. New vendor safe path - Unknown counterparties are allowed to exist but not to spend freely. - Require approval for first payments or low-trust recipients. - Promote to normal flow once transaction history and verification improve. ### 2. Trusted vendor fast path - Allow trusted or verified counterparties to pass with fewer interruptions. - Keep hard denies for sanctioned or blocked recipients. - Layer spend limits and time windows on top of trust so no single signal has too much power. ### 3. Solana cold-start enrichment - Use Fairscale when a Solana recipient has no Conto network history. - Combine that score with a conservative approval threshold. - Let the relationship graduate as real transaction history builds. ### 4. Trust deterioration response - Watch for trust score drops, repeated failures, or new flags. - Route affected counterparties into approval workflows. - Use alerts or auto-freeze when trust degradation becomes severe. ## Look Up Trust Programmatically Use the SDK network trust endpoint to inspect any wallet address: ```bash curl https://conto.finance/api/sdk/network/trust/0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18 \ -H "Authorization: Bearer $CONTO_API_KEY" ``` The response includes: - Global trust information - Agent-specific relationship trust, when it exists - Flags and risk indicators - Aggregate transaction history For Solana addresses, Conto can also include Fairscale-specific detail such as: - recommendation tier - behavioral red flags - pillar scores and badges - confidence and verification hints This is a useful building block for preflight checks, ops tooling, or AI assistant workflows. ## What Operators Can Inspect The Network dashboard is meant to answer two different questions: 1. What does the network know about this address right now? 2. How much shared intelligence is my organization currently participating in? In practice, operators can inspect: - detailed entity lists ranked by transaction volume and trust level - first-seen and last-seen timing for known entities - network-wide transaction counts, participating organizations, and tracked volume - your organization's own contribution to a known entity, including local flags or block signals - trust lookups for EVM addresses, Solana addresses, and supported domains This makes trust scoring easier to operationalize during recipient review, approval triage, and post-incident investigation. ## Network Sharing Modes Organizations can control how they participate in network intelligence from **Settings**. | Mode | What you share | What you receive | | ---- | -------------- | ---------------- | | `FULL` | Transaction telemetry, shared volume patterns, local trust hints, and manual risk signals | Full trust lookups, alerts, and network stats | | `PARTIAL` | Transaction telemetry and manual signals, but not shared volume or local trust scores | Full trust lookups, alerts, and network stats | | `RECEIVE_ONLY` | No transaction telemetry, no volume sharing, and no manual signal contribution | Trust lookups, alerts, and network stats | | Disabled | Nothing | No shared trust lookups or network analytics | If sharing is disabled, network lookups degrade gracefully: Conto returns an `UNKNOWN` baseline and explains that shared trust signals are paused until the organization re-enables network intelligence. ## Trust, Approvals, and Policy Design Trust scoring works best as part of a layered model: 1. Use trust to classify recipients. 2. Use approvals to review the gray area. 3. Use hard policy denies for clearly forbidden destinations. That gives you three lanes instead of one: - **Fast lane** for trusted counterparties - **Review lane** for unknown or changing counterparties - **Blocked lane** for clearly disallowed behavior ## Related Guides ### Trust Providers Link: https://conto.finance/docs/integrations/trust-providers See Fairscale, sanctions screening, and provider priority ### Approval Workflows Link: https://conto.finance/docs/guides/approval-workflows Use trust levels as a review trigger ### Securing Agents Link: https://conto.finance/docs/guides/securing-agents Build a layered risk model for agents that spend ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste trust lookup and policy setup commands --- # Paying for APIs with x402 When your AI agent calls a paid API, the API returns HTTP `402 Payment Required` with a payment challenge. The [x402 protocol](https://www.x402.org/) standardizes this flow. Conto sits in the middle to enforce policies before the agent pays. This guide is a walkthrough. For the endpoint reference (request/response shapes, scopes, error codes), see [SDK > x402 payments](https://conto.finance/docs/sdk/x402-payments). ## Prerequisites An active agent with an SDK key ([Quickstart](https://conto.finance/docs/quickstart/setup)) A funded wallet (Base `USDC` or Tempo `USDC.e` for production, or Tempo Testnet `pathUSD` for testing) An x402-enabled API to call (or use the examples below to simulate) ## How x402 Works ``` Agent calls API → HTTP 402 → Conto pre-authorizes → Agent pays & retries → Conto records ``` | Step | Who | What happens | |------|-----|-------------| | 1 | Agent | Calls an x402-enabled API | | 2 | API | Returns `402 Payment Required` with amount, recipient, facilitator | | 3 | Agent | Sends payment details to Conto for policy check | | 4 | Conto | Evaluates x402 policies, returns authorized or denied | | 5 | Agent | If authorized, signs payment and retries the API call | | 6 | Agent | Records the completed transaction in Conto for tracking | Conto never touches the x402 payment itself. It acts as the policy and tracking layer. Your agent (or wallet provider like Sponge) handles the actual signing and payment. ## Step 1: Set Up x402 Policies Before your agent starts paying for APIs, set guardrails. Without x402-specific policies, only your general spend limits apply. ### Recommended Starter Policy Go to **Policies** → **New Policy**. | Field | Value | |-------|-------| | Name | x402 API Guardrails | | Policy Type | COMPOSITE | Add these rules to cap per-request cost and total per-service spend: **Rule 1: Cap per API call** | Field | Value | |-------|-------| | Rule Type | X402_MAX_PER_REQUEST | | Operator | LTE | | Value | 0.50 | | Action | ALLOW | No single x402 payment can exceed $0.50. **Rule 2: Budget per service** | Field | Value | |-------|-------| | Rule Type | X402_MAX_PER_SERVICE | | Operator | LTE | | Value | `{"maxAmount": 50, "period": "DAILY"}` | | Action | ALLOW | Total spend per API service domain cannot exceed $50. Go to the agent's **Permissions** tab and assign the policy. Info: You can also add `X402_ALLOWED_SERVICES` with a JSON array value such as `["api.example.com", "data.provider.io"]` to restrict which API domains your agent can pay. This is the strongest guardrail: the agent can only pay APIs you've explicitly approved. ## Step 2: Pre-Authorize a Payment When your agent receives an HTTP 402, extract the payment details (amount, recipient, facilitator) and check them against Conto with `POST /api/sdk/x402/pre-authorize`. Conto evaluates your x402 policies plus your general spend limits and responds one of two ways: - **Authorized**: the response includes the wallet to pay from. The agent signs the payment and retries the API call. - **Denied**: the response lists the violated rules. The agent should log the denial and either skip the API call or escalate. See [Pre-Authorization in the SDK reference](https://conto.finance/docs/sdk/x402-payments#pre-authorization) for the full request and response shapes. ## Step 3: Record the Transaction After the x402 payment executes onchain, record it with `POST /api/sdk/x402/record` so it counts toward budgets and shows up in analytics. For high-frequency API calls, batch multiple records in one request. See [Recording Transactions](https://conto.finance/docs/sdk/x402-payments#recording-transactions) and [Batch Recording](https://conto.finance/docs/sdk/x402-payments#batch-recording) for the request shapes. If you skip recording, Conto can't track budget consumption. Your per-service limits won't enforce correctly because Conto doesn't know the payment happened. ## Step 4: Monitor Spending Check how much your agent has spent and what's remaining with `GET /api/sdk/x402/budget`, and list the x402 API services it has interacted with via `GET /api/sdk/x402/services`. See [Budget Tracking](https://conto.finance/docs/sdk/x402-payments#budget-tracking) and [Querying Services](https://conto.finance/docs/sdk/x402-payments#querying-services) for details, including session-scoped budget views. ### Dashboard Go to **Analytics** in the dashboard to see: - x402 spend trends over time - Per-service cost breakdown - Request frequency and average cost per call ## Full Integration Example Here's how an agent handles the complete x402 flow in TypeScript: The TypeScript SDK currently exposes standard payment helpers. For x402 flows, call the SDK REST endpoints directly: ```typescript const CONTO_API_BASE = 'https://conto.finance'; const contoApiKey = process.env.CONTO_API_KEY; type PreAuthorizeResponse = { authorized: boolean; reasons: string[]; wallet?: { id: string; chainId: string; address: string }; }; async function postConto (path: string, body: unknown): Promise { if (!contoApiKey) { throw new Error('CONTO_API_KEY is required'); } const response = await fetch(`${CONTO_API_BASE}${path}`, { method: 'POST', headers: { Authorization: `Bearer ${contoApiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify(body), }); if (!response.ok) { throw new Error(`Conto ${path} failed: ${await response.text()}`); } return response.json() as Promise ; } async function callPaidApi(url: string) { // Step 1: Call the API const response = await fetch(url); if (response.status !== 402) { return response.json(); // No payment needed } // Step 2: Parse the 402 payment challenge const paymentHeader = response.headers.get('X-Payment'); if (!paymentHeader) { throw new Error('Missing X-Payment header'); } const { amount, recipient, facilitator, paymentId } = JSON.parse(paymentHeader) as { amount: number; recipient: string; facilitator?: string; paymentId?: string; }; // Step 3: Pre-authorize through Conto const auth = await postConto ('/api/sdk/x402/pre-authorize', { amount, recipientAddress: recipient, resourceUrl: url, facilitator, scheme: 'exact', paymentId, }); if (!auth.authorized || !auth.wallet) { console.error('Policy denied x402 payment:', auth.reasons); throw new Error(`x402 denied: ${auth.reasons.join(', ')}`); } // Step 4: Sign and pay (via your wallet provider) const { txHash } = await walletProvider.signX402Payment({ amount, recipient, facilitator, }); // Step 5: Retry the API call with payment proof const paidResponse = await fetch(url, { headers: { 'X-Payment-Signature': txHash }, }); // Step 6: Record in Conto await postConto('/api/sdk/x402/record', { amount, recipientAddress: recipient, txHash, resourceUrl: url, facilitator, scheme: 'exact', paymentId, walletId: auth.wallet.id, chainId: auth.wallet.chainId, }); return paidResponse.json(); } ``` ## x402 Policy Reference The complete list of x402 rule types, value formats, and operators lives in [Advanced Policies > x402 Protocol Rules](https://conto.finance/docs/policies/advanced#x402-protocol-rules). ## Anomaly Detection Conto automatically monitors x402 patterns and creates alerts for price spikes, high-frequency bursts, new services, budget burn, duplicate payments, and failed streaks. See [Anomaly Detection in the SDK reference](https://conto.finance/docs/sdk/x402-payments#anomaly-detection) for what triggers each alert and where to configure thresholds. ## Troubleshooting Your general spend limits still apply to x402 payments. If the x402 amount plus today's spend exceeds your daily limit, it's denied. Check your wallet-level and agent-level spend limits. Ensure you're recording transactions after they execute. If you skip the record step, Conto can't decrement the budget correctly. Also check if batch records are being sent for high-frequency calls. The allowlist is strict, only listed domains can receive x402 payments. Make sure you've added the exact domain (e.g., `api.example.com`, not `example.com` or `www.api.example.com`). Pre-authorization is a policy check, not an onchain operation. If it's slow, it's likely network latency to the Conto API. Consider caching authorization results for repeated calls to the same endpoint within a short window. ## Next Steps ### MPP Sessions Link: https://conto.finance/docs/guides/mpp-session-payments Session-based micropayments for streaming APIs ### x402 SDK Reference Link: https://conto.finance/docs/sdk/x402-payments Full API reference for x402 endpoints ### Advanced Policies Link: https://conto.finance/docs/policies/advanced All x402 policy rule types and value formats ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste x402 recipes --- # MPP Session Payments The Machine Payment Protocol (MPP) enables session-based micropayments on Tempo. Unlike x402 where each API call is a separate payment, MPP opens a session with a deposit budget. Your agent makes multiple requests against that budget and the session settles when done. This guide is a walkthrough. For the endpoint reference (request/response shapes, scopes, error codes), see [SDK > MPP payments](https://conto.finance/docs/sdk/mpp-payments). ## Prerequisites An active agent with an SDK key ([Quickstart](https://conto.finance/docs/quickstart/setup)) A funded Tempo wallet with `pathUSD` on testnet/demo flows or `USDC.e` on mainnet An MPP-enabled service to call (or use the examples below to simulate) ## MPP vs x402 | | x402 | MPP | |---|---|---| | **Payment model** | Pay-per-request | Session with deposit | | **Best for** | Occasional API calls | Streaming, multi-request workflows | | **Chain** | Base (USDC), Tempo (USDC.e on mainnet / pathUSD on testnet) | Tempo (USDC.e on mainnet / pathUSD on testnet) | | **Settlement** | Immediate per call | On session close | | **Unused funds** | N/A | Returned to agent | Use x402 when each API call is independent. Use MPP when your agent will make many requests to the same service in a session (e.g., streaming data, iterative processing, chat APIs). ## How MPP Works ``` Pre-authorize → Open session (deposit) → Make requests → Close session → Settle ``` | Step | What happens | |------|-------------| | 1 | Agent calls an MPP-enabled service, gets a 402 challenge | | 2 | Agent pre-authorizes the session deposit through Conto policies | | 3 | Agent opens a session with a deposit budget | | 4 | Agent makes requests, each consumes part of the deposit | | 5 | Session closes, unused deposit is returned | | 6 | Agent records the final settled amount in Conto | ## Step 1: Set Up MPP Policies Go to **Policies** → **New Policy**. | Field | Value | |-------|-------| | Name | MPP Session Guardrails | | Policy Type | COMPOSITE | **Rule 1: Cap session deposit** | Field | Value | |-------|-------| | Rule Type | MPP_MAX_SESSION_DEPOSIT | | Operator | LTE | | Value | 25 | | Action | ALLOW | No single session can have a deposit greater than $25. **Rule 2: Cap per-request charge** | Field | Value | |-------|-------| | Rule Type | MPP_MAX_PER_REQUEST | | Operator | LTE | | Value | 1.00 | | Action | ALLOW | No individual request within a session can charge more than $1.00. **Rule 3: Limit concurrent sessions** | Field | Value | |-------|-------| | Rule Type | MPP_MAX_CONCURRENT_SESSIONS | | Operator | LTE | | Value | 3 | | Action | ALLOW | Agent can have at most 3 open sessions at once. Go to the agent's **Permissions** tab and assign the policy. ## Step 2: Pre-Authorize the Session When your agent needs to open an MPP session, first check policies with `POST /api/sdk/mpp/pre-authorize`, sending the deposit amount and `"intent": "session"`. Conto evaluates your MPP policies plus your general spend limits and responds one of two ways: - **Authorized**: the response includes the wallet to use. Proceed to open the session with the MPP-enabled service. - **Denied**: the response lists the violated rules. The agent should either request a smaller session or escalate. See [Pre-Authorization in the SDK reference](https://conto.finance/docs/sdk/mpp-payments#pre-authorization) for the full request and response shapes. ## Step 3: Open the Session After Conto authorizes, open the MPP session with the service. The session deposit is locked onchain: ```typescript // Using Sponge MCP or your MPP client const session = await mppClient.openSession({ serviceUrl: 'https://api.service.com/stream', maxDeposit: '10.00', walletAddress: auth.wallet.address, }); console.log('Session ID:', session.sessionId); // Session ID: mpp_session_xyz ``` The deposit ($10 in this case) is committed. The agent can now make requests up to this amount. ## Step 4: Make Requests Each request to the MPP service consumes part of the deposit: ```typescript // Request 1: $0.50 charge const result1 = await mppClient.request({ sessionId: session.sessionId, url: 'https://api.service.com/stream/query', body: { query: 'market analysis for AAPL' }, }); // Remaining deposit: $9.50 // Request 2: $0.75 charge const result2 = await mppClient.request({ sessionId: session.sessionId, url: 'https://api.service.com/stream/summarize', body: { text: result1.data }, }); // Remaining deposit: $8.75 ``` The service tracks charges against the session deposit. No additional onchain transactions happen during the session, settlement occurs on close. ## Step 5: Close and Settle When your agent is done, close the session. Unused deposit is returned: ```typescript const settlement = await mppClient.closeSession({ sessionId: session.sessionId, }); console.log('Total charged:', settlement.totalCharged); // $1.25 console.log('Returned:', settlement.returned); // $8.75 console.log('TX Hash:', settlement.transactionHash); ``` | Session Summary | Amount | |-----------------|--------| | Initial deposit | $10.00 | | Total charged | $1.25 | | Returned to agent | $8.75 | ## Step 6: Record in Conto Record the settled amount with `POST /api/sdk/mpp/record`, including the settlement `txHash` and the `sessionId`, so Conto can track spending. See [Recording Transactions in the SDK reference](https://conto.finance/docs/sdk/mpp-payments#recording-transactions) for the request shape, including per-call `batchItems`. Record the **settled amount** ($1.25), not the deposit amount ($10.00). The settled amount is what was actually charged. Recording the deposit would overcount spending against your budgets. ## Step 7: Monitor Spending Check remaining MPP budget with `GET /api/sdk/mpp/budget` and list the MPP services your agent has used via `GET /api/sdk/mpp/services`. See [Budget Tracking](https://conto.finance/docs/sdk/mpp-payments#budget-tracking) and [Querying Services](https://conto.finance/docs/sdk/mpp-payments#querying-services) for details, including session-scoped budget views. ### Dashboard Go to **Analytics** to see MPP-specific metrics: session frequency, average session cost, per-service breakdown, and deposit utilization (how much of each deposit is actually used). ## Full Integration Example Complete TypeScript flow for an MPP session: The TypeScript SDK currently exposes standard payment helpers. For MPP flows, call the SDK REST endpoints directly. This example reuses the `postConto` helper and `PreAuthorizeResponse` type from the [x402 guide's integration example](https://conto.finance/docs/guides/x402-api-payments#full-integration-example): ```typescript async function runMppSession(serviceUrl: string, queries: string[]) { // 1. Pre-authorize with Conto const auth = await postConto ('/api/sdk/mpp/pre-authorize', { amount: 10.00, recipientAddress: '0xServiceAddress', resourceUrl: serviceUrl, intent: 'session', depositAmount: 10.00, }); if (!auth.authorized || !auth.wallet) { throw new Error(`MPP denied: ${auth.reasons.join(', ')}`); } // 2. Open session const session = await mppClient.openSession({ serviceUrl, maxDeposit: '10.00', }); // 3. Make requests const results = []; for (const query of queries) { const result = await mppClient.request({ sessionId: session.sessionId, url: `${serviceUrl}/query`, body: { query }, }); results.push(result.data); } // 4. Close and settle const settlement = await mppClient.closeSession({ sessionId: session.sessionId, }); // 5. Record in Conto await postConto('/api/sdk/mpp/record', { amount: settlement.totalCharged, recipientAddress: '0xServiceAddress', txHash: settlement.transactionHash, resourceUrl: serviceUrl, sessionId: session.sessionId, scheme: 'mpp', walletId: auth.wallet.id, chainId: auth.wallet.chainId, }); return { results, cost: settlement.totalCharged }; } ``` ## MPP Policy Reference The complete list of MPP rule types, value formats, and operators lives in [Advanced Policies > MPP Protocol Rules](https://conto.finance/docs/policies/advanced#mpp-protocol-rules). ## Troubleshooting Your agent has too many open sessions. Close existing sessions before opening new ones, or increase the `MPP_MAX_CONCURRENT_SESSIONS` limit in your policy. The deposit is locked onchain when the session opens. If your wallet has $15 and you try to open a $20 session, it fails. Check your wallet balance and request a smaller deposit. The service determines final settlement. If charges seem wrong, check the session details with the service provider. Conto records whatever you report. Make sure you're recording the settlement amount from the close response. MPP is currently supported only on the Tempo blockchain (see [Supported Chain](https://conto.finance/docs/sdk/mpp-payments#supported-chain) for chain IDs, currencies, and explorers). For paid APIs on Base or Ethereum, use the [x402 protocol](https://conto.finance/docs/guides/x402-api-payments) instead. ## Next Steps ### x402 Payments Link: https://conto.finance/docs/guides/x402-api-payments Per-request API payments on Base and Tempo ### MPP SDK Reference Link: https://conto.finance/docs/sdk/mpp-payments Full API reference for MPP endpoints ### Advanced Policies Link: https://conto.finance/docs/policies/advanced All MPP policy rule types and value formats ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste MPP recipes --- # Card Management This guide walks through connecting payment cards in the Conto dashboard, assigning them to agents, and enforcing spend policies. Info: Issuing new cards directly through Conto is not yet generally available. Today, you can connect any existing card manually and enforce the full policy engine on it. ## Prerequisites - A Conto organization with at least one agent ## Connecting a Card Go to **Cards** in the sidebar. Click **Create Card**. The **Manual** provider is selected by default. Fill in: - **Card name** - A descriptive name (e.g., "Marketing Agent Card") - **Last 4 digits** - The last 4 digits of the card number - **Brand** - Visa, Mastercard, Amex, or Other - **Card type** - Virtual or Physical - **Daily limit** - Maximum daily spend (default: $1,000) - **Per-transaction limit** - Maximum per charge (default: $500) Note: Additional providers shown in the list and marked as **Coming Soon** will allow you to issue new cards directly through Conto when generally available. The card appears in your cards grid. You can now assign it to an agent. ## Assigning Cards to Agents Each card can be assigned to one or more agents with independent spend controls. On the card tile, click the menu icon and select **Assign to Agent**. Choose an active agent from the dropdown. Agents already linked to this card are filtered out. Configure per-agent spending controls: | Setting | Default | Description | |---------|---------|-------------| | Per-transaction | $250 | Max amount per charge | | Daily | $500 | Max daily spend | | Weekly | (optional) | Max weekly spend | | Monthly | (optional) | Max monthly spend | Agent limits cannot exceed the card's own limits. Click **Assign Card**. The agent can now use this card subject to the configured limits. ## Linking Policies Beyond field-based limits, you can link named policies to cards for advanced rule enforcement. Click on a card to open its detail page. In the **Policies** panel, you can see currently linked policies. Select a policy from the dropdown and click the add button. The policy's rules are immediately enforced on all card transactions. ### Example: Geographic + MCC Policy Create a policy with these rules, then link it to a card: ```json { "name": "US Merchants Only - No Gambling", "policyType": "COMPOSITE", "priority": 50, "rules": [ { "ruleType": "GEOGRAPHIC_RESTRICTION", "operator": "NOT_IN", "value": "[\"US\", \"CA\"]", "action": "DENY" }, { "ruleType": "CARD_BLOCKED_MCCS", "operator": "IN", "value": "[\"7995\", \"7994\"]", "action": "DENY" } ] } ``` This denies any transaction from outside the US/Canada and blocks gambling MCCs. ## Card Lifecycle | Action | Dashboard | API | |--------|-----------|-----| | **Pause** | Menu > Pause Card | `PATCH /api/cards/{id}/state` | | **Resume** | Menu > Resume Card | `PATCH /api/cards/{id}/state` | | **Cancel** | Menu > Cancel Card | `PATCH /api/cards/{id}/state` | Cancelling a card deactivates all agent links. ## Monitoring The card detail page shows: - **Spend stats** - Spent today, per-tx limit, weekly/monthly limits - **Linked agents** - Each agent's individual limits and status - **Policies** - Linked policies with rule badges - **Transactions** - Recent card transactions with merchant details and status Spend tracking resets automatically at the configured intervals (daily, weekly, monthly). ## Next Steps ### Card Payments API Link: https://conto.finance/docs/sdk/card-payments Full API reference for card operations ### Policy Overview Link: https://conto.finance/docs/policies/overview Learn about the policy engine ### Securing Agents Link: https://conto.finance/docs/guides/securing-agents Security best practices ### Policy Testing Link: https://conto.finance/docs/guides/policy-testing Test policies before deployment --- # Testing Spending Policies This guide focuses on **policy semantics**: how rules, actions, and priorities combine, and how to prove it with a three-tier threshold test that approves, requires approval, or denies payments based on amount. For environment choices (agent sandbox vs testnet), counterparty and time-window scenarios, and production migration, see [Testing Payments Safely](https://conto.finance/docs/guides/testing-payments). ## Prerequisites A Conto account and organization An active agent with a linked, funded wallet and an SDK key in `CONTO_API_KEY`. The [Quickstart](https://conto.finance/docs/quickstart/setup) walks through creating the wallet, connecting the agent, and generating the key ## What You'll Build | Amount Range | Expected Result | Policy | | ------------ | -------------------------- | ------------------------------ | | $0 - $10 | **Approved** automatically | Under all thresholds | | $10 - $15 | **Requires approval** | Exceeds approval threshold | | $15+ | **Denied** | Exceeds max transaction amount | ## Step 1: Verify Your Setup Before creating policies, confirm the agent is correctly configured: ```bash curl https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_API_KEY" ``` This returns your agent's profile, linked wallets, active policies, and current spend tracking. Check that: - `agent.status` is `"ACTIVE"` - `wallets` array is not empty If either check fails, go back to the [Quickstart](https://conto.finance/docs/quickstart/setup). ## Step 2: Create Policies Create two policies to test different enforcement behaviors. ### Policy A: Spend Limit Go to **Policies** in the sidebar and click **Create Policy**. - **Name**: "Manual Spend Test" - **Description**: "Deny transactions over $15" - **Policy Type**: SPEND_LIMIT | Field | Value | |---|---| | Rule Type | `MAX_AMOUNT` | | Operator | `LTE` | | Value | `15` | | Action | `ALLOW` | This allows transactions up to $15. Anything above is denied. Info: **How rule actions work:** - `ALLOW` + `LTE $15` means: "Allow transactions where the amount is ≤ $15" - Transactions that do NOT match the ALLOW condition are implicitly denied - `DENY` + `GT $15` achieves the same effect: "Deny transactions where amount > $15" - `REQUIRE_APPROVAL` + `GT $10` means: "Require manual approval when amount > $10" Think of it as: the **action** tells Conto what to do when the **condition is true**. ### Policy B: Approval Threshold - **Name**: "Manual Approval Test" - **Description**: "Require approval for transactions over $10" - **Policy Type**: APPROVAL_THRESHOLD | Field | Value | |---|---| | Rule Type | `REQUIRE_APPROVAL_ABOVE` | | Operator | `GREATER_THAN` | | Value | `10` | | Action | `REQUIRE_APPROVAL` | Transactions over $10 require manual approval in the dashboard before they can execute. ## Step 3: Assign Policies to the Agent Navigate to your agent's detail page. Click the **Permissions** tab. Assign "Manual Spend Test" and "Manual Approval Test" to the agent. All assigned policies are evaluated with AND logic, the most restrictive rule wins. You can re-run the `GET /api/sdk/setup` call from Step 1 to confirm `policies` now shows both assigned policies. ## Step 4: Run Test Transactions Use `curl` or any HTTP client to test the three scenarios. ### Test 1: $5 Payment (Expect: APPROVED) ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 5, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Test - under all limits", "category": "software" }' ``` Expected response: ```json { "requestId": "cmm...", "status": "APPROVED", "currency": "pathUSD", "wallet": { "address": "0x788dD0...", "availableBalance": 999822 } } ``` ### Test 2: $12 Payment (Expect: REQUIRES_APPROVAL) ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 12, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Test - over approval threshold" }' ``` Expected response: ```json { "requestId": "cmm...", "status": "REQUIRES_APPROVAL", "violations": [ { "type": "PER_TX_LIMIT", "message": "[Policy: Manual Approval Test] Amount $12 exceeds approval threshold $10", "source": "policy_rule", "policyName": "Manual Approval Test" } ] } ``` ### Test 3: $20 Payment (Expect: DENIED) ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 20, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Test - over max amount" }' ``` Expected response: ```json { "requestId": "cmm...", "status": "DENIED", "violations": [ { "type": "PER_TX_LIMIT", "message": "[Policy: Manual Spend Test] Transaction amount $20 exceeds limit $15", "source": "policy_rule", "policyName": "Manual Spend Test" } ] } ``` ## Step 5: Execute an Approved Payment If Test 1 returned `APPROVED`, you can execute it onchain: ```bash curl -X POST https://conto.finance/api/sdk/payments/REQUEST_ID/execute \ -H "Authorization: Bearer $CONTO_API_KEY" ``` Response includes the `txHash` and an explorer URL to verify onchain. ## Using the SDK Instead of curl The same three tests in TypeScript (`conto.payments.request` with amounts 5, 12, and 20) are shown in the [Quickstart's SDK step](https://conto.finance/docs/quickstart/setup#step-9-same-flow-via-the-sdk). ## Editing Wallet Limits After Setup If you need to change wallet spending limits after the initial setup: 1. Go to the agent detail page 2. Open the **Overview** or **Wallets** tab 3. Click the **pencil icon** next to the wallet 4. Update per-transaction, daily, weekly, or monthly limits 5. Click **Save Changes** If the per-transaction limit is set to `$0`, the wallet-level per-transaction cap is disabled. Update it to a positive value when you need a cap. ## How Policy Evaluation Works Conto evaluates wallet-level limits first, then policy rules with AND logic. The first DENY stops evaluation. Org-level policies stack with agent-level policies. See [Policy Overview](https://conto.finance/docs/policies/overview) for the full reference. ## Troubleshooting These accordions cover policy-semantics issues. For setup issues (lost SDK keys, unfunded wallets), see the [Quickstart troubleshooting](https://conto.finance/docs/quickstart/setup#troubleshooting); for environment and scenario issues, see [Testing Payments Safely](https://conto.finance/docs/guides/testing-payments#troubleshooting). Multiple policies are evaluated with AND logic. If one policy denies while another would require approval, the denial takes priority. Check which policies are assigned in the Permissions tab. Policies at the same priority level are all evaluated. If both an approval threshold (`>$10`) and a spend limit (`>$15`) match, DENY wins over REQUIRES_APPROVAL. Priority changes sort order only; it does not override a failing rule. Org-level policies apply to all agents. If a Starter policy caps transactions at $25 and your agent policy allows up to $100, the $25 cap wins. Check with your org admin. ## Next Steps ### Policy Types Link: https://conto.finance/docs/policies/overview Explore all available policy rule types ### SDK Reference Link: https://conto.finance/docs/sdk/payments Full SDK payment methods and options ### Time Windows Link: https://conto.finance/docs/policies/time-windows Restrict payments to specific hours and days ### Counterparties Link: https://conto.finance/docs/policies/counterparties Allowlist and blocklist recipient addresses --- # Architecture Patterns These are the core integration patterns teams implement with Conto in production. Use them as canonical reference diagrams when you are designing a new agent payment workflow or documenting an existing one. ## 1. Managed Execution with an Integrated Wallet Use this pattern when Conto should both evaluate policy and orchestrate execution through an integrated wallet provider such as Privy or Sponge. ```mermaid flowchart LR Agent["Agent runtime"] --> Request["POST /api/sdk/payments/request\nautoExecute=true"] Request --> Policy["Policy engine"] Policy --> Decision{"Approved?"} Decision -->|"Yes"| Wallet["Integrated wallet provider\nPrivy or Sponge"] Decision -->|"Requires review"| Approval["Approval workflow"] Decision -->|"No"| Denied["Denied with violations"] Approval -->|"Approved"| Wallet Approval -->|"Rejected"| Denied Wallet --> Chain["Blockchain settlement"] Chain --> Audit["Transactions, audit logs,\nalerts, analytics"] ``` - Best for: teams that want fewer moving parts and Conto-managed execution. - Common controls: spend limits, approval thresholds, trust rules, time windows. ## 2. External Wallet Approval + Confirm Use this pattern when your agent already controls its own wallet or transfer tools and Conto acts as the policy gate. ```mermaid flowchart LR Agent["Agent runtime"] --> Approve["POST /api/sdk/payments/approve"] Approve --> Policy["Policy engine"] Policy --> Gate{"Approved?"} Gate -->|"Yes"| Transfer["Agent executes transfer\nwith its own keys or wallet tools"] Gate -->|"Requires review"| Review["Approval workflow"] Gate -->|"No"| Denied["Denied with reasons"] Review -->|"Approved"| Transfer Review -->|"Rejected"| Denied Transfer --> Confirm["POST /api/sdk/payments/{id}/confirm"] Confirm --> Audit["Conto records tx hash,\nstatus, audit trail"] ``` - Best for: OpenClaw and Hermes agents that already have wallet tools. - Canonical flow: `approve -> transfer -> confirm`. ## 3. x402 API Control Loop Use this pattern when an API returns `402 Payment Required` and each paid call is a separate machine payment event. ```mermaid flowchart LR Agent["Agent calls paid API"] --> Challenge["HTTP 402 challenge"] Challenge --> PreAuth["POST /api/sdk/x402/pre-authorize"] PreAuth --> Policy["x402 policy controls"] Policy --> Allowed{"Authorized?"} Allowed -->|"Yes"| Pay["Wallet signs x402 payment"] Allowed -->|"No"| Stop["Abort or escalate"] Pay --> Retry["Retry API call with payment"] Retry --> Record["POST /api/sdk/x402/record"] Record --> Analytics["Budgets, service stats,\nauditability"] ``` - Best for: pay-per-use APIs and machine commerce with explicit per-call pricing. - Core controls: price ceilings, service allowlists, endpoint velocity, service budgets. ## 4. MPP Session Lifecycle Use this pattern when an agent will make repeated requests to the same service and wants a session budget instead of separate onchain settlement for each call. ```mermaid flowchart LR Agent["Agent receives MPP payment challenge"] --> PreAuth["POST /api/sdk/mpp/pre-authorize"] PreAuth --> Policy["MPP policy controls"] Policy --> Session{"Authorized?"} Session -->|"Yes"| Open["Open session with deposit"] Session -->|"No"| Stop["Abort or escalate"] Open --> Charges["Multiple service requests\nconsume session budget"] Charges --> Close["Close session and settle"] Close --> Record["POST /api/sdk/mpp/record"] Record --> Analytics["Session budgets,\nservice usage, burn rate"] ``` - Best for: chat, streaming, iterative processing, or high-frequency service calls. - Core controls: session budget, max concurrent sessions, max duration, and service allowlists. ## 5. Human Approval Workflow Approval workflows sit in front of execution and resolve high-risk or policy-triggered payments before money moves. ```mermaid flowchart TD Request["Payment request"] --> Match["Find highest-priority matching workflow"] Match --> Create["Create approval request"] Create --> Notify["Dispatch to Slack, email,\nTelegram, WhatsApp, or webhook"] Notify --> Decide["Approver decision(s)"] Decide --> Enough{"Enough approvals?"} Decide --> Reject{"Any rejection?"} Enough -->|"Yes"| Approved["Payment approved"] Enough -->|"No"| Pending["Still pending"] Reject -->|"Yes"| Denied["Payment denied"] Reject -->|"No"| Pending Approved --> Audit["Record channel, actor,\nstatus, audit trail"] Denied --> Audit ``` - Best for: large payments, new recipients, low-trust counterparties, and finance review. - Supports multi-approver, role-based, specific-approver, and sequential workflows. ## 6. Trust Scoring Feedback Loop Trust scoring is not just a lookup; it is a feedback loop that continuously changes how counterparties are evaluated. ```mermaid flowchart LR Counterparty["Counterparty address"] --> History["Transaction history"] Counterparty --> Reliability["Failures, flags, alerts"] Counterparty --> Activity["Age, recency, consistency"] Counterparty --> Verification["Verification + network data"] Verification --> Fairscale["Fairscale for Solana\ncold-start enrichment"] Verification --> Network["Conto network intelligence"] History --> Score["Trust score + trust level"] Reliability --> Score Activity --> Score Fairscale --> Score Network --> Score Score --> Policies["Counterparty and approval policies"] Policies --> Outcomes["Allow, require approval,\nor deny"] ``` - Best for: vendor controls, trust-based approvals, network-aware risk gating. - Related docs: [/guides/trust-scoring](https://conto.finance/docs/guides/trust-scoring), [/integrations/trust-providers](https://conto.finance/docs/integrations/trust-providers) ## Which Pattern Should You Start With? | Goal | Recommended pattern | | ----------------------------------------------- | ---------------------------------------- | | Fastest first payment with minimal custom logic | Managed execution with integrated wallet | | Add guardrails to an existing agent wallet | External wallet approval + confirm | | Govern machine-paid APIs | x402 API control loop | | Govern repeated session spend | MPP session lifecycle | | Add finance or security review | Human approval workflow | | Route based on recipient quality and risk | Trust scoring feedback loop | ## Related Guides ### Choose Your Integration Link: https://conto.finance/docs/guides/choose-your-integration Decide between SDK, OpenClaw, Hermes, x402, and MPP ### Approval Workflows Link: https://conto.finance/docs/guides/approval-workflows Configure review and escalation logic ### Trust Scoring Link: https://conto.finance/docs/guides/trust-scoring Understand how recipient trust feeds policy decisions ### Recipes Link: https://conto.finance/docs/guides/recipes Copy-paste commands for the main flows above --- # Webhooks Conto sends HTTP POST requests to your configured URL when payments progress, an A2A payment request is created, a service spend record is written, or an agent is frozen or unfrozen. ## Setup 1. Go to **Settings** > **Webhooks** in the dashboard 2. Enter your HTTPS endpoint URL 3. Copy the generated **signing secret**, you'll need this to verify payloads Webhook URLs must use HTTPS. HTTP, localhost, and private IP ranges are blocked for security (SSRF protection). ## Event Types | Event | Fires when | | -------------------------- | -------------------------------------------- | | `payment.requested` | A payment request is created | | `payment.approved` | A payment passes policy evaluation | | `payment.denied` | A payment is blocked by policy | | `payment.executed` | A payment transaction is submitted onchain | | `payment.confirmed` | A payment is confirmed onchain | | `payment.failed` | A payment transaction fails | | `payment_request.created` | An agent-to-agent payment request is created | | `service_payment.recorded` | An x402 or MPP transaction is recorded | | `service_payment.failed` | An x402 or MPP transaction fails | | `agent.frozen` | An agent is frozen | | `agent.unfrozen` | An agent is restored to active status | ## Payload Format Every webhook POST includes these headers and a JSON body: ### Headers | Header | Description | | -------------------------- | -------------------------------------- | | `X-Conto-Event` | Event type (e.g., `payment.confirmed`) | | `X-Conto-Timestamp` | ISO 8601 timestamp of the event | | `X-Conto-Signature` | HMAC-SHA256 signature of the body | | `X-Conto-Delivery-Attempt` | Attempt number (1, 2, or 3) | ### Body ```json { "event": "payment.confirmed", "timestamp": "2026-04-07T12:00:00.000Z", "data": { "paymentId": "cmm5h0req000l49h7irxzh11p", "amount": 50, "transactionHash": "0xabc...", "transactionId": "cmm5g0txn000l49h7hqwyg11p", "organizationId": "cmm5i0org000l49h7jsyai11p", "agentId": "cmm5a7agt008t49h7bjqza99x" } } ``` ## Verifying Signatures Every payload is signed with your webhook secret using HMAC-SHA256. Verify signatures to confirm the request came from Conto. ```typescript import express from 'express'; import { createHmac, timingSafeEqual } from 'crypto'; function verifyWebhook(rawBody: string, signature: string | undefined, secret: string): boolean { if (!signature) return false; const expected = createHmac('sha256', secret).update(rawBody).digest('hex'); const signatureBuffer = Buffer.from(signature, 'hex'); const expectedBuffer = Buffer.from(expected, 'hex'); if (signatureBuffer.length !== expectedBuffer.length) { return false; } return timingSafeEqual(signatureBuffer, expectedBuffer); } // In your handler app.post('/webhooks/conto', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.header('x-conto-signature'); const rawBody = req.body.toString('utf8'); if (!verifyWebhook(rawBody, signature, process.env.WEBHOOK_SECRET!)) { return res.status(401).send('Invalid signature'); } const { event, data } = JSON.parse(rawBody); switch (event) { case 'payment.confirmed': console.log('Payment confirmed:', data.transactionHash); break; case 'payment.denied': console.log('Payment denied:', data.reasons); break; } res.status(200).send('OK'); }); ``` The same rule applies in other frameworks: verify the exact raw request body before you parse it. ## Retry Behavior Failed deliveries are retried up to **3 times** with exponential backoff: | Attempt | Timing | | ------- | ------------------------------------- | | 1 | Immediate | | 2 | ~1 second later | | 3 | ~3 seconds after the initial delivery | A delivery is considered failed if your endpoint returns a non-2xx status code or doesn't respond within **10 seconds**. ## Agent Callback URLs In addition to organization-level webhooks, individual agents can have a `callbackUrl` set during creation. When set, webhooks are delivered to both the organization URL and the agent's callback URL. ## Delivery Targets | Target | Configured via | Receives events for | | -------------------- | ------------------- | -------------------------- | | Organization webhook | Settings > Webhooks | All events in the org | | Agent callback URL | Agent config | Events for that agent only | Both targets receive the same payload format and signature headers. --- # Auto-Freeze Conto can automatically freeze agents when suspicious behavior is detected. When an agent is frozen, all its transactions are blocked until a human reviews and unfreezes it. ## How It Works After every transaction or policy evaluation, Conto checks the agent's behavior against configurable thresholds. If a threshold is exceeded: - **Auto-freeze enabled**: The agent is immediately suspended, its wallets are frozen, and a CRITICAL alert is created. - **Auto-freeze disabled** (default): An alert is created for visibility, but the agent continues operating. ## Trigger Types | Trigger | What it detects | Default threshold | | ------------------------------ | ------------------------------------------- | ------------------------- | | `CONSECUTIVE_VIOLATIONS` | Repeated policy denials | 5 consecutive violations | | `CONSECUTIVE_FAILURES` | Repeated transaction failures | 5 consecutive failures | | `SPEND_VELOCITY` | Hourly spend rate vs. 30-day average | 3x the average | | `LARGE_TRANSACTION_ANOMALY` | Single transaction much larger than average | 10x the average | | `TRUST_SCORE_BELOW_THRESHOLD` | Average counterparty trust too low | Below 0.2 | | `TRUST_SCORE_DROP` | Trust score dropped significantly in 24h | 30% drop | | `RAPID_COUNTERPARTY_SWITCHING` | Too many unique recipients in one hour | 10 unique recipients/hour | | `MANUAL` | Admin manually froze the agent | N/A | ### Trigger Details **Spend Velocity** compares the agent's spend in the last hour against its average hourly spend over 30 days. Requires at least 5 historical transactions to activate. **Large Transaction Anomaly** compares the most recent transaction amount to the historical average. Requires at least 10 historical transactions. **Rapid Counterparty Switching** counts distinct `toAddress` values in the last hour. A sudden spike in new recipients can indicate compromised credentials. ## Configuration Configure thresholds per agent in the dashboard under **Agents > [Agent] > Freeze Settings**, or via the freeze configuration endpoint: ```bash curl -X PATCH https://conto.finance/api/agents/AGENT_ID/freeze-config \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "autoFreezeEnabled": true, "maxConsecutiveViolations": 3, "maxConsecutiveFailures": 3, "spendVelocityMultiplier": 2, "largeTxMultiplier": 5, "minTrustScore": 0.3, "trustScoreDropThreshold": 0.2, "maxNewCounterpartiesPerHour": 5 }' ``` ### Configuration Fields | Field | Type | Default | Description | | ----------------------------- | ------ | ------- | --------------------------------------------------------- | | `maxConsecutiveViolations` | number | 5 | Freeze after N consecutive policy violations | | `maxConsecutiveFailures` | number | 5 | Freeze after N consecutive transaction failures | | `spendVelocityMultiplier` | number | 3 | Freeze when hourly spend exceeds Nx the 30-day average | | `largeTxMultiplier` | number | 10 | Freeze when a single tx exceeds Nx the historical average | | `minTrustScore` | number | 0.2 | Freeze when average counterparty trust drops below this | | `trustScoreDropThreshold` | number | 0.3 | Freeze on a 30%+ trust score drop in 24h | | `maxNewCounterpartiesPerHour` | number | 10 | Freeze when unique recipients per hour exceeds this | ## Freezing and Unfreezing ### Manual Freeze ```bash curl -X POST https://conto.finance/api/agents/AGENT_ID/freeze \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "reason": "Investigating unusual spending pattern", "freezeWallets": true }' ``` ### Manual Unfreeze ```bash curl -X POST https://conto.finance/api/agents/AGENT_ID/unfreeze \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "reason": "Investigation complete, no issues found", "unfreezeWallets": true, "resetCounters": true }' ``` Setting `resetCounters: true` (the default) resets the consecutive violation and failure counters so the agent doesn't immediately re-trigger after unfreezing. ## What Happens When an Agent Is Frozen 1. Agent status changes to `SUSPENDED` 2. All linked wallets are optionally frozen (`freezeWallets: true`) 3. A `CRITICAL` severity alert is created 4. A freeze event is recorded in the audit log 5. Webhooks fire (`agent.frozen`) 6. All subsequent payment requests return a denial ## Freeze History View freeze events in the dashboard under **Agents > [Agent] > Freeze History**, or via the API: ```bash curl https://conto.finance/api/freeze-events?agentId=AGENT_ID \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" ``` Each freeze event records: - Trigger type and trigger data - Who initiated it (user or system) - Whether wallets were frozen - Resolution timestamp and notes (after unfreezing) --- # Audit Logs Every action in Conto, creating agents, executing payments, changing policies, freezing accounts, is recorded in an immutable audit log with SHA-256 hash chains for tamper detection. ## What Gets Logged ### Actions | Action | Description | | ------------------------------------------- | ---------------------------------------------- | | `CREATE` | Resource created (agent, wallet, policy, etc.) | | `UPDATE` | Resource modified | | `DELETE` | Resource removed | | `APPROVE` / `REJECT` | Approval decision made | | `SUSPEND` / `ACTIVATE` | Agent frozen or unfrozen | | `FUND` / `WITHDRAW` / `TRANSFER` | Wallet balance changes | | `PAYMENT_EXECUTED` | Payment submitted onchain | | `PAYMENT_CONFIRMED` | Payment confirmed onchain | | `PAYMENT_DENIED` | Payment blocked by policy | | `PAYMENT_FAILED` | Payment transaction failed | | `EXTERNAL_PAYMENT_APPROVAL` | External wallet payment approved | | `EXTERNAL_PAYMENT_CONFIRMED` | External wallet payment confirmed | | `POLICY_VIOLATION` | Policy rule triggered | | `ALERT_CREATED` / `ALERT_RESOLVED` | Alert lifecycle | | `SETTINGS_CHANGED` | Organization settings modified | | `PERMISSION_GRANTED` / `PERMISSION_REVOKED` | Role or scope changes | | `LOGIN` / `LOGOUT` | User session events | | `AUDIT_LOG_EXPORTED` | Audit log data exported | ### Resources Logs track actions on: `agent`, `wallet`, `transaction`, `policy`, `policy_rule`, `organization`, `user`, `member`, `api_key`, `sdk_key`, `alert`, `counterparty`, `relationship`, `settings`, `approval_request`, `approval_workflow`, `payment_request`. ## Log Entry Fields Each audit log entry contains: | Field | Description | | --------------- | -------------------------------------------------------- | | `action` | What happened (CREATE, UPDATE, DELETE, etc.) | | `resource` | What type of resource was affected | | `resourceId` | ID of the affected resource | | `previousState` | State before the change (JSON) | | `newState` | State after the change (JSON) | | `actorType` | Who did it: USER, API, AGENT, or SYSTEM | | `actorId` | User ID, API key ID, or "system" | | `ipAddress` | Client IP (from reverse proxy headers) | | `userAgent` | Client user agent string | | `metadata` | Additional context (audit hash, change diff, API key ID) | | `createdAt` | When the action occurred | ## Change Detection When a resource is updated, the audit service automatically diffs the previous and new states and records which fields changed: ```json { "changes": [ { "field": "status", "oldValue": "ACTIVE", "newValue": "SUSPENDED" }, { "field": "spendLimitDaily", "oldValue": 1000, "newValue": 500 } ] } ``` ## Tamper-Evident Hash Chain Each log entry includes a SHA-256 hash computed over the previous entry's hash, the timestamp, action, resource, and state data. This creates a chain where modifying any entry invalidates all subsequent hashes. You can verify chain integrity from the signed-in dashboard session: ```bash curl "https://conto.finance/api/audit-logs/verify?startDate=2026-01-01T00:00:00Z&endDate=2026-04-07T00:00:00Z" \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" ``` Response: ```json { "verified": true, "totalLogs": 1247, "verifiedLogs": 1247, "brokenAt": null, "error": null } ``` If tampering is detected, the response includes `brokenAt` with the ID of the first compromised entry. ## Viewing Logs ### Dashboard Go to **Audit Logs** in the sidebar. Filter by: - Action type - Resource type - Actor (user or API key) - Date range ### Dashboard API ```bash curl "https://conto.finance/api/audit-logs?resource=agent&action=SUSPEND&limit=20" \ -H "Cookie: $CONTO_DASHBOARD_COOKIE" ``` The dashboard audit-log routes use the signed-in browser session and do not accept SDK keys or organization API keys. Set `CONTO_DASHBOARD_COOKIE` to the full Cookie header from a signed-in dashboard request. Agents that only need their own audit trail can use the SDK route: ```bash curl "https://conto.finance/api/sdk/audit-logs?resource=payment_request&limit=20" \ -H "Authorization: Bearer $CONTO_API_KEY" ``` ## IP Attribution Audit logs capture the client IP address using platform-set headers in this priority order: 1. `cf-connecting-ip` (Cloudflare) 2. `x-real-ip` (nginx) 3. `x-forwarded-for` first entry (Vercel) This allows tracing actions back to specific network locations for security investigations. --- # Roles & Permissions Conto uses role-based access control (RBAC) to manage what each team member can do within an organization. ## Roles | Role | Description | |------|-------------| | **Owner** | Full access. Can manage billing, settings, encryption keys, and all resources. An organization can have multiple Owners; the last Owner cannot remove themselves without transferring ownership first. | | **Admin** | Can manage agents, wallets, policies, API keys, and team members. Cannot change billing or encryption. | | **Manager** | Can create and update agents, manage counterparties, approve transactions, and manage alerts. Cannot create wallets or policies. | | **Viewer** | Read-only access to agents, wallets, policies, transactions, counterparties, alerts, and analytics. | | **Member** | Limited access. Can view wallets but cannot modify anything. | ## Permission Matrix | Permission | Owner | Admin | Manager | Viewer | Member | |-----------|-------|-------|---------|--------|--------| | **Agents** | | | | | | | View agents | Yes | Yes | Yes | Yes | -- | | Create agents | Yes | Yes | Yes | -- | -- | | Update agents | Yes | Yes | Yes | -- | -- | | Delete agents | Yes | Yes | -- | -- | -- | | Suspend/freeze agents | Yes | Yes | Yes | -- | -- | | **Wallets** | | | | | | | View wallets | Yes | Yes | Yes | Yes | Yes | | Create wallets | Yes | Yes | -- | -- | -- | | Fund wallets | Yes | Yes | -- | -- | -- | | Withdraw from wallets | Yes | -- | -- | -- | -- | | **Policies** | | | | | | | View policies | Yes | Yes | Yes | Yes | -- | | Create/edit policies | Yes | Yes | -- | -- | -- | | **Transactions** | | | | | | | View transactions | Yes | Yes | Yes | Yes | -- | | Execute transactions | Yes | Yes | Yes | -- | -- | | Approve transactions | Yes | Yes | Yes | -- | -- | | **Counterparties** | | | | | | | View counterparties | Yes | Yes | Yes | Yes | -- | | Manage counterparties | Yes | Yes | Yes | -- | -- | | **Alerts** | | | | | | | View alerts | Yes | Yes | Yes | Yes | -- | | Acknowledge/resolve | Yes | Yes | Yes | -- | -- | | **Analytics** | | | | | | | View analytics | Yes | Yes | Yes | Yes | -- | | Export data | Yes | Yes | -- | -- | -- | | **Settings** | | | | | | | View settings | Yes | Yes | -- | -- | -- | | Modify settings | Yes | -- | -- | -- | -- | | **Team** | | | | | | | View members | Yes | Yes | Yes | Yes | -- | | Invite/remove members | Yes | Yes | -- | -- | -- | | **API Keys** | | | | | | | View API keys | Yes | Yes | -- | -- | -- | | Create/revoke API keys | Yes | -- | -- | -- | -- | ## Managing Members ### Invite a Member Go to **Settings** > **Team** > **Invite Member**. Enter the email and select a role. ### Change a Role Changing roles requires team management permission (Owner or Admin), and role changes are enforced by hierarchy: you can only change or remove members whose role is strictly below your own. An Admin can manage Managers, Members, and Viewers, but not another Admin. Owners can manage anyone, including other Owners, and only an Owner can promote a member to Owner. The last Owner cannot be demoted or removed without transferring ownership first. ## API Key Scopes Organization API keys use scopes that map to these permissions. When creating a key, you can select a preset or pick individual scopes: | Preset | Scopes included | |--------|----------------| | **Read Only** | `*:read` scopes only | | **Standard** | Read + write for agents, wallets, policies, transactions, counterparties | | **Admin** | All scopes (Owner-only) | See [Admin SDK > Scopes](https://conto.finance/docs/sdk/admin#scopes) for the full scope list. --- # Rate Limits All API endpoints are rate-limited using a sliding window algorithm. Limits are enforced per agent (for SDK endpoints) or per IP/user (for dashboard and auth endpoints). ## Limits by Endpoint | Endpoint Category | Limit | Window | Key | |------------------|-------|--------|-----| | SDK payment endpoints (`/request`, `/execute`, `/approve`, `/confirm`) | 60 requests | 1 minute | Per agent | | SDK read endpoints (`/wallets`, `/transactions`, `/policies`, `/setup`) | 120 requests | 1 minute | Per agent | | Auth endpoints (login, register) | 10 requests | 5 minutes | Per IP | | Auth endpoints (login, register) | 5 requests | 5 minutes | Per account | | Dashboard API endpoints | 100 requests | 1 minute | Per user | Info: Auth endpoints enforce **two independent limits**: per-IP and per-account. The per-account limit prevents credential stuffing attacks that rotate source IPs. Both limits must pass for a request to proceed. ## Response Headers Every API response includes rate limit headers: | Header | Description | |--------|-------------| | `X-RateLimit-Remaining` | Requests remaining in the current window | | `X-RateLimit-Reset` | ISO 8601 timestamp when the window resets | | `Retry-After` | Seconds to wait (only present when rate limited) | ## Rate Limited Response When a request is rate limited, the API returns HTTP `429`: ```json { "error": "Rate limit exceeded. Please slow down your requests.", "code": "RATE_LIMITED", "retryAfter": 12 } ``` ## Retry Strategy The SDK handles retries automatically for `429` and `5xx` responses: - Up to **3 retries** with exponential backoff - Respects `Retry-After` headers - Backoff: 1s, 2s, 4s (capped at 10s) - Client errors (`4xx` except `429`) are not retried For manual retry logic: ```typescript async function retryOnRateLimit(fn: () => Promise , maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { const response = await fn(); if (response.status === 429) { const retryAfter = parseInt(response.headers.get('Retry-After') || '5', 10); await new Promise(r => setTimeout(r, retryAfter * 1000)); continue; } return response; } throw new Error('Rate limited after max retries'); } ``` ## Behavior on backend errors Rate limiting uses a sliding window counter backed by Redis in production. If a Redis call fails, the limiter degrades to a per-instance in-memory counter so requests keep flowing while abuse stays bounded; it does not fail closed. When Redis is not configured at all (development), the in-memory counter is used from the start. --- # Recipes Quick, self-contained solutions for specific tasks. Each recipe assumes you have an active agent with an SDK key. For initial setup, see [Quickstart](https://conto.finance/docs/quickstart/setup). ```bash # Agent SDK key (for payment operations) export CONTO_API_KEY="conto_agent_your_key_here" # Org API key (for admin operations: managing agents, wallets, policies) export CONTO_ORG_API_KEY="conto_your_org_key_here" ``` --- ## Agent Frameworks Both skill flavors below rely on `conto-check.sh`, which in turn requires `curl`, `jq`, and `python3` on `PATH`. `curl` and `python3` ship with macOS and most Linux distros; install `jq` via your package manager. `python3` powers the localhost OAuth callback used by `conto-check.sh setup`. ### Install the OpenClaw Skill ```bash npx clawhub install conto bash skills/conto/conto-check.sh setup "my-openclaw-agent" "0xYourWalletAddress" EVM 42431 ``` Use this when your OpenClaw agent already has wallet tools and you want Conto to become the policy gate. --- ### Install the Hermes Skill ```bash hermes skills install well-known:https://conto.finance/.well-known/skills/conto --force bash ~/.hermes/skills/conto/conto-check.sh setup "my-hermes-agent" "0xYourWalletAddress" EVM 42431 ``` Use this when you want Hermes-native skill installation with the same Conto policy and approval controls. Current Hermes releases require `--force` for this networked finance skill after you review the install scan. --- ## Setup ### Connect an Agent via API First fetch a membership id for the human or service account that should own the agent: ```bash curl https://conto.finance/api/organizations/me/members \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" ``` Then create the active agent with that `members[].id`: ```bash curl -X POST https://conto.finance/api/agents \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "My Agent", "agentType": "CUSTOM", "ownerMembershipId": "mem_abc123...", "status": "ACTIVE" }' ``` Returns the agent ID. Use an org-level API key (`conto_...`) for this call. Browser-session requests can default to the current member, but org API key calls should include `ownerMembershipId` so ownership and policy repair flows remain deterministic. --- ### Generate an SDK Key via API ```bash curl -X POST https://conto.finance/api/agents/AGENT_ID/sdk-keys \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Production Key", "expiresInDays": 90, "keyType": "standard" }' ``` Copy the key from the response. It's only shown once. --- ### Provision a Sponge Wallet Sponge custody uses the [`@paysponge/sdk`](https://docs.paysponge.com/sdk-reference) under the hood. Set `SPONGE_API_KEY` (and `SPONGE_MASTER_KEY` for fleet management) in your environment. ```bash curl -X POST https://conto.finance/api/wallets \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Agent Ops Wallet", "chainType": "EVM", "custodyType": "SPONGE" }' ``` Then provision it to generate an onchain address: ```bash curl -X POST https://conto.finance/api/wallets/WALLET_ID/provision \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" ``` --- ### Link a Wallet to an Agent ```bash curl -X POST https://conto.finance/api/agents/AGENT_ID/wallets \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "walletId": "WALLET_ID", "delegationType": "LIMITED", "perTransactionLimit": 100, "dailyLimit": 500, "allowedDays": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] }' ``` If you omit `allowedDays`, the wallet link is active every day. Send a narrower list, such as `["Mon", "Tue", "Wed", "Thu", "Fri"]`, only when you intentionally want weekend payments denied. --- ### Check Agent Setup Verify the agent is correctly configured with wallets and policies: ```bash curl https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_API_KEY" ``` --- ## Payments ### Request and Execute a Payment Two calls: request (policy check) → execute (onchain transfer). ```bash # Step 1: Request REQUEST=$(curl -s -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 10, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Service payment" }') echo $REQUEST # Step 2: Execute (extract requestId from response) curl -X POST https://conto.finance/api/sdk/payments/REQUEST_ID/execute \ -H "Authorization: Bearer $CONTO_API_KEY" ``` --- ### Pay an AgentScore-Gated Merchant If the merchant is AgentScore-native, include the merchant compliance policy in the request. Conto will return `VERIFICATION_REQUIRED` with a verification URL when the operator identity needs a step-up before settlement. ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 25, "recipientAddress": "0x1234567890abcdef1234567890abcdef12345678", "purpose": "Merchant checkout", "autoExecute": true, "agentScorePolicy": { "requireVerified": true, "requireKyc": true, "requireSanctionsClear": true, "allowedJurisdictions": ["US"] } }' ``` If the response status is `VERIFICATION_REQUIRED`, direct the human to `verification.verifyUrl`. Once the session completes, Conto re-runs policy evaluation and auto-executes if the original call used `autoExecute: true`. --- ### Accept Agent Payments Through a Merchant Gate Create a hosted gate for your merchant org: ```bash curl -X POST https://conto.finance/api/sdk/merchant-gates \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Agent Commerce Checkout", "requireVerified": true, "requireKyc": true, "requireSanctionsClear": true, "allowedJurisdictions": ["US", "CA"], "settlementWalletId": "WALLET_ID", "settlementAsset": "USDC", "maxAmountPerPurchase": 250 }' ``` Then let a buyer agent hit the public gate URL with the `merchant:purchase` scope: ```bash curl -X POST https://conto.finance/api/merchant/GATE_ID/purchase \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 25, "purpose": "Checkout order #1234", "category": "MERCHANT_GATE" }' ``` The gate returns either an executed payment, a normal Conto deny/approval result, or a `403` with AgentScore `verify_url` / `poll_url` / `poll_secret` fields when identity verification is still required. --- ### Check Transaction Status ```bash curl https://conto.finance/api/sdk/payments/REQUEST_ID \ -H "Authorization: Bearer $CONTO_API_KEY" ``` Returns `PENDING`, `CONFIRMING`, `CONFIRMED`, `FAILED`, or `REJECTED`. --- ### List Recent Transactions ```bash curl https://conto.finance/api/sdk/transactions \ -H "Authorization: Bearer $CONTO_API_KEY" ``` --- ### x402 and MPP Endpoint Calls The pre-authorize → record → budget/services flows are documented once, with full request and response shapes, in the SDK reference: - [x402 Payments](https://conto.finance/docs/sdk/x402-payments): pre-authorize, record (including batch), budget, services - [MPP Payments](https://conto.finance/docs/sdk/mpp-payments): pre-authorize, record settlements, budget, services For both protocols, record endpoints use flat top-level settlement fields and optional `batchItems` for per-call detail. Do not send a top-level `payments` array. The policy recipes below show how to set the guardrails those endpoints enforce. --- ### Approve and Confirm an External Wallet Payment Use this flow when your agent holds its own keys and Conto should only authorize the spend. ```bash # Step 1: Ask Conto for approval APPROVAL=$(curl -s -X POST https://conto.finance/api/sdk/payments/approve \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 50, "recipientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18", "senderAddress": "0x1a2b3c4d5e6f...", "purpose": "Vendor payout", "chainId": 42431 }') echo $APPROVAL # Step 2: Agent executes the transfer with its own wallet tools # Step 3: Confirm the onchain transfer back to Conto curl -X POST https://conto.finance/api/sdk/payments/APPROVAL_ID/confirm \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "txHash": "0xabc123...", "approvalToken": "APPROVAL_TOKEN" }' ``` --- ## Policies ### Limit Agent to $50/Day ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Daily Cap: $50", "policyType": "SPEND_LIMIT", "rules": [ { "ruleType": "DAILY_LIMIT", "operator": "LTE", "value": "50", "action": "ALLOW" } ] }' ``` Then assign to agent: ```bash curl -X POST https://conto.finance/api/agents/AGENT_ID/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "policyId": "POLICY_ID" }' ``` --- ### Require Approval Above $100 ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Approval Above $100", "policyType": "APPROVAL_THRESHOLD", "rules": [ { "ruleType": "REQUIRE_APPROVAL_ABOVE", "operator": "GREATER_THAN", "value": "100", "action": "REQUIRE_APPROVAL" } ] }' ``` --- ### Block Payments Outside Business Hours ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Business Hours Only", "policyType": "TIME_WINDOW", "rules": [ { "ruleType": "TIME_WINDOW", "operator": "BETWEEN", "value": "{\"start\": \"09:00\", \"end\": \"17:00\"}", "action": "ALLOW" }, { "ruleType": "DAY_OF_WEEK", "operator": "IN_LIST", "value": "[\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\"]", "action": "ALLOW" } ] }' ``` --- ### Allowlist Specific Recipients ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Approved Vendors Only", "policyType": "COUNTERPARTY", "rules": [ { "ruleType": "ALLOWED_COUNTERPARTIES", "operator": "IN_LIST", "value": "[\"0x1234567890abcdef1234567890abcdef12345678\", \"0xabcdef1234567890abcdef1234567890abcdef12\"]", "action": "ALLOW" } ] }' ``` --- ### Cap x402 API Spending ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "x402 Guardrails", "policyType": "COMPOSITE", "rules": [ { "ruleType": "X402_MAX_PER_REQUEST", "operator": "LTE", "value": "0.10", "action": "ALLOW" }, { "ruleType": "X402_MAX_PER_SERVICE", "operator": "LTE", "value": "{\"maxAmount\": 25, \"period\": \"DAILY\"}", "action": "ALLOW" } ] }' ``` --- ### Restrict to Allowed x402 Services ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "x402 Service Allowlist", "policyType": "COMPOSITE", "rules": [ { "ruleType": "X402_ALLOWED_SERVICES", "operator": "IN_LIST", "value": "[\"api.example.com\", \"data.provider.io\"]", "action": "ALLOW" } ] }' ``` --- ### Cap MPP Session Deposits ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "MPP Session Guardrails", "policyType": "COMPOSITE", "rules": [ { "ruleType": "MPP_MAX_SESSION_DEPOSIT", "operator": "LTE", "value": "25", "action": "ALLOW" }, { "ruleType": "MPP_MAX_PER_REQUEST", "operator": "LTE", "value": "1.00", "action": "ALLOW" }, { "ruleType": "MPP_MAX_CONCURRENT_SESSIONS", "operator": "LTE", "value": "3", "action": "ALLOW" } ] }' ``` --- ### Restrict MPP to Allowed Services ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "MPP Service Allowlist", "policyType": "COMPOSITE", "rules": [ { "ruleType": "MPP_ALLOWED_SERVICES", "operator": "IN_LIST", "value": "[\"api.service.com\", \"streaming.provider.io\"]", "action": "ALLOW" } ] }' ``` --- ## Approvals & Trust ### Look Up Trust for a Counterparty Address ```bash curl https://conto.finance/api/sdk/network/trust/0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18 \ -H "Authorization: Bearer $CONTO_API_KEY" ``` Requires the `network:read` scope. Returns global trust information, relationship-specific trust data, transaction history, and any network flags. --- ### Require Approval for Large Payments and Use Slack for Review The fastest production pattern is: 1. Create an approval threshold rule: ```bash curl -X POST https://conto.finance/api/policies \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Approval Above $500", "policyType": "APPROVAL_THRESHOLD", "rules": [ { "ruleType": "REQUIRE_APPROVAL_ABOVE", "operator": "GREATER_THAN", "value": "500", "action": "REQUIRE_APPROVAL" } ] }' ``` 2. Configure a Slack approval channel: See [/guides/external-approvals](https://conto.finance/docs/guides/external-approvals) for the full Slack setup and approval action flow. --- ## Monitoring ### Get Agent Spending Summary ```bash curl "https://conto.finance/api/sdk/analytics?period=month" \ -H "Authorization: Bearer $CONTO_API_KEY" ``` --- ### Get Wallet Balance ```bash curl https://conto.finance/api/sdk/wallets \ -H "Authorization: Bearer $CONTO_API_KEY" ``` Returns all linked wallets with current balances. --- ### List Active Alerts ```bash curl https://conto.finance/api/alerts \ -H "Authorization: Bearer $CONTO_ORG_API_KEY" ``` --- ## TypeScript SDK Equivalents The recipes above use curl. Here are the payment operations in TypeScript using the SDK: ```typescript import { Conto } from '@conto_finance/sdk'; const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! }); // Request + execute payment const req = await conto.payments.request({ amount: 10, recipientAddress: '0x...', purpose: 'Service payment', }); if (req.status === 'APPROVED') { const tx = await conto.payments.execute(req.requestId); console.log(tx.explorerUrl); } // Check status const status = await conto.payments.status(req.requestId); // Single-call payment (request + execute) const result = await conto.payments.pay({ amount: 50, recipientAddress: '0x...', purpose: 'API credits', }); console.log(result.txHash); ``` Note: The `Conto` class provides `conto.payments` for agent payment operations. For admin operations (agents, wallets, policies) use `ContoAdmin`, see the [Admin SDK](https://conto.finance/docs/sdk/admin). For x402 and MPP, use the REST endpoints in the [x402](https://conto.finance/docs/sdk/x402-payments) and [MPP](https://conto.finance/docs/sdk/mpp-payments) SDK references; for transaction listing and wallet queries, use the curl recipes above. ## Related ### Choose Integration Link: https://conto.finance/docs/guides/choose-your-integration SDK vs Agent Skills vs x402 vs MPP ### Quickstart Link: https://conto.finance/docs/quickstart/setup Full setup walkthrough ### x402 Payments Link: https://conto.finance/docs/guides/x402-api-payments Pay for APIs with x402 ### MPP Sessions Link: https://conto.finance/docs/guides/mpp-session-payments Session-based micropayments ### Approval Workflows Link: https://conto.finance/docs/guides/approval-workflows Add review and escalation controls ### Trust Scoring Link: https://conto.finance/docs/guides/trust-scoring Use counterparty trust as a control surface --- # API Reference Conto publishes its REST API reference from the same OpenAPI source used by the in-app Swagger viewer. If you are onboarding a customer or integration partner, start with the interactive reference below and pair it with the authentication and operational guides in this page. ## Primary References | Resource | URL | Best for | | -------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------- | | Interactive API docs | [https://conto.finance/api-docs](https://conto.finance/api-docs) | Browsing endpoints and trying requests in Swagger UI | | OpenAPI JSON | [https://conto.finance/api/openapi](https://conto.finance/api/openapi) | Code generation and schema validation | | SDK guides | [/sdk/installation](https://conto.finance/docs/sdk/installation) | Agent-facing integration patterns and examples | | Admin SDK guide | [/sdk/admin](https://conto.finance/docs/sdk/admin) | Organization-level automation with `ContoAdmin` | | Error handling | [/sdk/error-handling](https://conto.finance/docs/sdk/error-handling) | Status codes, retryable failures, and recovery | | Rate limits | [/guides/rate-limits](https://conto.finance/docs/guides/rate-limits) | Throughput planning and backoff strategy | | Webhooks | [/guides/webhooks](https://conto.finance/docs/guides/webhooks) | Event delivery, signatures, and retries | ## Authentication Use the credential type that matches the API surface you are calling: | Credential | Format | Use for | Notes | | ---------- | ------ | ------- | ----- | | Browser session | Session cookie | Dashboard-originated `/api/*` requests | Used by the web app after login | | Organization API key | `conto_...` | Org-level provisioning and management endpoints such as `/api/agents`, `/api/wallets`, `/api/policies`, and `/api/api-keys` | Works with `ContoAdmin` | | Agent SDK key | `conto_agent_...` | Agent-facing `/api/sdk/*` endpoints | Works with the `Conto` client | See [/sdk/authentication](https://conto.finance/docs/sdk/authentication) for the full key matrix, expiration behavior, and scope model. ## Base URLs | Surface | URL | | ------- | --- | | Production API base URL | `https://conto.finance` | | Interactive reference | `https://conto.finance/api-docs` | | OpenAPI spec | `https://conto.finance/api/openapi` | | Public guides | `https://conto.finance/docs` | ## Common Integration Paths - **Agent payment flow:** Start with [/sdk/payments](https://conto.finance/docs/sdk/payments) for request, approval, execution, and status flows. - **Org provisioning and control-plane automation:** Use [/sdk/admin](https://conto.finance/docs/sdk/admin) for agents, wallets, policies, and SDK key lifecycle management. - **External-wallet approval flows:** Use [/guides/external-approvals](https://conto.finance/docs/guides/external-approvals) when Conto evaluates a payment but your infrastructure broadcasts the transaction. - **Service-to-service micropayments:** Use [/guides/x402-api-payments](https://conto.finance/docs/guides/x402-api-payments) or [/guides/mpp-session-payments](https://conto.finance/docs/guides/mpp-session-payments) for x402 and MPP flows. ## Operational Expectations - `POST /api/sdk/payments/request` supports `idempotencyKey` for safe client retries. - SDK keys always expire automatically: default lifetime is 365 days and the maximum is 730 days. - Org API keys always expire too: `expiresInDays` defaults to 365 and is capped at 365. - Webhook endpoints must be public HTTPS URLs and should verify Conto signatures on every request. - Rate limits differ between SDK routes and dashboard routes; design clients to honor `429` and `Retry-After`. --- # Defaults This page is the single source of truth for default values in Conto. Other pages link here instead of restating values inline, so the docs stay consistent when defaults change. ## Chains and currencies The API/SDK and the CLI use different chain defaults on purpose. The API defaults to testnet so backend integrations are safe by default. The CLI defaults to mainnet because interactive operators usually want production. | Setting | Default | Notes | |---|---|---| | Default chain ID (API/SDK) | `42431` (Tempo Testnet) | Applied when `chainId` is not supplied to `POST /api/wallets` or `POST /api/sdk/payments/request`. | | Default chain ID (CLI) | `4217` (Tempo Mainnet) | Used by `create-conto-agent` interactive prompts. Override with `--chain`. | | Default chain type | `EVM` | Applied to new wallets when omitted. | | Default Tempo Mainnet currency | `USDC.e` | Returned in payment responses for chain `4217`. | | Default Tempo Testnet currency | `pathUSD` (TIP-20) | Returned in payment responses for chain `42431`. | | Default Base/Ethereum/Arbitrum/Polygon currency | `USDC` | Resolved per chain by `getPrimaryStablecoin(chainId)`. | | Default Solana currency | `USDC` (SPL) | Resolved by chain ID `solana-mainnet`. | ### Explorer URLs Tempo has two networks with two explorers. Each is canonical for its chain. | Chain ID | Name | Explorer | |---|---|---| | `4217` | Tempo Mainnet | `https://explore.tempo.xyz` | | `42431` | Tempo Testnet | `https://explore.moderato.tempo.xyz` | EVM chains use the standard block explorers (`basescan.org`, `etherscan.io`, etc.) and Solana uses `solscan.io` / `explorer.solana.com`. ## Wallets `POST /api/wallets` applies these Zod defaults before persisting: | Field | Default | |---|---| | `walletType` | `EOA` | | `chainType` | `EVM` | | `chainId` | `42431` (via `getDefaultChain()`) | | `custodyType` | `PRIVY` | | `isWatchOnly` | `false` | ### Custody priority The payment evaluator selects wallets in this order when an agent has multiple linked wallets: `PRIVY > SPONGE > SMART_CONTRACT > EXTERNAL` Executable custody (PRIVY, SPONGE) is preferred so platform-routed payments do not need user intervention. ## Agent-wallet links `POST /api/agents/{id}/wallets` applies these defaults: | Field | Default | Notes | |---|---|---| | `delegationType` | `LIMITED` | Other values: `FULL`, `VIEW_ONLY`, `PREAPPROVED`, `ALLOWLIST`. | | `spendLimitPerTx` | `100` | USD. `null` means unlimited. | | `spendLimitDaily` | `1000` | `null` means unlimited. | | `spendLimitWeekly` | `null` | Unlimited unless set. | | `spendLimitMonthly` | `null` | Unlimited unless set. | | `allowedHoursStart` | `0` | Hour of day, 0-23. | | `allowedHoursEnd` | `24` | Hour of day, 1-24. | | `allowedDays` | `['Mon','Tue','Wed','Thu','Fri']` | Use full 7-day list to allow weekends. | | `timezone` | `UTC` | IANA names accepted (`America/New_York`, etc.). | For wallet-level spend limits, `null`, omitted fields, and `0` mean "unlimited". Use a positive number to enforce a cap. ## External-wallet auto-create When `POST /api/sdk/payments/approve` is called with a `senderAddress` that does not yet exist in the organization, Conto creates an EXTERNAL wallet automatically with: | Field | Default | |---|---| | `spendLimitPerTx` | `null` (unlimited per transaction) | | `spendLimitDaily` | `1000` USD | | `spendLimitWeekly` | `5000` USD | | `spendLimitMonthly` | `20000` USD | | `custodyType` | `EXTERNAL` | | `enforcementMode` | `MONITORING_ONLY` | Tighten these via `PATCH /api/agents/{agentId}/wallets/{walletId}` before relying on them in production. ## Approval tokens | Endpoint | Token TTL | |---|---| | `POST /api/sdk/payments/request` | 5 minutes | | `POST /api/sdk/payments/approve` (external wallets) | 10 minutes | | `POST /api/sdk/cards/approve` | 5 minutes | Tokens are single-use. After expiry, request approval again. ## SDK keys | Setting | Default | Notes | |---|---|---| | `expiresInDays` | `365` | Optional. Defaults to 365 when omitted. | | Max `expiresInDays` | `730` | 2-year hard cap. | | Key format (standard) | `conto_agent_...` | Per-agent. Used for payment operations. | | Key format (admin) | `conto_agent_...` | Per-agent. Adds `agents:write`, `wallets:write`, `policies:write`. | | Org API key format | `conto_...` | Org-level. Used with `ContoAdmin`. | Full keys are returned only once at creation. Store them immediately. ## Payment requests | Setting | Default | |---|---| | `currency` (on `POST /api/transactions`) | `USDC` | | `urgency` | `NORMAL` | | `autoExecute` | `false` | | Idempotency window | Indefinite. Same `idempotencyKey` + same payload returns the cached result. Different payload returns `409 IDEMPOTENCY_CONFLICT`. | ## Policy evaluation | Setting | Default | Notes | |---|---|---| | Policy priority direction | Higher first | `evaluatePolicyRules` sorts by descending priority. | | Default policy priority | `50` | Use `0-100`. Reserve 90+ for security/compliance rules you want evaluated first. | | Rule combination | `AND` | All rules in a policy must pass. | | Policy combination | `AND` | All policies assigned to an agent must pass. First `DENY` stops evaluation. | | Counterparty trust storage | Decimal `0.0-1.0` | Rule values for `TRUST_SCORE` use the same scale. Defaults to `0.5` (`UNKNOWN`). | ## Counterparties | Field | Default | |---|---| | `trustScore` | `0.5` | | `trustLevel` | `UNKNOWN` | | `riskLevel` | `MEDIUM` | | `verified` | `false` | | `type` | `VENDOR` | Trust levels map to score ranges: | Range | Level | |---|---| | `0.75 - 1.0` | `TRUSTED` | | `0.5 - 0.75` | `VERIFIED` | | `0.2 - 0.5` | `UNKNOWN` | | `0.0 - 0.2` | `BLOCKED` | ## Rate limits | Endpoint group | Limit | Window | Key | |---|---|---|---| | SDK payment endpoints | 60 | 1 minute | Per agent | | SDK read endpoints | 120 | 1 minute | Per agent | | Auth endpoints | 10 | 5 minutes | Per IP | | Account auth | 5 | 5 minutes | Per account | | Dashboard | 100 | 1 minute | Per user | Sliding window. Fails closed if the backing store is unavailable. ## Pagination | Field | Default | |---|---| | `limit` | `50` | | Max `limit` | `100` | | `offset` | `0` | Paginated responses return `{ items, total, limit, offset }`. ## Webhook delivery | Setting | Default | |---|---| | Max retries | `3` | | Backoff | Immediate first attempt, retries after 1s, then 2s | | Timeout | 10 seconds | | Signature header | `X-Conto-Signature` (HMAC-SHA256) | | Required scheme | HTTPS (HTTP and private IPs blocked) | ## Auto-freeze thresholds | Trigger | Default threshold | |---|---| | `CONSECUTIVE_VIOLATIONS` | 5 | | `CONSECUTIVE_FAILURES` | 5 | | `SPEND_VELOCITY` | 3x normal | | `LARGE_TRANSACTION_ANOMALY` | 10x normal | | `TRUST_SCORE_BELOW_THRESHOLD` | `<0.2` | | `TRUST_SCORE_DROP` | `30%` | | `RAPID_COUNTERPARTY_SWITCHING` | 10 per hour | Tunable via `PATCH /api/agents/{id}/freeze-config`. ## Org roles `OrgRole` enum: `OWNER`, `ADMIN`, `MANAGER`, `MEMBER`, `VIEWER`. New members default to `MEMBER`. See [Roles and permissions](https://conto.finance/docs/guides/roles-permissions) for the permission matrix. --- # Changelog Product updates from Conto The latest features, improvements, and fixes shipped to Conto. Entries are grouped by release date with the most recent at the top. Want to be notified of new releases? Follow [@contofinance](https://twitter.com/contofinance) on Twitter or join our [Discord community](https://discord.gg/h7rYrpkrRt). ## July 5, 2026 ### x402 Budgets Support Session-Aware Tracking Conto now tracks x402 budgets by `sessionId`, so teams can measure burn rate and remaining budget for a specific API payment session instead of only viewing aggregate protocol spend. The SDK, public docs, and policy guides now expose the same session-aware x402 and MPP budget flows, making it easier to pre-authorize, record, and monitor machine-payable API usage with one consistent integration model. ## June 22, 2026 ### Anonymous Agent Sandbox Quickstart Conto now includes an anonymous agent sandbox flow that creates a test-mode organization, agent, Tempo Testnet wallet, and SDK keys without email verification or manual setup. The launch also adds a dedicated Mintlify quickstart and claim flow, giving agent builders a faster path to test policy evaluation, receipts, and audit behavior before wiring up a production integration. ## June 18, 2026 ### Conto Pay Live Rollout Guidance Conto Pay docs now include a dedicated live rollout guide for launch evidence, live-review requests, rollout gate modes, public rollout evidence, and agent behavior. Operators and authenticated agents can use the guide to understand when a hosted workspace should stay in sandbox, request Conto review, wait for support, or present live-money capability. Conto Pay guides and the solution page now also call out saved-contact trust review: Profile API fingerprints and ETags can be used to compare current payee identity, and unresolved trust warnings block saved-contact payment preparation until the operator reviews the current profile. ## June 12, 2026 ### CLI Quickstart Works End to End The `npx @conto_finance/create-conto-agent` quickstart now produces a setup that can pay in production. The wizard creates wallets with the server's default custody, installs the `conto` CLI into your project so `npx conto ` resolves correctly, and writes a runnable `example.ts` with an opt-in `--execute` step. New `conto doctor` command diagnoses auth, key scopes, wallet, custody, chain, balance, and base URL in one pass, backed by `GET /api/sdk/setup`, which now reports per-wallet `executionMode` and `isTestnet`. Standard SDK keys are documented as they actually behave: the preset covers the full payment lifecycle (`payments:request`, `payments:execute`, `payments:approve`, `payments:confirm`) plus read scopes, and the key creation response now lists the granted scopes. ## June 11, 2026 ### Hosted Conto Pay Profiles, Requests, and Receipts Conto Pay now supports hosted profile URLs and handles, payee-initiated payment requests, request review pages, direct-payment receipt pages, and a unified activity inbox so teams can manage discovery, receivables, approvals, and payment follow-up from one hosted workspace. ### Network Intelligence Sharing Controls and Explainability The Network workspace now exposes richer trust explainability, including detailed entity views, contribution-aware trust lookups, Fairscale recommendation and red-flag context for Solana, and organization-level sharing modes for full, partial, receive-only, or disabled participation. ## May 6, 2026 ### Security Disclosure Policy Conto now publishes a public security disclosure page and machine-readable `security.txt`, making it easier for customers and security researchers to report issues and review scope, response expectations, and safe-harbor guidance. ## April 28, 2026 ### Interactive Solutions Pages Five public solutions pages now let teams see live Conto policy evaluation across delivery, global payroll, agentic commerce, supply chain, and AI infrastructure scenarios, including both approved and blocked paths. ## April 26, 2026 ### Policy Template Library The Policies workspace now includes use-case-driven templates for infrastructure, vendor payouts, marketing, research, compliance, and time-bound workflows, with recommended limits and similar-policy benchmarks. ## April 24, 2026 ### Trust Score Explainability Counterparty trust scores now show weighted score breakdowns, positive and negative signals, recommended actions, and the next milestone needed to improve trust. ## April 23, 2026 ### Hosted Conto Pay Assistant Workflow Conto Pay now supports a fuller end-to-end workflow in chat, including wallet readiness, recipient setup, approvals, retries, cancellations, and payment execution from one assistant thread. ## April 21, 2026 ### Unified Billing Command Center Billing settings now bring plan details, live usage meters, forecasts, alerts, and invoices together in one workspace so owners and admins can monitor spend in one place. ## April 20, 2026 ### Public Pricing Page Conto now includes a public pricing page with Free, Builder, and Enterprise tiers, plus a public tiers endpoint that keeps plan details consistent across the product and marketing site. ## April 16, 2026 ### Machine Spend Analytics A new Machine Spend Analytics view gives teams a clearer picture of agent spend, counterparty activity, and payment protocol usage. ## April 15, 2026 ### Hardened Approval Workflows Approval workflows now behave more consistently across in-app and external channels, with stronger safeguards around approvals, notifications, and payment handling. ## April 14, 2026 ### Dashboard UX Refresh The dashboard has been updated to make setup, transaction review, approval handling, and navigation faster across desktop and mobile. ### Accessibility Improvements Accessibility updates improved keyboard navigation, screen reader support, table semantics, and contrast across the product. ### Admin Panel Updates The admin panel now gives teams better visibility into user activity, audit history, and signup monitoring. ### Developer Page Polish The in-dashboard developer reference now includes clearer examples and better guidance for sandbox usage and error handling. ## April 13, 2026 ### Improved AI Assistant Experience The AI Assistant experience now includes a cleaner mobile layout, clearer confirmations, better error states, and improved visibility into tool progress. ## April 12, 2026 ### Global AI Assistant Conto now includes a global AI Assistant that can be opened from anywhere in the dashboard. Teams can use natural language to work across agents, wallets, policies, counterparties, and approvals from one interface. ## Previous Releases For older changes, see the full [`CHANGELOG.md`](https://github.com/Conto-Finance/conto/blob/main/CHANGELOG.md) on GitHub. --- ## Blog Posts (Full Content) --- Agentic payments have arrived faster than most infrastructure is prepared for. Agents are purchasing services, paying for APIs, buying compute, and executing transactions without humans in the loop. But the current state of agentic commerce resembles something far less structured than a modern financial system. There are no controls for agents that pay. It's the Wild West. ## The New Gunslingers: Agents with Wallets A new class of economic participant is emerging: autonomous agents with the ability to spend money. As intelligence improves, financial autonomy becomes inevitable. An agent that can decide what to do will need the ability to decide what to pay for. It's the next step towards AGI. When you add money into the equation, the significance of every transaction goes up. Powered by stablecoins and programmable payment rails, agents can move money instantly, around the world, at high frequency, all without knowing their counterparties or using intermediaries. This is powerful, but also comes with risks. There are few standardized controls, limited visibility, and almost no purpose-built governance systems for non-human spenders. This leads to: - No clear spending boundaries - Minimal verification of counterparties - Fragmented compliance - Little real-time oversight While stablecoins remove friction, they also lack safeguards embedded in traditional financial systems. The result is that agents can fire off payments as they see fit. If agentic payments is going to be adopted by the enterprise, new controls are needed. ## Why Enterprises Need Guardrails Enterprises operate under strict requirements. There are financial controls they need to adhere to, regulations that are non-negotiable, governance and audit demands, and an overall need to manage risk and reporting. An enterprise deploying thousands of agents faces new challenges including: - Overspending across agents - Payments to malicious counterparties - Agents going rogue - Compliance violations Without a control layer, scaling agentic payments is not viable. Enterprises need a system that sits between agent intent and payment execution, a layer that determines: - Should this agent be allowed to spend? And how much? - Who can it transact with? - Under what conditions? - How is activity monitored and audited? ## What Guardrails Look Like To move from experimentation to production, agentic payments need programmable controls across several areas including: ### 1. Policy and Authorization - Dynamic spending limits - Context-aware approvals - Counterparty allowlists/blocklists - Multi-step authorization for high-risk actions ### 2. Real-Time Observability - Live transaction monitoring - Agent-level spend visibility - Alerts for anomalous behavior ### 3. Compliance and Audit - Immutable transaction logs - Explainability of agent actions - Audit-ready reporting ### 4. Identity and Permissions - Verified agent identities - Scoped permissions by task - Human in the loop approval workflows ### 5. Counterparty Intelligence - Trust scoring for vendors and APIs - Shared risk signals - Detection of malicious actors These are core features needed to take agentic payments from an experiment to enterprise-ready. ## A Control Center for Agentic Payments The existing corporate finance stack was built for humans. Approval workflows, expense reports, procurement systems, and static card limits weren't built for agentic speed and scale. Enterprises need a control center to monitor, govern, and manage agents that spend money. We're building that at **Conto**. From spend management to understanding relationships between agents, APIs, and merchants, we're giving organizations a new way to manage agentic payments. ## Wrangling the New Frontier Every new technology goes through a similar cycle. Experimentation, adoption, the emergence of risk, and the controls and institutionalization of processes that follows. Agentic payments are still early - high potential, high risk, minimal structure. The companies that define this category will be those that introduce trust, control, and visibility. --- Want to securely deploy agentic payments in your organization? Get in touch to see how we can help you manage your agentic spending. [Contact us](mailto:support@conto.finance). --- Agentic payments has taken the timeline by storm (again). But this time they're moving from novelty to infrastructure. Soon agents will purchase services, manage supply chains, procure compute, payout contractors and execute transactions across the internet that previously had humans in the loop. Betting against agentic payments is betting against AGI. It's inevitable. Much of the discussion around agentic payments has focused on consumer use cases - personal AI assistants booking travel, agents shopping online, or bots interacting with marketplaces. The largest opportunity for agentic payments and stablecoins in particular is not consumer commerce - it's the enterprise. Across fintech, retail, e-commerce, logistics, and infrastructure, companies are already deploying AI agents to automate operational workflows, develop new products, and improve the customer experience. As those agents become more capable, they will inevitably take responsibility for payments as well. Industries that demand fast settlement and high-volume programmable transactions are where we'll see adoption first. Giving agents the ability to pay is one step closer to true autonomy because they're putting money on the line. This shift demands a new category of financial infrastructure designed not for humans, but for agents. ## Applications in the Enterprise Enterprises will adopt agentic payments at much larger scale, volume, and value, and with different use cases than consumers. Companies already operate complex workflows that require constant coordination across vendors, suppliers, and infrastructure providers. A few areas where enterprise payment agents are emerging: ### Procurement Agents that monitor pricing and automatically purchase tools, APIs, or services when needed. ### Compute Infrastructure Agents that dynamically purchase compute, storage, or bandwidth from cloud providers or decentralized infrastructure networks. ### Supply Chain Agents that reorder inventory when stock runs low, negotiate vendor pricing, and manage logistics payments. ### Finance and Treasury Agents that manage liquidity, route payments, or optimize settlement rails. Today, humans sit in the middle of those transactions. They click send and fill out the documentation to make sure things happen on time. As agents further integrate into the business, the financial layer will evolve to support agentic payments. Enterprise operations involve massive payment flows. Even small automation improvements can generate significant financial throughput. ## The Payment Chain Era Another significant tailwind driving enterprise adoption of agentic payments is the focus of blockchain infrastructure on enterprise use cases. Previously, blockchain ecosystems focused on retail users, speculative assets, gaming, trading or DeFi. A new generation of payments-focused Layer-1 networks is prioritizing real economic activity. New stablecoin infrastructure like Tempo and Arc is designed specifically to support agentic payments. Programmable, real-time settlement, micropayments, and remittances are just a few of the use cases enabled by this technology. Enabling instant, low cost payments across users, agents, services, and businesses is critical. For enterprises deploying AI agents, this infrastructure removes many of the limitations of legacy financial systems. It is also a perfect fit for the new products that organizations can build with agents. Think about a platform like DoorDash or Deel automating instant contractor payouts with an agent. Or a frontier lab deploying a GPU compute trading agent to secure the best pricing and supply of compute for training runs and to match inference demand. Or fintechs leveraging agents and stablecoin rails to move money faster so it's where their clients want it to be - instead of waiting for wires to go through over the weekend or T+1 or T+2 settlement. ## The Enterprise Problem: Trust Enterprises do not simply need agents that can pay. They need agents they can trust. It's okay to just give your agent a card or wallet and have it spend when you're experimenting with OpenClaw or building an agent over the weekend. Enterprise-grade agentic payments are a whole different beast. Compliance, regulations, governance, making sure the CFO has visibility into agentic spending for the last week - there's a new set of requirements that must be met. Existing corporate financial systems were designed around human employees. Expense platforms like Ramp or Brex manage spending through familiar mechanisms like card limits and approval workflows. These controls work when transactions happen at human speed. They break down when thousands of agents are transacting simultaneously, interacting with counterparties both internal and external to the business. Imagine a company deploying thousands of autonomous agents across its operations. Without proper governance infrastructure, companies face serious risks: - Agents overspending - Interacting with malicious counterparties - Triggering compliance violations - Creating financial exposure across multiple systems Enterprises need spend management, designed from the ground up for agents. Policies, workflows, compliance, the gritty details of what makes companies function needs to apply to agents too. This control layer becomes essential infrastructure for the agent economy. Without it, enterprises cannot safely deploy autonomous financial actors. ## The Agentic Economy The number of AI agents operating across the internet will grow into the trillions. The agent economy will be a new contributor to the GDP of the internet. The enterprise will be a key driver of this transformation - but they cannot capitalize on it without the infrastructure required to govern autonomous financial behavior. 1. **Step 1:** Enabling agents to pay 2. **Step 2:** Building the financial operating system that allows companies to safely deploy these agents Together, they enable the next phase of the internet. Think beyond knowledge agents. It's the age of economic agents. --- Want to securely deploy agentic payments in your organization? Get in touch to see how we can help you manage your agentic spending. [Contact us](mailto:support@conto.finance). --- When an agent is about to send a payment to a Solana wallet it has never interacted with before, what does it know about the recipient? Until now, the answer was: not much. Today we're announcing our integration with [Fairscale](https://fairscale.xyz), a composable reputation scoring system for Solana wallets. Every Solana address that passes through Conto is now automatically enriched with onchain behavioral data. Agents, and the organizations behind them, now have real trust signals before money moves. ## Who Can You Trust? Trust in agentic payments has a cold start problem. When an agent encounters a new counterparty, there's no transaction history to draw from. No past interactions, no success rate, no volume data. The address is a blank slate. For human-driven payments, this might be acceptable. A user can do research, ask questions, or start with a small amount. Agents don't have that luxury. They need to make decisions quickly, often at scale, and they need data to inform those decisions. Without trust data, organizations are left with two options: block unknown addresses entirely (limiting agent capability) or allow them through with no assessment (accepting unquantified risk). Neither option works well. ## What Fairscale Brings ![Fairscale reputation score for a Solana address on the Conto Network page](https://conto.finance/images/blog/fairscale-trust-lookup.png) Fairscale analyzes onchain behavioral signals across Solana to produce a reputation score from 0 to 100. It looks at: - **Transaction patterns** - frequency, consistency, and recency of activity - **Token holdings** - portfolio composition and economic stake - **Staking activity** - participation in network security - **Social connections** - onchain relationships and community involvement This gives us a behavioral fingerprint for any Solana wallet, even if Conto has never seen it before. When a Solana address comes through Conto with no existing network data, Fairscale scores are automatically normalized and used as the trust baseline. Agents and organizations get a real score instead of an empty default. No configuration needed, it's built in for every organization on Conto. ## What This Means for Trust Scoring Fairscale data feeds into Conto's native trust score calculation that comes included as part of our platform. Here's how it fits into the broader picture: 1. **Conto Network Intelligence** comes first - real transaction history from across the platform is the strongest trust signal 2. **Fairscale reputation** fills in the gaps - when an address has no network history on Solana, Fairscale provides a behavioral baseline 3. **Compliance checks** always run regardless of trust score This layered approach means trust scores get more accurate over time. A new Solana address starts with Fairscale data, and as it transacts through Conto, network intelligence takes over with increasingly rich signals. ## Building With the Ecosystem We believe the best infrastructure is composable. The agentic payments and commerce ecosystem is full of teams building specialized, high-quality services. Our job is to bring those tools together in a way that makes it safer and more reliable for agents to transact. As new reputation systems, risk providers, and intelligence platforms emerge across different chains, we will bring the best of them to Conto. Building in the space? [Get in touch](mailto:support@conto.finance)! ## Try It - Soon The Fairscale integration will be included for all organizations on Conto when we go live. Look up any Solana address on the Network page to see its Fairscale reputation data. For organizations that want to enforce reputation thresholds, you can add a Fairscale minimum score policy rule to block payments to wallets below a specified score. --- Want to learn more about how Conto handles agent risk and trust? Send us an email at [support@conto.finance](mailto:support@conto.finance). --- We spent a day at Stripe Sessions. Here's what we learned. Despite the apathy and disillusion on the timeline, agentic commerce is very real. The largest companies in payments, e-commerce, and infrastructure are continuing to invest aggressively and are putting real resources behind it. It was front and center across keynotes and partner sessions. The gap is not conviction. The gap is consumer behavior catching up to the tech. Anyone involved in selling on the internet does not want to be caught off guard the way many were by AI a few years ago. Making products legible to agents, enabling seamless checkout, and laying the right rails for autonomous transactions are all underway. ## Agentic commerce has real backing One of the clearest takeaways from the event was that agentic commerce is not a side conversation anymore. It is becoming part of the roadmap at the companies that already shape how money moves online. The foundations are being set now. Teams want to make sure their products can be discovered, understood, and purchased by agents when that behavior becomes mainstream. That work is happening before consumer behavior fully catches up. ## Stablecoins and MPP are moving into the conversation I was happily surprised by how much airtime MPP, Tempo, Privy, and stablecoins got. Having those topics mentioned by Patrick Collison at the start of the keynote and then demoed by John Collison matters. Stripe is doing a lot to make frontier financial infrastructure understandable and accessible for developers and enterprises. That kind of distribution and validation helps move the whole space forward. The framing felt practical. These technologies are being adopted because they are often the best tools for global, programmable, agent-driven transactions. ## The market is starting to take shape Agentic payments are still early, but the shape of the market is becoming clearer. Stablecoin rails are emerging as the default for new, global, and high-frequency use cases like API access. Enterprise automation is another clear area of interest. Cards still make sense for existing consumer and e-commerce flows. This looks much more like a layering of systems than a zero-sum shift. Tempo and Coinbase both showed strong interest in the category, and their session offered a useful perspective on where things may go next. Giving every Link user the ability to hand an agent a virtual card is incredible distribution. Guardrails, controls, and management of agentic payments came up in almost every conversation. ## Stripe looks well positioned for the agentic economy Stripe's acquisition strategy is elite and has set them up well for this moment. Bridge gives them a leader in stablecoins. Privy gives them a premier digital wallet. Metronome connects directly to the rise of usage-based and AI-driven pricing models. These acquisitions feel thoughtful and aligned with Stripe's long-term strategy, not like short-term acquihires or products that later become afterthoughts. They strengthen the platform and help Stripe stay at the cutting edge of payments. We like to joke about corporate synergies, but Stripe is one of the few companies where they genuinely seem to show up. ## Stripe is shipping with startup speed Stripe's shipping velocity is impressive and still feels a lot like a startup. I think that will be particularly notable when they go public. The number of new products and features showcased, from Treasury to Projects CLI and more, made it clear that Stripe is well positioned to thrive in the AI era. They are not waiting to be disrupted. They are trying to build a company that stays durable for the next several decades. ## The data may have been the strongest signal Some of the strongest evidence came from the Stripe data itself. Stripe sits at a unique vantage point across global commerce, and the charts showed a clear AI-driven inflection since the start of the year. New company formation, payment volume, CLI usage, the growth tied to AI and agents does not look isolated to a small handful of companies. It looks broad, and it looks real. ## Builder demand is immediate Sessions focused on agentic commerce and payments were full. Demand from builders is real and immediate, especially around how to operationalize payments and infrastructure for autonomous systems. That matters because it suggests this is moving from narrative to implementation. Builders are not just curious about the idea. They are actively looking for the tools and systems that let them ship. ## The brand still matters Stripe's brand continues to be a differentiator. Despite its scale, it still feels deliberate and distinct through things like Stripe Press, the Cheeky Pint pub with mini Guinness pours, and the overall tone of the event. The design and production value on the keynotes was great. I will make one exception for the archival footage quick hits. They do need a bigger venue. The show floor, keynotes, sessions, and lunch were all packed, a bit too packed. ## In summary Agentic everything is coming, including payments and commerce. Stripe is going to play a key role in that future. It may be worth thinking about the company less as a payments incumbent and more as a frontier lab for what payments become next. --- ## Related reading - [MPP Session Payments](https://conto.finance/blog/mpp-session-payments) - [Paying for APIs with x402](https://conto.finance/blog/x402-paying-for-apis) - [Enterprise Agentic Payments](https://conto.finance/blog/enterprise-agentic-payments) - [Sign Up for Conto](https://conto.finance) --- An agent with a wallet and no policies is an open checkbook. It can spend any amount, to any address, at any time. That's fine for a hackathon demo. It's not fine for production. Securing an agent that handles real money requires defense in depth: multiple independent controls that each catch a different class of risk. We recommend five layers. ## Layer 1: Spending Limits The most fundamental control. Set how much an agent can spend per transaction, per day, per week, and per month. This catches the obvious failure modes: a runaway loop that drains a wallet, a prompt injection that tricks an agent into overspending, or a misconfigured amount. Even if every other control fails, spending limits cap the blast radius. A reasonable starting point for most agents: - Per-transaction: $100 - Daily: $500 - Monthly: $5,000 These are conservative recommendations for new agents. Note that Conto's system defaults for auto-created wallets are higher (daily: $1,000, weekly: $5,000, monthly: $20,000) — you should tighten them based on the agent's actual needs, not its theoretical maximum. ## Layer 2: Counterparty Controls Spending limits control how much. Counterparty controls determine who. An allowlist restricts the agent to a known set of addresses: verified vendors, internal wallets, trusted API providers. A blocklist catches known bad actors. Both can be combined. For high-security deployments, start with an allowlist-only approach. The agent can only transact with addresses you've explicitly approved. That eliminates the class of attacks where the agent is tricked into sending money to an attacker-controlled address. ## Layer 3: Time Windows Not every agent should be able to spend money at 3 AM on a Saturday. Time window policies restrict when payments can happen: business hours only, weekdays only, or custom schedules. This matters most for agents that interact with external services. If the agent shouldn't be making procurement decisions outside of working hours, enforce it at the policy level instead of relying on the agent's own judgment. ## Layer 4: Micropayment Controls Agents increasingly pay for APIs using protocols like [x402](https://conto.finance/docs/guides/x402-api-payments) and [MPP](https://conto.finance/docs/guides/mpp-session-payments). These are small, high-frequency payments (often fractions of a dollar) that add up quickly. Micropayment-specific policies let you cap per-request amounts, set per-service daily limits, restrict which services the agent can pay for, and limit session deposits. Without these, an agent could rack up hundreds of dollars in API fees before anyone notices. ## Layer 5: Alerts and Monitoring Policies prevent bad transactions. Alerts tell you when something unusual is happening, even if it's technically within limits. Set up alerts for denied payments, high-value transactions, unusual spending patterns, and new counterparty interactions. The point is to give humans visibility into agent financial behavior in real time, not to auto-block. ## Evaluation Order Conto evaluates policies in a specific order: wallet-level limits first, then agent-specific policies. The first denial wins. If any rule at any level blocks the payment, it stops. You can set conservative defaults and then selectively loosen them for specific agents. A procurement agent might get a higher per-transaction limit than a monitoring agent, while both inherit the same counterparty blocklist. ## Start Strict, Loosen Gradually The safest approach is to deploy with tight controls and relax them as you build confidence. It's easier to increase a spending limit after watching the agent's behavior than to recover from overly permissive defaults. The full configuration guide with code examples for every layer is in the docs: [Securing Agents with Policies](https://conto.finance/docs/guides/securing-agents). For quick setup commands, see [Recipes](https://conto.finance/docs/guides/recipes). ### Related - [How to Test Agent Payments Without Losing Real Money](https://conto.finance/blog/testing-agent-payments) - validate your policies on Tempo Testnet - [x402: How Agents Pay for APIs with HTTP](https://conto.finance/blog/x402-paying-for-apis) - deep dive on micropayment controls - [MPP: Session-Based Payments for Agents on Tempo](https://conto.finance/blog/mpp-session-payments) - session deposit and budget controls --- Need help designing a policy strategy for your agents? [Get in touch](mailto:support@conto.finance) or [start building](https://conto.finance). --- Nous Research's Hermes agents can execute payments autonomously. That unlocks a lot, but it also opens the door to real financial risk if there's nothing standing between the agent and the wallet. We're excited to announce our Hermes integration. It's a Conto skill that evaluates every outgoing payment against your spending policies before a single token leaves the wallet. If you're running Hermes agents, you can now enforce per-transaction caps, rolling budgets, counterparty allowlists, human approval thresholds, and 40+ other rule types — all through a single skill install. We're opening up the full policy suite to early adopters at no cost while we collect feedback. [Join our Discord](https://discord.gg/h7rYrpkrRt) if you want to try it out or have questions. ## Why This Matters Autonomous payment ability is table stakes for useful agents. But autonomy without constraints is how wallets get drained — a misconfigured API call, an unexpected loop, a bad recipient address. The usual fix is custom validation logic bolted onto each agent, which tends to be brittle, incomplete, and hard to audit. Conto centralizes that enforcement. You define the rules once, and every payment your Hermes agent attempts gets checked against them before execution. ## The Flow Every payment attempt passes through Conto before any funds move: 1. You configure spending policies in the Conto dashboard 2. Your Hermes agent initiates a payment 3. The skill sends the payment details to Conto's approval endpoint 4. Conto evaluates the request against every active policy 5. The response is `APPROVED`, `DENIED`, or `REQUIRES_APPROVAL` 6. The agent acts accordingly ``` POST /api/sdk/payments/approve ``` A single call covers all your rules — transaction limits, daily caps, counterparty checks, time windows, everything. If the payment doesn't clear, the agent gets back the specific violations so it can report why. ## Installation Hermes supports well-known skill discovery, so setup is one command: ```bash hermes skills install well-known:https://conto.finance/.well-known/skills/conto --force ``` This pulls down the skill manifest and a `conto-check.sh` helper script into `~/.hermes/skills/conto/`. Hermes currently flags networked finance skills during install, so `--force` is needed after you review the scan output. Then add your SDK key to `~/.hermes/.env`: ```bash CONTO_SDK_KEY=conto_agent_your_key_here CONTO_API_URL=https://conto.finance ``` You can generate keys from the [Conto dashboard](https://conto.finance) under **Agents > SDK Keys > Generate New Key**. Standard keys handle payment evaluation and transaction visibility. Admin keys also allow policy creation and wallet management. ## Policy Types Over 40 rule types are available across several categories: - **Human Approval.** Require manual sign-off for payments above a configurable threshold. - **Spend Limits.** Per-transaction maximums, plus daily, weekly, and monthly rolling caps. Budget allocations for specific use cases. - **Category Controls.** Restrict payments by category — allow only `API_PROVIDER` and `INFRASTRUCTURE`, block `TRAVEL` and `MARKETING`, or any combination across 14 supported categories. - **Counterparty Management.** Maintain allowlists of approved recipient addresses or blocklists of known-bad ones. - **Scheduling.** Limit payments to business hours, specific days of the week, or block them entirely during maintenance windows. - **x402 API Controls.** Set price ceilings per x402 call, cap daily spend per service, or block specific x402 endpoints entirely. You can create policies through structured JSON or plain language: ``` /conto create a policy that limits each transaction to 200 pathUSD ``` ## Wallet Modes The integration supports two custody models: **Provider-managed (Sponge or Privy):** A single API call handles policy evaluation and payment execution together. The wallet provider holds the keys, and Conto orchestrates the full flow. This is the simplest setup if you don't need direct key custody. **External wallet:** Your agent holds its own keys. Conto evaluates the payment and returns an approval. Your agent then executes the transfer independently and confirms back with the transaction hash: ``` POST /api/sdk/payments/{approvalId}/confirm ``` Approval tokens are cryptographically bound to the original request parameters — amount, recipient, and chain — and expire after 10 minutes. They can't be replayed for a different payment. ## Chains Base, Tempo, and Solana are all supported, along with their respective stablecoins. ## Get Started 1. Sign up at [conto.finance](https://conto.finance) 2. Install the Conto skill: ```bash hermes skills install well-known:https://conto.finance/.well-known/skills/conto --force ``` 3. Connect your Hermes agent in the dashboard 4. Generate an SDK key 5. Add the config to `~/.hermes/.env` 6. Create your first policy ## Resources - [Hermes SDK Reference](https://conto.finance/docs/sdk/skills) — full API docs for the Hermes integration - [Conto Dashboard](https://conto.finance) — manage agents, policies, and SDK keys - [Skill Manifest](https://conto.finance/.well-known/skills/conto) — well-known endpoint for skill discovery - [Policy Guide](https://conto.finance/docs/policies) — deep dive into all 40+ rule types - [Discord Community](https://discord.gg/h7rYrpkrRt) — feedback, questions, and support - [OpenClaw Integration](https://conto.finance/docs/sdk/skills) — if you're also building on OpenClaw --- Your agents can move money. Conto makes sure they do it on your terms. --- We've shipped a lot of internal, partner, as well as customer-facing work across Conto this month! Here's what's now live across the product, the public site, and our developer surfaces including an exciting new product - [Enchant](https://askenchant.com) ## A refreshed Conto brand across the site and product Conto's branding got an overhaul on both the public site and inside the product. Goodbye vibe-code purple. We rolled the new brand system across marketing and dashboard surfaces and introduced a new, modernized logo. ## Enchant beta is live We launched [Enchant in beta](https://askenchant.com), a consumer product built on top of Conto's spend management platform. Enchant is a simpler way to use top APIs and AI models through micropayments. Rather than committing to a big subscription or wiring up payment flows by hand, you can pay for services in small increments through agentic payments (x402 and MPP). Access top APIs like Fal, Suno, Browserbase, Parallel, Exa, and more without needing to deal with the complexity of setting up wallets and agents. It also shows Conto in action. The same payment infrastructure that powers internal spend controls and operator workflows can just as easily power a direct end-user experience. Try it today at [askenchant.com](https://askenchant.com). New users get 3 free prompts, a $0.25 credit for creating an account, and referral credits on top of that. ## Stripe Sessions and the agentic payments community We hosted a happy hour during Stripe Sessions and spent time with our earliest supporters, fellow founders, and operators building in agentic payments and commerce. It was great to meet influential builders and leaders in person and have in-depth conversations on the future of the space. Stripe Sessions was a good reminder of how much energy is going into making agent-driven payments and commerce real. Check out our recap [here](https://www.conto.finance/blog/field-notes-from-stripe-sessions). ## Better policy, trust, and identity tools inside the product Operators now get more context when deciding how agents and counterparties should be allowed to spend. We added trust score explainability for counterparties: weighted score breakdowns, the signals pushing a score up or down, recommended next actions, and the next milestone needed to improve trust. There's also a richer Policy Template Library, so teams can start from use-case-driven templates instead of building every control from scratch. Agent identity is much more explicit now too. Identity fields flow through more of the app and SDK, and the dashboard has a dedicated identity surface, review workflows, and bulk remediation tools so teams can clean up ownership and identity issues without grinding through records one at a time. We also tightened the surrounding operator flows, including organization switching, upgrade paths, and team management controls. ## Smoother wallet, billing, and payment operations Wallet workflows are now more practical for teams operating across multiple custody models and chains. Conto supports attaching existing Privy-backed wallets, registering external wallets more directly, and handling balances more consistently across external wallets and Tempo. Conto Pay, our hosted agentic payments solution, also got more dependable. We hardened the payment flow and expanded the chat-driven controls so teams can fund wallets, inspect payments, and manage policies right from the assistant. On billing, teams get better plan controls and more consistent handling of Enterprise limits across the dashboard and enforcement flows. ## Better developer onboarding and public docs Conto is easier to discover and integrate from the outside. The new public [Build](https://conto.finance/build) hub pulls together the SDK, MCP, CLI, OpenAPI, `llms.txt`, and skills in one place. We also published machine-readable discovery surfaces, including `/.well-known/agent.json` and a stable skills manifest, so agents and developer tooling have a clearer starting point. We expanded the docs too: a Conto Hybrid Integration guide, clearer wallet custody guidance, better customer-facing SDK docs, and a more explicit explanation of when to use organization API keys versus agent SDK keys. The thread through all of it: make Conto easier to understand, evaluate, and integrate. --- Not every payment is a one-shot transaction. When an agent streams data from an API, processes a batch of requests, or interacts with a service over an extended period, paying per-request creates unnecessary overhead. Each payment needs an onchain transaction, each transaction costs gas, and the total friction scales linearly with usage. MPP (Machine Payment Protocol) solves this with sessions. An agent opens a session with a deposit, makes as many requests as needed, and settles once when the session closes. One onchain transaction to open, one to close. Everything in between is offchain. ## How MPP Sessions Work The lifecycle has four steps: 1. **Open** - Agent deposits funds into a session with the service provider 2. **Use** - Agent makes requests, each one debited from the session balance 3. **Close** - Either party closes the session 4. **Settle** - The actual amount consumed is settled onchain; unused deposit is returned This is different from x402, where each request is a separate payment. MPP amortizes the cost across an entire session, which makes it better suited for high-frequency interactions and streaming use cases. ## x402 vs MPP Both protocols enable machine-to-machine payments, but they optimize for different patterns: | | x402 | MPP | |---|---|---| | Payment model | Per-request | Per-session | | Onchain transactions | One per request | Two (open + close) | | Best for | Infrequent, varied APIs | High-frequency, streaming | | Chain | Base, Ethereum | Tempo | | Settlement | Immediate | On session close | An agent that makes one data lookup per hour is a good fit for x402. An agent that streams real-time market data for 8 hours is a good fit for MPP. ## Why Sessions Need Controls Sessions introduce a different risk surface. The deposit amount determines the maximum a session can cost. Without controls, an agent could open sessions with large deposits across multiple services, tying up significant capital. Conto's MPP policy rules address this: - **Session budget** - cap the maximum deposit per session - **Per-request ceiling** - limit how much any single request within a session can cost - **Concurrent session limits** - restrict how many sessions an agent can have open simultaneously - **Session duration limits** - force sessions to close after a maximum time - **Service allowlist** - restrict which services the agent can open sessions with These are evaluated during pre-authorization, before the session deposit is made. ## Running MPP Through Conto The flow mirrors x402 but with session awareness: ```bash # 1. Pre-authorize the session curl -X POST https://conto.finance/api/sdk/mpp/pre-authorize \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 10.00, "recipientAddress": "0xServiceAddress", "resourceUrl": "https://api.service.com/stream", "serviceDomain": "api.service.com", "intent": "session", "depositAmount": 10.00 }' ``` If authorized, the agent opens the session, uses the service, and when it closes, records the settlement back to Conto: ```bash # 2. Record the settled amount (not the deposit) curl -X POST https://conto.finance/api/sdk/mpp/record \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 3.50, "recipientAddress": "0xServiceAddress", "transactionHash": "0xsettlement123...", "sessionId": "mpp_session_xyz", "scheme": "mpp" }' ``` Note that you record the settled amount ($3.50 in this example), not the deposit ($10.00). This keeps spend tracking accurate: the agent's daily total reflects actual consumption, not reserved capital. ## Building for Tempo MPP runs on Tempo, a payments-focused blockchain designed for high-frequency, low-value settlement. Session deposits and settlements use Tempo stablecoins: `USDC.e` on Tempo mainnet and `pathUSD` for testnet/demo flows. The chain's low fees make the two-transaction session model practical even for small amounts. The full implementation guide with TypeScript examples and policy configuration is in the docs: [MPP Session Payments](https://conto.finance/docs/guides/mpp-session-payments). Quick-reference commands are on the [Recipes](https://conto.finance/docs/guides/recipes) page. ### Related - [x402: How Agents Pay for APIs with HTTP](https://conto.finance/blog/x402-paying-for-apis) - the per-request alternative for infrequent API calls - [Five Layers of Security for Agents That Spend Money](https://conto.finance/blog/five-layers-agent-security) - where session controls fit in a layered policy strategy --- Exploring session-based payments for your agents? [Start building with Conto](https://conto.finance) or reach out at [support@conto.finance](mailto:support@conto.finance). --- Your agent can make payments. That's the easy part. The hard part is making sure it _should_. Today we're launching our OpenClaw integration, a skill that adds policy enforcement to every payment your AI agent makes. If you're building on OpenClaw, you can now drop in Conto and get per-transaction limits, daily budgets, category restrictions, approval workflows, and 40+ other rule types with quick setup. For a limited time we're offering unlimited access to the full suite of Conto policies to beta testers. We'd love your feedback. [Join our Discord community](https://discord.gg/h7rYrpkrRt) to drop us a note. ## The Problem OpenClaw gives agents the ability to execute payments. That's powerful, but also dangerous. Without guardrails, an agent can drain a wallet on a bad API call, pay a blacklisted address, or blow through a monthly budget in an afternoon. Most teams end up hand-rolling ad-hoc checks that don't scale and miss edge cases. Giving agents the ability to pay requires a lot of trust. Conto helps you add controls to get you there. ## How It Works Conto intercepts every payment attempt before execution and evaluates it against your configured policies: 1. User sets payment policies 2. Agent initiates a payment 3. The Conto skill calls our approval endpoint 4. We evaluate against all active policies 5. We return `APPROVED`, `DENIED`, or `REQUIRES_APPROVAL` 6. The agent proceeds (or doesn't) Most OpenClaw agents use the external wallet flow, where the agent holds its own keys: ``` POST /api/sdk/payments/approve (policy check) POST /api/sdk/payments/{id}/confirm (report tx hash) ``` If you use a Conto-managed wallet (Privy or Sponge), a single call to `/api/sdk/payments/request` handles both the policy check and execution. Every policy evaluated. No payment goes through without passing your rules. ## Setup ### Getting Started Install the Conto skill from [ClawHub](https://clawhub.ai/kwattana/conto): ```bash npx clawhub install conto ``` You can inspect the raw skill manifest at [conto.finance/skill.md](https://conto.finance/skill.md), but use ClawHub for installation so the helper script is installed with the skill. ### Configuration Add your SDK key to `~/.openclaw/openclaw.json`: ```json { "skills": { "entries": { "conto": { "env": { "CONTO_SDK_KEY": "conto_agent_your_key_here", "CONTO_API_URL": "https://conto.finance" } } } } } ``` Generate keys from the [dashboard](https://conto.finance) under **Agents > SDK Keys > Generate New Key**. Standard keys cover payment evaluation and visibility. Admin keys add policy creation and wallet administration. ## What You Can Enforce We support 40+ rule types across several categories: - **Approval Workflows.** Require human sign-off above a spending threshold. - **Spend Controls.** Per-transaction caps, daily/weekly/monthly limits, budget allocations. - **Category Management.** Whitelist or blacklist specific API providers and payment categories. - **Counterparty Rules.** Block suspicious addresses, allowlist approved vendors. - **Time-Based Restrictions.** Business hours only, weekday-only, maintenance blackout windows. - **API Cost Controls.** Cap per-request costs and limit daily spend per service. Policies can be created via structured input or natural language: ``` /conto create a policy that limits each transaction to 200 pathUSD ``` ## Two Wallet Modes **Integrated (Sponge or Privy):** One API call handles both the policy check and payment execution. Your wallet provider holds the keys (Privy or Sponge, respectively) while Conto orchestrates policy evaluation and execution through the provider. Simplest path if you don't need to hold your own keys. **External wallet:** Your agent holds the keys. Conto approves the payment, your agent executes the transfer, then confirms back with the transaction hash: ``` POST /api/sdk/payments/{REQUEST_ID}/confirm ``` This gives you full custody while still enforcing every policy. ## Chain Support The integration works across Base, Tempo, and Solana with support for their respective stablecoins. ## Get Started 1. Sign up at [conto.finance](https://conto.finance) 2. Install the skill from [ClawHub](https://clawhub.ai/kwattana/conto): ```bash npx clawhub install conto ``` You can inspect the raw manifest at [conto.finance/skill.md](https://conto.finance/skill.md); use ClawHub for installation so the helper script is installed too. 3. Connect your agent in the dashboard 4. Link your wallet to the agent 5. Generate an SDK key 6. Add the config to your OpenClaw setup 7. Create your first policy Full SDK reference: [conto.finance/docs/sdk/skills](https://conto.finance/docs/sdk/skills) ### Related - [Adding Spending Policies to Any OpenClaw Agent](https://conto.finance/blog/openclaw-spending-policies) - deeper dive on the policy flow and external wallet mode - [Zero to First Agent Payment in 5 Minutes](https://conto.finance/blog/zero-to-first-payment) - the general Conto setup walkthrough - [Five Layers of Security for Agents That Spend Money](https://conto.finance/blog/five-layers-agent-security) - design a complete policy strategy - [How to Test Agent Payments Without Losing Real Money](https://conto.finance/blog/testing-agent-payments) - validate policies on Tempo Testnet --- Your agents can pay. Now make sure they pay correctly. --- [OpenClaw](https://github.com/openclaw/openclaw) gives agents the ability to act. Conto gives organizations control over how those agents spend money. The Conto skill for OpenClaw connects both: it hooks into the payment flow and evaluates every transaction against 40+ policy rule types before a dollar moves onchain. ## The Problem With Uncontrolled Agent Wallets When you give an OpenClaw agent a wallet, it can pay anyone, any amount, at any time. For personal projects and hackathons, this is fine. For anything with real stakes (a company deploying agents, a team managing budgets, a product handling user funds) it's a serious gap. The common workaround is to limit the wallet balance. Give the agent $50 and let it spend freely. But that doesn't distinguish between a legitimate $50 vendor payment and a $50 payment to a malicious address. It doesn't enforce business hours. It doesn't require approval for high-value transactions. It's a balance cap, not a policy engine. ## How the Conto Skill Works The skill sits between the agent's intent to pay and the actual onchain transfer: ``` Agent decides to pay → Skill calls Conto → Policies evaluated → Pay or deny ``` When the agent wants to send money, the skill calls Conto's payment request endpoint. Conto evaluates every policy assigned to the agent. If all rules pass, the payment proceeds. If any rule fails, the payment is blocked and the agent receives the specific violations. The agent doesn't need to know about the policies. It tries to pay. The control layer handles the rest. ## Setting It Up Four steps: 1. **Connect your agent in Conto** - create an agent record and assign policies 2. **Link your wallet** - register your wallet address so Conto can track spend limits 3. **Generate an SDK key** - Standard for payment-only, Admin if you want the agent to manage its own policies 4. **Add to OpenClaw config** - set the SDK key and API URL in `openclaw.json` Once configured, the agent can interact with policies through natural language: ``` /conto create a policy that limits each transaction to 200 pathUSD /conto list my policies Send 50 pathUSD to 0x742d... on Tempo ``` The last command triggers the full flow: the skill calls Conto, policies are evaluated, the agent transfers onchain, and the skill confirms the transaction back to Conto for tracking. ## What You Can Control The skill supports all of Conto's policy types: - **Spending limits** - per-transaction, daily, weekly, monthly caps - **Counterparty controls** - allowlists and blocklists for recipient addresses - **Time restrictions** - business hours, allowed days, blackout windows - **Category controls** - allow or block specific payment categories - **Approval thresholds** - require human sign-off above a certain amount - **Velocity limits** - rate-limit transaction frequency - **x402 and MPP controls** - govern micropayment spending Policies can be created through the Conto dashboard, the API, or through the OpenClaw agent itself (with an Admin SDK key). They're evaluated independently, and the first denial wins. ## The External Wallet Flow OpenClaw agents typically hold their own keys, so they use Conto's external wallet flow: 1. **Approve** - skill calls Conto to check policies 2. **Transfer** - agent sends the payment onchain using its own keys 3. **Confirm** - skill reports the transaction hash back to Conto Conto never needs access to the agent's private keys. It only provides the policy decision. The agent keeps full custody of its wallet while getting spending controls. ## Dashboard Visibility Every payment, approved or denied, shows up in the Conto dashboard. Confirmed transactions include explorer links and full audit trails. Denied attempts appear in the alerts view with the specific policy violations that blocked them. For organizations running multiple OpenClaw agents, this is a single view of all agent financial activity: which agents are spending, how much, to whom, and whether any are hitting policy limits. The full setup guide with an end-to-end example is in the docs: [Agent Skills](https://conto.finance/docs/sdk/skills). Install from [ClawHub](https://clawhub.ai/kwattana/conto) with `npx clawhub install conto`; the raw manifest is available at [conto.finance/skill.md](https://conto.finance/skill.md) for inspection. For quick policy setup commands, check the [Recipes](https://conto.finance/docs/guides/recipes) page. ### Related - [Zero to First Agent Payment in 5 Minutes](https://conto.finance/blog/zero-to-first-payment) - the general Conto setup walkthrough - [Five Layers of Security for Agents That Spend Money](https://conto.finance/blog/five-layers-agent-security) - design a complete policy strategy - [How to Test Agent Payments Without Losing Real Money](https://conto.finance/blog/testing-agent-payments) - validate policies on Tempo Testnet --- Running OpenClaw agents that handle money? [Add spending controls with Conto](https://conto.finance) or reach out at [support@conto.finance](mailto:support@conto.finance). --- If your first test of an agent's spending controls happens in production, you've already lost. Agentic payments need the same testing rigor as any other production system, arguably more since the failure mode is real money leaving real wallets. Conto supports full testing on Tempo Testnet with free pathUSD tokens. Every policy type, every rule evaluation, every approval flow works identically to mainnet. The only difference is that no real value moves. ## Five Scenarios You Should Test Before any agent goes live, run these five scenarios. Each one validates a different part of the policy engine: **1. Approved payment** - A payment within all limits. Confirms the basic flow works end to end. **2. Denied by spending limit** - A payment that exceeds a per-transaction or daily cap. Validates that the agent stops when it should. **3. Requires human approval** - A payment above the approval threshold. Validates the pause-and-wait flow for high-value transactions. **4. Blocked counterparty** - A payment to an address not on the allowlist (or on a blocklist). Validates counterparty controls. **5. Time window restriction** - A payment attempted outside business hours. Validates temporal controls. If all five pass, your policy configuration is enforcing correctly. If any fail unexpectedly, you've found a misconfiguration before it matters. ## The Testing Pattern Each test follows the same structure: 1. Set up a policy targeting the scenario 2. Attempt a payment that should trigger the policy 3. Verify the response matches expectations (approved, denied, or requires_approval) 4. Check the dashboard for the correct audit trail The request endpoint is the same one used in production: ```bash curl -X POST https://conto.finance/api/sdk/payments/request \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 10, "recipientAddress": "0x...", "purpose": "Test payment" }' ``` The response tells you what happened and why. Denied payments include a `violations` array with every rule that failed, so you know which policy blocked the transaction and what the threshold was. ## From Test to Production Moving from testnet to production is a configuration change, not a code change. Swap the wallet from Tempo Testnet to your production chain, review your policies one more time, and deploy. The full testing guide with all five scenarios, policy setup commands, and a production migration checklist is in the docs: [Testing Payments Safely](https://conto.finance/docs/guides/testing-payments). Quick-reference curl commands are on the [Recipes](https://conto.finance/docs/guides/recipes) page. ### Related - [Zero to First Agent Payment in 5 Minutes](https://conto.finance/blog/zero-to-first-payment) - set up Conto and make your first payment - [Five Layers of Security for Agents That Spend Money](https://conto.finance/blog/five-layers-agent-security) - design a production policy stack --- Ready to test your agent's payment controls? [Get started on Tempo Testnet](https://conto.finance) or reach out at [support@conto.finance](mailto:support@conto.finance). --- The question I get most is: when will agentic payments become real? It's the billion-dollar question. If I knew exactly when and how it would happen, Conto would have the ten-figure valuation to match. That said, I do have a view on how it plays out. Everyone wants to get right to the space-age vision: consumers booking flights through agents, AI employees coordinating supply chains, agents managing budgets and procurement with no one in the loop. That future is coming, but adoption happens in phases. We're in the middle of a massive infrastructure buildout for agentic payments. From protocols to platforms, the foundation of the agentic economy is being built by startups and industry giants like Stripe, Shopify, Coinbase, and Visa. The real breakthroughs come when builders move from abstract theses to shipped, applied products. Here's my timeline for agentic payments: - **Stage 1: Micropayments between agents and services** - today - **Stage 2: Local commerce and SMBs** - 1 year - **Stage 3: Enterprise payments and agentic commerce** - 2-3 years ## Stage One: Micropayments Lead the Way The first wave is already here, and it starts with agents paying for digital services. This is where protocols like x402 and MPP (Machine Payment Protocol) come in, enabling micropayments on stablecoin rails (and traditional card rails too in some cases). The next 6 to 12 months belong to this stage, as companies find new ways to monetize their services and attract agents. An agent can pay fractions of a cent for an API request, unlock premium data on demand, pay per inference or per second of compute, and stream payments continuously as services are consumed. Machine payments in their natural habitat. Leading AI companies like Exa, Parallel, Browserbase, and Fal have opened their APIs to agents via x402 and MPP, and are actively making their services easier for agents to consume. Micropayments are the hook that gets developers to explore agentic payments and bring the learnings back to their companies. We're even seeing consumer products emerge like Enchant that abstract away the x402/MPP plumbing entirely, letting people access the best models and services through micropayments. Don't get fixated on payment volume. What's more important to take away from the rise of micropayments agents is the behavioral shift and new products that emerge. Agents are now capable of spending money. Things will only get more interesting. ## Stage Two: Agents Enter the Real World The next stage moves beyond APIs and into local commerce, where agents start coordinating real-world services on behalf of users: ordering delivery, booking local services, restocking supplies from nearby merchants, and handling recurring errands. Merchants begin accepting machine-originated payments directly through protocols like MPP. This is roughly a year out, though much of the groundwork is already being set. Local businesses may seem counterintuitive to be early adopters of agentic payments, but I believe that they will be open to any form of added revenue and orders. Agents are the channel and if merchants can easily add ways to become discoverable and accept payments at little cost, they'll adopt it. Some of the least tech savvy businesses are now becoming the most AI-pilled. On the consumer side, people are doing more and more with their personal and coding agents. The ability to order lunch, supplies, or groceries right from the chat is convenient. Agents are already browsing the web, writing production code, and solving some of the most complex math and science problems. So why aren't they paying? Nimble small and mid-sized businesses will also build agentic payments into their own apps and ecosystems. The more AI-forward a company is, the sooner it realizes that letting agents pay is the logical next step. Stopping for a human to approve every payment breaks the whole premise of autonomy. AI-native startups will lead the way here. ChatGPT and Claude have made users expect intelligence and context with every interaction. Companies need to deliver this and payments are no exception. Successful agentic payment and commerce implementations at this stage won't be too crazy. They'll still resemble familiar usage patterns and behaviors. But they'll be running on agents instead of automations. ## Stage Three: Enterprise Adoption Changes the Scale The long-term opportunity for agentic payments is in the enterprise. We'll see the first enterprise pilots this year, and widespread adoption in the next two to three. A few industry leaders move first, and the rest follow fast. Pressure from Wall Street to become AI-ready and automate across the organization is a major tailwind. Most enterprise payment workflows still rely on human processes around approvals, invoices, procurement, reimbursements, vendor management, and compliance checks. They're slow because the financial systems underneath them were designed for people, paper, and PDFs. Agentic workflows are already transforming businesses and payments will be no different. Agents operating inside enterprises will need the ability to move money autonomously to pay vendors, execute transactions, move funds, and more. Eventually entire workflows become autonomous. An autonomous business might source suppliers, purchase inventory, negotiate pricing, manage treasury, coordinate fulfillment, pay contractors, run marketing campaigns, and rebalance spending dynamically, all without constant human orchestration. This is where the infrastructure requirements get serious. Enterprises won't allow agentic payments without programmable policies, spend limits, identity controls, auditability, compliance, approval frameworks, and real-time observability. You might ask "why isn't this just a cron job or an automation?". That's just a stepping stone to autonomous agents. Why have a dumb process when you can have something that acts with intelligence and understands the full context of your business at any point in time? You might not be thinking about it, but your competitor definitely is. The vision of agentic commerce will have matured by this stage. All the work that the big retailers and eCommerce players have been putting in around discoverability and agent experience will pay off. The businesses that adapt earliest will become the preferred vendors for autonomous buyers. Consumers will be more comfortable using agents to shop on their favorite sites. Some of the best agentic commerce experiences will be ones that are not labeled "agentic commerce". They'll be so seamlessly built into the product experience that the user won't know what's happening behind the scenes. People debate whether anyone will actually shop through an agent. But ChatGPT and Claude have already shown how fast AI products can reshape consumer behavior. As agents weave deeper into daily life, and as a generation grows up with them, transacting through an agent will feel more and more natural. ## The Agentic Economy Is Just Getting Started Many write off agentic payments as a niche experiment. Overhyped. Too soon. Chasing a problem. That misses the bigger picture. Agents are reasoning, acting, and spending and they're on the path to being fully autonomous. Models will keep improving and the demand for agents that can transact in a trusted way will only increase. The early stages may be unclear, but they're the first building blocks of the agentic economy. What's built today is setting the stage for a future where millions (trillions) of agents are transacting with each other and with services, merchants, people, and businesses. Agentic payments is inevitable. --- Here's what shipped at Conto this week. We've updated the AI assistant (name pending, any suggestions?), platform hardening, and admin tooling, with some docs cleanup on the side. ## Unlocking the assistant The assistant got a lot of attention this week. You can now set and manage policies directly in the chat. This is in addition to querying alerts and agent status with natural language. ## Security and reliability We shipped a batch of changes aimed at authentication paths, approval flows, and audit log integrity. On the reliability side, we continued with enterprise-readiness work to support critical workflows. ## Admin and operator tooling A few practical wins for the people running Conto day-to-day: - Better filtering on the audit log - UX fixes across onboarding, transactions, and policy screens - Machine spend analytics, so you can see where agent dollars are actually going The spend analytics view is worth a look if you've been flying blind on agent usage. ## Docs and developer experience We refreshed the public docs site, and expanded the growth and hardening guides. --- ## Related reading - [Five Layers of Agent Security](https://conto.finance/blog/five-layers-agent-security) - [Enterprise Agentic Payments](https://conto.finance/blog/enterprise-agentic-payments) - [OpenClaw Spending Policies](https://conto.finance/blog/openclaw-spending-policies) - [Zero to First Payment](https://conto.finance/blog/zero-to-first-payment) - [Sign Up for Conto](https://conto.finance) - [Join the Discord](https://discord.gg/h7rYrpkrRt) --- Here's what shipped at Conto last week. We focused a lot on Conto Pay, our new agentic payments solution for companies that want to ship agent-driven payment flows without building the whole stack themselves. The agentic payments landscape is vast and rapidly growing and we've been hearing a lot from teams that find it challenging to navigate. How do you pick the right providers from a market map of 100s of different vendors in a market that is changing every day? We're working to make that easier. ## Conto Pay as a hosted payments solution Conto Pay gives teams a single place to fund wallets, run payments, and keep agent activity under control, without standing up wallets, stablecoin rails, payment workflows, and operational tooling on their own. This week's updates push it further in that direction. ## More of the payment workflow now happens in chat Conto Pay now supports a broader set of payment actions directly from its dedicated chat surface. Teams can refresh and fund wallets, inspect payments, cancel or retry payment actions, and manage payment controls from inside Conto Pay chat. The full payment workflow lives in one place, with fewer reasons to drop out of the flow to handle routine operational steps somewhere else. ## A more complete hosted experience The Conto Pay experience now supports a fuller payment console workflow, so teams using Conto Pay as their hosted payments layer get a more capable, consistent surface for managing wallets, payments, and controls in one place. If you want to capitalize on agentic payments, there's a lot of complexity around the infrastructure needed to get there. Conto Pay is built to handle that end to end so your team can focus on your product. Our goal is to bridge the gap between agentic payments as an interesting idea and what it actually looks like in reality. ## Broader stablecoin coverage We expanded USDT support across the chains Conto already supports. For teams using Conto to coordinate agent payment flows, that means more flexibility in how they fund wallets and move money, and a wider set of stablecoin options to work with out of the box. --- ## Related reading - [Enterprise Agentic Payments](https://conto.finance/blog/enterprise-agentic-payments) - [Agentic Payments Wild West](https://conto.finance/blog/agentic-payments-wild-west) - [Zero to First Payment](https://conto.finance/blog/zero-to-first-payment) - [Sign Up for Conto](https://conto.finance) - [Join the Discord](https://discord.gg/h7rYrpkrRt) --- The HTTP 402 status code ("Payment Required") has existed since 1997. It was reserved for future use. Nearly three decades later, it finally has a real implementation. The [x402 protocol](https://conto.finance/docs/sdk/x402-payments) gives 402 actual payment semantics. When an agent calls a paid API and gets a 402 response, the body includes payment requirements: how much, to whom, on which chain. The agent pays, retries the request with a payment header, and gets the data. No API keys, no subscriptions, no invoices. Just HTTP and money. ## The Flow An x402 interaction has three steps: 1. **Agent calls API** - gets a 402 with payment requirements 2. **Agent pays** - sends USDC onchain to the facilitator address 3. **Agent retries** - includes the payment signature, gets the response For the agent, it's one extra round trip. For the API provider, every request is paid for at the time of use. ## Why This Needs Controls The simplicity of x402 is also its risk. An agent that can pay for any API, at any price, with no limits, is a cost management problem waiting to happen. Consider an agent that queries a paid data API in a loop. Each request costs $0.05. Harmless in isolation. At 1,000 requests per hour, that's $50/hour, or $1,200/day. Without controls, nobody notices until the monthly bill arrives. Conto's x402 policy rules address this directly: - **Per-request ceiling** - cap the maximum any single x402 payment can cost - **Per-service daily limit** - cap total spending on a specific API domain - **Service allowlist** - restrict which APIs the agent can pay for at all - **Velocity limits** - rate-limit how many paid requests an agent can make per hour These rules are evaluated during the pre-authorization step, before any money moves. ## Pre-Authorize, Pay, Record When running x402 payments through Conto, the agent adds a pre-authorization step before paying: ```bash # 1. Pre-authorize against policies curl -X POST https://conto.finance/api/sdk/x402/pre-authorize \ -H "Authorization: Bearer $CONTO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 0.05, "recipientAddress": "0xFacilitator", "resourceUrl": "https://api.example.com/data", "serviceDomain": "api.example.com" }' ``` If authorized, the agent proceeds with the payment. After the onchain transaction completes, it records the payment back to Conto for tracking and spend accounting. This three-step flow (pre-authorize, pay, record) means every x402 payment is policy-checked, onchain verified, and fully auditable. ## The Bigger Picture x402 is one of the first payment protocols built for machine-to-machine commerce. It removes the friction of API key management and subscription billing, replacing it with pay-per-use at the protocol level. But protocol-level payments without controls create new risks. Conto adds the governance layer: visibility and spending limits over agents' x402 usage, just like you'd govern traditional payments. The full implementation guide with TypeScript examples and policy configuration is in the docs: [Paying for APIs with x402](https://conto.finance/docs/guides/x402-api-payments). Quick-reference commands are on the [Recipes](https://conto.finance/docs/guides/recipes) page. ### Related - [MPP: Session-Based Payments for Agents on Tempo](https://conto.finance/blog/mpp-session-payments) - the session-based alternative for high-frequency use cases - [Five Layers of Security for Agents That Spend Money](https://conto.finance/blog/five-layers-agent-security) - where x402 controls fit in a layered policy strategy --- Want to add x402 controls to your agents? [Start building with Conto](https://conto.finance) or reach out at [support@conto.finance](mailto:support@conto.finance). --- Getting an agent to make its first onchain payment shouldn't take a weekend. With Conto, it's four steps: create a wallet, connect your agent, generate an SDK key, and pay. For the full copy-paste setup walkthrough, see the [Quickstart](https://conto.finance/docs/quickstart/setup) quickstart. ## The Setup Every agent payment in Conto flows through three components: 1. **Wallet** - where the money lives. Your wallet provider holds the keys (Sponge, Privy, or your own for external wallets). 2. **Agent** - the identity making decisions, connected in the Conto dashboard 3. **SDK Key** - scoped credentials the agent uses to talk to Conto You create each through the dashboard or via the API. The wallet gets provisioned onchain (Base, Tempo, or Solana), linked to the agent with delegation limits, and the agent gets an SDK key with the appropriate scopes. Once configured, your agent can verify its setup with a single call: ```bash curl https://conto.finance/api/sdk/setup \ -H "Authorization: Bearer $CONTO_API_KEY" ``` If the response shows an active agent, linked wallets, and assigned policies, you're ready to pay. ## The Payment Flow Conto uses a two-step payment model: **request** then **execute**. The request step evaluates policies. Every rule assigned to the agent (spending limits, counterparty restrictions, time windows, approval thresholds) is checked before the payment is approved. If anything fails, the payment is denied with the specific violations listed. The execute step sends money onchain. For integrated wallets (Privy or Sponge), Conto orchestrates the transfer through the wallet provider. For external wallets, the agent transfers itself and confirms back. Separating these steps means you can test whether a payment would be allowed without moving money. The policy engine always sits between intent and execution. ## Why This Matters Most agent frameworks skip financial controls entirely. They give the agent a wallet, maybe a card, and hope for the best. That works for demos. It falls apart when you're running dozens of agents in production with real budgets. The first payment is the starting point. Once the pattern is established (request, evaluate, execute) you can layer on spending limits, counterparty allowlists, time restrictions, and approval workflows without changing how the agent interacts with Conto. The full step-by-step setup guide is in the docs: [Quickstart](https://conto.finance/docs/quickstart/setup). For quick copy-paste snippets, check the [Recipes](https://conto.finance/docs/guides/recipes) page. ### Related - [How to Test Agent Payments Without Losing Real Money](https://conto.finance/blog/testing-agent-payments) - validate policies on Tempo Testnet before going live - [Five Layers of Security for Agents That Spend Money](https://conto.finance/blog/five-layers-agent-security) - design a complete policy strategy --- Building with agents that spend money? [Get started with Conto](https://conto.finance) or reach out at [support@conto.finance](mailto:support@conto.finance). --- ## API Reference (auto-generated from OpenAPI spec) ### Authentication User registration and authentication - `POST /api/auth/register` — Register a new account Create a new user account and organization, then send an email verification link. Privileged API credentials are not issued until the account is verified. ### Agent Onboarding Agent-forward signup flows, including anonymous test-mode sandboxes and organization-token self-registration - `GET /api/agents/sandbox` — Describe anonymous agent sandbox signup Returns machine-readable defaults for creating an anonymous Conto test-mode sandbox without a human email verification step. Returned credentials expire after 7 days. - `POST /api/agents/sandbox` — Create an anonymous agent sandbox Stripe-style agent onboarding: creates a test-mode organization, owner placeholder, agent, external testnet wallet, SDK key, and sandbox read-only organization API key. No human intervention is required. Returned keys are shown once and expire after 7 days. Sandbox payments execute in simulated mode: request then execute returns status COMPLETED with simulated true and a placeholder txHash receipt. - `POST /api/agents/sandbox/claim` — Claim an anonymous sandbox Attaches an anonymous sandbox to the signed-in human account. Use the sandbox read-only organization API key returned by POST /api/agents/sandbox as the claim secret. - `GET /api/agents/register` — Describe organization-token agent registration Returns public metadata for org-scoped agent self-registration. With a token query parameter, validates the registration token and returns available agent capacity. - `POST /api/agents/register` — Register an agent into an existing organization Lets an agent join an existing organization using a human-generated registration token. This path issues a least-privilege SDK key scoped to payments:request. ### Agents AI agent management - `GET /api/agents` — List all agents Retrieve all agents for the current organization. - `POST /api/agents` — Create a new agent Create an AI agent that can be linked to wallets and policies for controlled payments. Requests made with org API keys should include `ownerMembershipId`; browser-session requests can default to the current member. - `POST /api/agents/remediation` — Run bulk identity remediation for agents Assign owners or backfill safe identity fields like missing agent IDs and purposes based on existing descriptions. - `GET /api/agents/{id}` — Get agent by ID Get full agent details including linked wallets, policies, and transaction counts. - `PATCH /api/agents/{id}` — Update agent - `DELETE /api/agents/{id}` — Delete agent - `GET /api/agents/{id}/wallets` — List wallets linked to agent - `POST /api/agents/{id}/wallets` — Link wallet to agent Link a wallet to an agent with delegation type, spend limits, and time window controls. - `PATCH /api/agents/{id}/wallets/{walletId}` — Update agent-wallet link Update spend limits, delegation type, or time window for an agent-wallet link. - `DELETE /api/agents/{id}/wallets/{walletId}` — Unlink wallet from agent - `GET /api/agents/{id}/policies` — List policies assigned to agent - `POST /api/agents/{id}/policies` — Assign policy to agent - `DELETE /api/agents/{id}/policies` — Unassign policy from agent Uses query parameter: DELETE /api/agents/{id}/policies?policyId={policyId} - `GET /api/agents/{id}/sdk-keys` — List SDK keys for agent - `POST /api/agents/{id}/sdk-keys` — Generate SDK key for agent Generate a new SDK API key for the agent. The full key is returned only once. Request body supports `name`, optional `expiresInDays`, and optional `keyType`. Standard keys cover the payment lifecycle (request, execute, approve, confirm) plus read scopes; admin keys add delegated organization-management scopes for agents, wallets, and policies. - `POST /api/agents/{id}/freeze` — Freeze an agent Immediately suspend an agent and block all transactions. Optionally freeze associated wallets. Creates a FreezeEvent audit record. - `GET /api/agents/{id}/freeze` — Get freeze status and configuration Returns the agent freeze status, behavioral counters, stored freeze config, and the effective config (stored merged with defaults). - `POST /api/agents/{id}/unfreeze` — Unfreeze an agent Restore a frozen agent to ACTIVE status. Optionally unfreeze associated wallets and reset behavioral counters. - `PATCH /api/agents/{id}/freeze-config` — Update freeze configuration Update auto-freeze thresholds for an agent. Omitted fields keep their current values. Thresholds define when automatic freezing triggers fire. - `GET /api/agents/{id}/freeze-history` — Get agent freeze event history Paginated list of freeze and unfreeze events for this agent. ### Wallets Wallet management, provisioning, and funding - `GET /api/wallets` — List all wallets List all wallets for the organization with linked agents and policies. - `POST /api/wallets` — Create a new wallet Create a new wallet. By default creates a PRIVY-custodied EOA wallet on EVM. You can also attach an existing Privy-backed wallet by providing custodyType=PRIVY with externalWalletId and address, or register a self-custodied wallet with custodyType=EXTERNAL and address/importAddress. Requests are idempotent per externalWalletId + chainId or address + chainId within the organization. - `GET /api/wallets/{id}` — Get wallet by ID - `PATCH /api/wallets/{id}` — Update wallet - `POST /api/wallets/{id}/provision` — Provision wallet onchain Provision a Sponge-custodied wallet: links to the platform Sponge account, syncs a real blockchain address and balance, and marks the wallet ready for SDK-initiated payments. No request body required. ### Policies Spending policy configuration and rules - `GET /api/policies` — List all policies List all policies for the organization with their rules and assignments. - `POST /api/policies` — Create a new policy Create a policy with optional inline rules and agent assignments. When `rules` and/or `agentIds` are provided, everything is created in a single atomic transaction — if any step fails, nothing is created. You can also create a policy shell first and add rules separately via POST /api/policies/{id}/rules. - `GET /api/policies/{id}` — Get policy by ID - `PATCH /api/policies/{id}` — Update policy - `DELETE /api/policies/{id}` — Delete policy Permanently delete a policy and remove it from all agents. Consider deactivating (PATCH with isActive: false) instead if you want to preserve the policy configuration. - `GET /api/policies/{id}/rules` — List rules for a policy - `POST /api/policies/{id}/rules` — Add rules to a policy Add one or more rules to a policy. Rules are evaluated using AND logic — all must pass for a payment to be approved. ### Transactions Transaction history and management - `GET /api/transactions` — List transactions List payment transactions for the organization. Filter by status, agent, or amount. Transaction statuses: PENDING, APPROVED, DENIED, CONFIRMED, FAILED. ### SDK Payments SDK endpoints for agent payment flow (request, execute, status) - `POST /api/sdk/payments/request` — Request payment authorization Request authorization for a payment from an AI agent. Evaluates spend governance first, then optionally performs an AgentScore identity gate before settlement. Returns APPROVED, DENIED, REQUIRES_APPROVAL, or VERIFICATION_REQUIRED. - `GET /api/sdk/payments/{requestId}` — Get payment request status Check the status of a payment request. - `POST /api/sdk/payments/{requestId}/execute` — Execute approved payment Execute a previously approved payment request. The request must have status APPROVED and not be expired. Executes the onchain transaction via Sponge wallet. - `POST /api/sdk/payments/approve` — Approve an external wallet payment Request policy approval for a payment the agent will execute via its own external wallet. Returns an approval token to use when confirming. Requires `payments:approve` scope. - `POST /api/sdk/payments/{requestId}/confirm` — Confirm external wallet payment execution Confirm that an externally approved payment was executed by providing the transaction hash and approval token. Requires `payments:confirm` scope. ### SDK Agent SDK endpoints for agent self-service - `GET /api/sdk/all` — Get complete agent data Returns everything about the authenticated agent in a single call: profile, wallets, policies, counterparties, transactions, alerts, analytics, and capabilities. Use the `include` query parameter to cherry-pick specific sections. - `GET /api/sdk/agents/me` — Get agent profile Get the authenticated agent profile and summary statistics. - `GET /api/sdk/setup` — Get agent bootstrap configuration Returns comprehensive agent configuration including profile, wallets, policies, counterparties, scopes, available endpoints, and capabilities. Designed for initial SDK bootstrap. ### SDK Wallets SDK endpoints for agent wallet access - `GET /api/sdk/wallets` — List agent wallets List all wallets assigned to the authenticated agent. - `GET /api/sdk/wallets/{id}` — Get wallet details ### SDK Transactions SDK endpoints for agent transaction history - `GET /api/sdk/transactions` — List agent transactions - `GET /api/sdk/transactions/{id}` — Get transaction details - `POST /api/sdk/transactions/{id}/retry` — Retry a failed transaction Queue a failed transaction for retry. Only transactions with FAILED status can be retried. Requires `transactions:write` scope. ### SDK Policies SDK endpoints for agent policy inspection - `GET /api/sdk/policies` — List agent policies List policies that govern the authenticated agent, with effective limits. - `GET /api/sdk/policies/exceptions` — List policy exception requests List policy exception requests submitted by this agent. Requires `policies:exceptions` scope. - `POST /api/sdk/policies/exceptions` — Request a policy exception Submit a request for a policy exception (e.g., whitelist a counterparty, increase spend limit). Requires `policies:exceptions` scope. ### Counterparties Counterparty management and trust - `GET /api/counterparties` — List counterparties List counterparties (payment recipients) with their trust levels and transaction history. Trust levels: TRUSTED, VERIFIED, UNKNOWN, BLOCKED. - `POST /api/counterparties` — Create a counterparty ### API Keys Organization API key management - `GET /api/api-keys` — List organization API keys - `POST /api/api-keys` — Create organization API key Create an org-level API key with scoped permissions. The full key is returned only once. Keys always expire: `expiresInDays` defaults to 365 and is capped at 365. ### Alerts Alert management - `GET /api/alerts` — List alerts List alerts and notifications for the organization. Alert types include: SPEND_LIMIT_WARNING, SPEND_LIMIT_EXCEEDED, UNUSUAL_ACTIVITY, FAILED_TRANSACTION, POLICY_VIOLATION, NEW_COUNTERPARTY, HIGH_VALUE_TRANSACTION, AGENT_SUSPENDED, WALLET_LOW_BALANCE, BLOCKED_ADDRESS. Severities: INFO, WARNING, CRITICAL. ### x402 x402 protocol pre-authorization, recording, and analytics - `POST /api/sdk/x402/pre-authorize` — Pre-authorize an x402 payment Check policy approval before signing an x402 payment. - `POST /api/sdk/x402/record` — Record x402 payment(s) Record a single x402 payment or a batch of micropayments. - `GET /api/sdk/x402/services` — List x402 services used by agent - `GET /api/sdk/x402/budget` — Check x402 budget remaining Get x402 budget remaining, burn rate, and projections. ### mpp Machine Payment Protocol pre-authorization, recording, and analytics - `POST /api/sdk/mpp/pre-authorize` — Pre-authorize an MPP payment Check policy approval before creating an MPP credential. The agent sends the WWW-Authenticate: Payment challenge contents and Conto evaluates policies without executing anything. - `POST /api/sdk/mpp/record` — Record MPP payment(s) Record a single MPP payment or a batch of micropayments. Used by agents that handle MPP payments directly and want to report them to Conto for spend tracking and policy enforcement. - `GET /api/sdk/mpp/services` — List MPP services used by agent List all MPP services the agent has interacted with, including spend summaries, price trends, and known endpoints. - `GET /api/sdk/mpp/budget` — Check MPP budget remaining Get MPP budget remaining, burn rate, and projections. Includes daily/weekly/monthly spend, policy limits, and hours until budget exhaustion. ### SDK A2A Payments Agent-to-agent payment requests and resolution - `POST /api/sdk/a2a/request` — Create an A2A payment request Request payment from another Conto agent. The requesting agent is asking the target agent to send them funds. Target can be specified by agent ID or wallet address. - `GET /api/sdk/a2a/requests` — List A2A payment requests List payment requests for the authenticated agent. Filter by direction (incoming/outgoing) and status. - `GET /api/sdk/a2a/requests/{id}` — Get A2A payment request details Get details of a specific A2A payment request, including direction and status. - `POST /api/sdk/a2a/requests/{id}/execute` — Execute an approved A2A payment request Execute a previously approved A2A payment request. The request must be in an approved state. - `GET /api/sdk/a2a/resolve` — Resolve a wallet address to a Conto agent Check if a wallet address belongs to a registered Conto agent. Useful for verifying recipients before sending A2A payment requests. - `GET /api/sdk/a2a/stats` — Get A2A payment statistics Get aggregate A2A payment statistics for the authenticated agent. ### SDK Cards Card payment approval and confirmation (BYOC flow) - `POST /api/sdk/cards/approve` — Request card payment approval Request policy approval before charging a card (BYOC flow step 1). Evaluates per-transaction limits, daily/weekly/monthly limits, time windows, and merchant restrictions. Requires `payments:approve` scope. - `POST /api/sdk/cards/{id}/confirm` — Confirm card payment execution Confirm that a card payment was charged externally (BYOC flow step 2). Requires the approval token from the approve step. Requires `payments:confirm` scope. ### SDK Counterparties SDK endpoints for counterparty and network trust management - `GET /api/sdk/counterparties` — List agent counterparties List counterparties the agent has interacted with, including trust levels and transaction history. Requires `counterparties:read` scope. - `POST /api/sdk/counterparties` — Create a counterparty Register a new counterparty (payment recipient). Requires `counterparties:write` scope. - `GET /api/sdk/counterparties/{id}` — Get counterparty details Get detailed counterparty info including trust relationship and recent transactions. Requires `counterparties:read` scope. - `PATCH /api/sdk/counterparties/{id}` — Update a counterparty Update counterparty details. Requires `counterparties:write` scope. - `GET /api/sdk/network/trust/{address}` — Get network trust for an address Look up trust information for any wallet address on the Conto network. Returns entity type, trust scores, relationship history, and any flags. Requires `network:read` scope. ### SDK Alerts & Analytics SDK endpoints for alerts, analytics, audit logs, approval requests, spending limits, and rate limits - `GET /api/sdk/alerts` — List agent alerts List alerts for the authenticated agent. Requires `alerts:read` scope. Filter by status and severity. - `GET /api/sdk/alerts/{id}` — Get alert details Get details of a specific alert. Requires `alerts:read` scope. - `PATCH /api/sdk/alerts/{id}` — Acknowledge or resolve an alert Update an alert status by acknowledging or resolving it. Requires `alerts:write` scope. - `GET /api/sdk/analytics` — Get spending analytics Get spending analytics for the authenticated agent including volume trends, category breakdowns, and top merchants. Requires `analytics:read` scope. - `GET /api/sdk/audit-logs` — List audit logs Get audit logs of actions performed by or affecting this agent. Requires `audit:read` scope. - `GET /api/sdk/approval-requests` — List pending approval requests List pending approval requests for the agent, including payments awaiting human approval and incoming A2A payment requests. - `GET /api/sdk/spending-limits` — Get spending limits and usage Get per-wallet spending limits and current usage for the authenticated agent. Requires `wallets:read` scope. - `GET /api/sdk/rate-limits` — Get rate limit status Get current rate limit status, usage counts, and per-endpoint rate limits for the authenticated agent. ### Merchant Gates Hosted merchant acceptance gates plus SDK CRUD for configuring AgentScore-gated purchase endpoints - `GET /api/sdk/merchant-gates` — List merchant gates List hosted merchant acceptance gates configured for the authenticated agent organization. - `POST /api/sdk/merchant-gates` — Create a merchant gate Create a conto-hosted AgentScore merchant acceptance gate for the authenticated organization. - `GET /api/sdk/merchant-gates/{id}` — Get merchant gate details - `PATCH /api/sdk/merchant-gates/{id}` — Update a merchant gate - `DELETE /api/sdk/merchant-gates/{id}` — Delete a merchant gate - `POST /api/merchant/{gateId}/purchase` — Purchase through a hosted merchant gate Run AgentScore compliance plus Conto spend governance, then settle the payment into the merchant settlement wallet. ### Other - `GET /api/health` — Health check Check API health status. ### Safety - `GET /api/freeze-events` — List organization-wide freeze events Paginated list of all freeze and unfreeze events across all agents in the organization. ## Key Concepts Summary ### Registration - Agent sandbox: POST /api/agents/sandbox — Creates a test-mode organization, agent, external testnet wallet, SDK key, and sandbox API key without human email verification. Returned keys are shown once and expire after 7 days. - Agent sandbox quickstart: https://conto.finance/docs/quickstart/agent-sandbox — Copy-paste discovery, signup, setup, approval, confirmation, and human claim flow for autonomous agents. - Existing organization: POST /api/agents/register — Registers an agent with a human-generated organization registration token and returns a least-privilege SDK key. - Human account: POST /api/auth/register — Creates a user and organization, then requires email verification before privileged credentials are issued. ### Authentication - SDK Keys: `conto_agent_xxx...` - For agent payment operations (per-agent, generated via POST /api/agents/{id}/sdk-keys) - API Keys: `conto_xxx...` - For full platform API access (org-level, generated via POST /api/api-keys) ### Agent Types OPENAI_ASSISTANT, ANTHROPIC_CLAUDE, LANGCHAIN, AUTOGPT, CUSTOM Field name: `agentType` (not `type`) ### SDK Scopes Standard SDK keys: `payments:request`, `payments:execute`, `payments:approve`, `payments:confirm`, `wallets:read`, `policies:read`, `transactions:read`, `counterparties:read`, `alerts:read`, `agents:read`, `analytics:read`, `network:read` Admin SDK keys add opt-in organization-management scopes such as `agents:write`, `wallets:write`, and `policies:write`. Organization-token agent self-registration is more restrictive and only issues `payments:request`. ### Payment Flow 1. Agent calls `payments.request()` with amount, recipient, purpose 2. Conto evaluates all policies (spend limits, time windows, counterparty rules) 3. Returns APPROVED, DENIED, or REQUIRES_APPROVAL 4. If approved, agent calls `payments.execute()` with requestId 5. Transaction is submitted to blockchain and confirmed 6. Alternative: Use `autoExecute: true` in step 1 to request + execute in one call (returns status: "EXECUTED" with txHash) ### Wallet Selection Wallets are selected by custody priority: PRIVY > SPONGE > SMART_CONTRACT > EXTERNAL. Executable wallets (PRIVY, SPONGE) are preferred. Response includes `walletSelectionReason` and `currency`/`chain` info. ### Custody Providers - PRIVY (Default): Enterprise-grade key management with policy controls - SPONGE: Fast setup with gas sponsorship for stablecoins - EXTERNAL: Externally managed wallet (import address required) - SMART_CONTRACT: Onchain enforcement (coming soon) ### Wallet Lifecycle 1. Create wallet via POST /api/wallets (default: PRIVY custody, EOA, EVM) 2. Provision wallet via POST /api/wallets/{id}/provision (gets blockchain address) 3. Link wallet to agent via POST /api/agents/{agentId}/wallets (set spend limits) 4. Agent can now request and execute payments ### Policy Types & Rule Types Policies are created via `POST /api/policies` then rules added via `POST /api/policies/{id}/rules`. Each rule has: `ruleType`, `operator`, `value` (JSON string), `action` (ALLOW/DENY/REQUIRE_APPROVAL). - SPEND_LIMIT: Rules: `MAX_AMOUNT`, `DAILY_LIMIT`, `WEEKLY_LIMIT`, `MONTHLY_LIMIT`, `BUDGET_CAP` - TIME_WINDOW: Rules: `TIME_WINDOW` (BETWEEN operator, HH:MM format), `DAY_OF_WEEK` (IN_LIST), `BLACKOUT_PERIOD`, `DATE_RANGE` - COUNTERPARTY: Rules: `ALLOWED_COUNTERPARTIES` (IN_LIST, ALLOW), `BLOCKED_COUNTERPARTIES` (IN_LIST, DENY), `TRUST_SCORE`, `COUNTERPARTY_STATUS` - CATEGORY: Rules: `ALLOWED_CATEGORIES` (IN_LIST, ALLOW), `BLOCKED_CATEGORIES` (IN_LIST, DENY) - VELOCITY: Rules: `VELOCITY_LIMIT` (value: `{"maxCount": N, "period": "HOUR"}` or `{"maxAmount": N, "period": "DAILY"}`) - GEOGRAPHIC: Rules: `GEOGRAPHIC_RESTRICTION` (IN_LIST, DENY) - APPROVAL_THRESHOLD: Rules: `REQUIRE_APPROVAL_ABOVE` (GREATER_THAN, REQUIRE_APPROVAL) - CONTRACT/DeFi: Rules: `CONTRACT_ALLOWLIST`, `PROTOCOL_ALLOWLIST` ### Multi-Policy AND Logic All assigned policies must pass. First DENY stops evaluation immediately. DELETE policy from agent: `DELETE /api/agents/{id}/policies?policyId=xxx` (query param, not path param) ### AgentWallet-Level Limits Spend limits also exist at wallet level: `spendLimitPerTx`, `spendLimitDaily`, `spendLimitWeekly`, `spendLimitMonthly` (null = unlimited). Set via `POST /api/agents/{id}/wallets` or `PATCH /api/agents/{id}/wallets/{walletId}`. Agent wallet endpoints support both session auth and org API key auth. ### Operators Numeric: EQUALS/EQ, NOT_EQUALS/NEQ, GREATER_THAN/GT, GREATER_THAN_OR_EQUAL/GTE, LESS_THAN/LT, LESS_THAN_OR_EQUAL/LTE List: IN/IN_LIST, NOT_IN/NOT_IN_LIST Range: BETWEEN, NOT_BETWEEN ### Violation Types INSUFFICIENT_BALANCE, PER_TX_LIMIT, DAILY_LIMIT, WEEKLY_LIMIT, MONTHLY_LIMIT, TIME_WINDOW, BLOCKED_COUNTERPARTY, WHITELIST_VIOLATION, CATEGORY_RESTRICTION, VELOCITY_LIMIT, GEOGRAPHIC_RESTRICTION, BUDGET_EXCEEDED, EXPIRED_PERMISSION, CONTRACT_NOT_ALLOWED, BLACKOUT_PERIOD ### Trust Levels - TRUSTED (0.75-1.0): High confidence, minimal restrictions - VERIFIED (0.5-0.75): Established relationship - UNKNOWN (0.2-0.5): Limited history, requires scrutiny - BLOCKED (0.0-0.2): High risk, transactions blocked ## Quick Code Examples ### Initialize SDK ```typescript import { Conto } from '@conto_finance/sdk'; const conto = new Conto({ apiKey: process.env.CONTO_API_KEY }); ``` ### Make a Payment ```typescript const result = await conto.payments.pay({ amount: 50.00, recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...', recipientName: 'OpenAI', purpose: 'API credits', category: 'AI_SERVICES' }); console.log('TX Hash:', result.txHash); ``` ### Single-Call Payment (autoExecute) ```typescript const result = await fetch('/api/sdk/payments/request', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 50, recipientAddress: '0x...', purpose: 'API credits', autoExecute: true }) }).then(r => r.json()); // result.status === 'EXECUTED', result.execution.txHash, result.currency, result.chain ``` ### Bootstrap Agent (GET /api/sdk/setup) ```typescript const config = await fetch('/api/sdk/setup', { headers: { 'Authorization': `Bearer ${apiKey}` } }).then(r => r.json()); // config.agent, config.wallets, config.policies, config.counterparties, config.scopes, config.capabilities ``` ### Create Counterparty (POST /api/sdk/counterparties) ```typescript // Requires scope: counterparties:write await fetch('/api/sdk/counterparties', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Vendor', address: '0x...', type: 'VENDOR', category: 'AI_SERVICES' }) }).then(r => r.json()); ``` ### Request Policy Exception (POST /api/sdk/policies/exceptions) ```typescript // Requires scope: policies:exceptions await fetch('/api/sdk/policies/exceptions', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ type: 'ADD_TO_WHITELIST', reason: 'Need to pay new vendor', details: { counterpartyAddress: '0x...' } }) }).then(r => r.json()); ``` ### Two-Step Payment (Request then Execute) ```typescript // Step 1: Request authorization const request = await conto.payments.request({ amount: 100, recipientAddress: '0x...', purpose: 'Infrastructure costs' }); // Step 2: Execute if approved if (request.status === 'APPROVED') { const result = await conto.payments.execute(request.requestId); } ``` ### Create Wallet via API ```bash curl -X POST https://conto.finance/api/wallets \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Operations Wallet", "custodyType": "SPONGE", "chainType": "EVM", "chainId": "42431" }' ``` ## Support - Dashboard: https://conto.finance - Documentation: https://conto.finance/docs - Email: support@conto.finance