<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CAI</title>
    <description>The latest articles on DEV Community by CAI (@cailab).</description>
    <link>https://dev.to/cailab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4008187%2F53ebe87b-4371-40f5-972c-f98143974a5f.png</url>
      <title>DEV Community: CAI</title>
      <link>https://dev.to/cailab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cailab"/>
    <language>en</language>
    <item>
      <title>Payment mandates for SaaS: how AI agents pay recurring bills without asking permission every time</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Fri, 06 Nov 2026 06:21:08 +0000</pubDate>
      <link>https://dev.to/cailab/placeholder-58df</link>
      <guid>https://dev.to/cailab/placeholder-58df</guid>
      <description>&lt;h1&gt;
  
  
  Payment mandates for SaaS: how AI agents pay recurring bills without asking permission every time
&lt;/h1&gt;

&lt;p&gt;You run a SaaS that charges API usage in USDC. An AI agent calls your endpoint every hour. The first payment goes through fine. The second time, the agent asks the human "can I pay $0.03 for another 1000 tokens?" and the human has to click approve. Day two, same question. Day three, the user stops responding and your SaaS stops getting paid.&lt;/p&gt;

&lt;p&gt;This is the problem CAI payment mandates solve. One setup. No per-charge confirmations. The agent pays within the limits you define and the user sets.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a payment mandate changes the flow
&lt;/h2&gt;

&lt;p&gt;Without a mandate, every agent payment is a two-step conversation. The x402 prepare shows &lt;code&gt;requires_user_confirm: true&lt;/code&gt;, the agent asks the human, the human says yes, x402 execute goes through with &lt;code&gt;user_confirmed: true&lt;/code&gt;. That works for one-off purchases. It breaks for recurring SaaS billing.&lt;/p&gt;

&lt;p&gt;With a mandate, the user creates a payment mandate once at cai.com/app or through the API. They set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The merchant domain (your SaaS host)&lt;/li&gt;
&lt;li&gt;A daily cap in USD (say $200/day)&lt;/li&gt;
&lt;li&gt;A max per-payment limit (say $20 per charge)&lt;/li&gt;
&lt;li&gt;An expiry time (say 30 days)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After the user approves it through a hosted verification page, the mandate status becomes &lt;code&gt;active&lt;/code&gt;. From that point, the agent calls x402 payment prepare, the platform sees an active mandate covering the merchant domain and amount, and &lt;code&gt;requires_user_confirm&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt;. The agent calls x402 payment execute with &lt;code&gt;user_confirmed: false&lt;/code&gt;, and the payment goes through. No human in the loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API calls end to end
&lt;/h2&gt;

&lt;p&gt;Step one. The user creates the mandate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST https://api.cai.com/functions/v1/payment-mandate-create
Content-Type: application/json
Authorization: Bearer ***
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The body defines the guardrails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"merchant_domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api.your-saas.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"daily_cap_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_amount_per_payment_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_resource_patterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/v1/chat/completions"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_in_hours"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step two. The user approves the mandate through the hosted verification page. The agent polls &lt;code&gt;GET /payment-mandate-status&lt;/code&gt; to confirm the status is &lt;code&gt;active&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Step three. When the SaaS sends an x402 challenge, the agent calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /x402-payment-prepare
Content-Type: application/json
Authorization: Bearer ***

{
  "resource_url": "https://api.your-saas.com/v1/chat/completions",
  "merchant_domain": "api.your-saas.com",
  "recipient_address": "0xYourSaaSAddress",
  "amount": "5",
  "chain": "ETH",
  "token": "USDC"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response skips the confirm step. &lt;code&gt;requires_user_confirm&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt; because the active mandate covers this merchant, domain, and amount.&lt;/p&gt;

&lt;p&gt;Step four. The agent executes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /x402-payment-execute
Content-Type: application/json
Authorization: Bearer ***

{
  "attempt_id": "the_attempt_id_from_prepare",
  "user_confirmed": false
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The custodial transfer goes through. The SaaS gets paid. No one had to click anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the mandate protects
&lt;/h2&gt;

&lt;p&gt;Two safety mechanisms stop runaway spending. The daily cap limits total spending per day across all payments on that mandate. If the agent hits the $200/day cap, x402 payment prepare returns &lt;code&gt;requires_user_confirm: true&lt;/code&gt; again, and the agent must ask the human. The max per-payment limit prevents a single large charge from draining the wallet.&lt;/p&gt;

&lt;p&gt;New recipients also trigger a confirmation. If the merchant domain changes or the recipient address is new, the mandate does not cover it and the human sees the payment details before approving.&lt;/p&gt;

&lt;p&gt;The mandate system is CAI-native, not a full W3C/AP2 credential implementation. The gap ID is GAP_PAYMENT_MANDATE_V1 and the status is partial live. For card or PSP checkout flows, use hosted actions instead of x402.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for SaaS products
&lt;/h2&gt;

&lt;p&gt;A SaaS that needs human approval on every microtransaction loses conversions. The user stops approving after the third notification. The agent stalls. Revenue drops. Payment mandates flip this. The human sets the guardrails once, the agent operates within them, and the SaaS gets paid reliably.&lt;/p&gt;

&lt;p&gt;The same mandate covers multiple SaaS products. A user running three AI agents can have one mandate per service, each with its own daily cap. The agents route through x402 without the user ever seeing a payment prompt until a mandate limit is reached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up your SaaS as a mandate merchant
&lt;/h2&gt;

&lt;p&gt;Your SaaS needs to implement the x402 challenge. When an agent calls your paid endpoint, return HTTP 402 with a JSON body containing the payment challenge fields: recipient_address, amount, chain, and token. The agent's x402 payment prepare parses this and routes through CAI.&lt;/p&gt;

&lt;p&gt;That is the entire server-side change. You do not need a merchant account, you do not need a payment processor redirect, and you do not need to handle chargebacks. The custodial transfer delivers USDC to your address on the same chain.&lt;/p&gt;

&lt;p&gt;The CAI skill at &lt;a href="https://cai.com/skill.md" rel="noopener noreferrer"&gt;https://cai.com/skill.md&lt;/a&gt; documents every endpoint and parameter. The capabilities page at &lt;a href="https://cai.com/capabilities.html" rel="noopener noreferrer"&gt;https://cai.com/capabilities.html&lt;/a&gt; shows the live, partial live, and planned status of every feature.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>payments</category>
    </item>
    <item>
      <title>A worked example with @cai.com: from signup to first hosted-action payment to a stored vault credential</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Wed, 04 Nov 2026 06:40:26 +0000</pubDate>
      <link>https://dev.to/cailab/a-worked-example-with-caicom-from-signup-to-first-hosted-action-payment-to-a-stored-vault-59g2</link>
      <guid>https://dev.to/cailab/a-worked-example-with-caicom-from-signup-to-first-hosted-action-payment-to-a-stored-vault-59g2</guid>
      <description>&lt;h1&gt;
  
  
  A worked example with &lt;a class="mentioned-user" href="https://dev.to/cai"&gt;@cai&lt;/a&gt;.com — from signup to first hosted-action payment to a stored vault credential
&lt;/h1&gt;

&lt;p&gt;A worked example, end to end. About six minutes from &lt;code&gt;cai.com/app&lt;/code&gt; to a working agent that has an &lt;code&gt;@cai.com&lt;/code&gt; email, a funded wallet, a stored vault credential, and an installed MCP server. This post walks through every step with the actual commands and the actual API calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Sign up
&lt;/h2&gt;

&lt;p&gt;Go to &lt;code&gt;cai.com/app&lt;/code&gt;. Enter your name, your existing email, paste the 6-digit code CAI sends, set a password. Done. About 2 minutes.&lt;/p&gt;

&lt;p&gt;What you have at the end: an &lt;code&gt;@cai.com&lt;/code&gt; email, an empty wallet, an empty vault, and an API key with the read scopes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Receive your first &lt;code&gt;@cai.com&lt;/code&gt; email
&lt;/h2&gt;

&lt;p&gt;Forward a test mail to your new address from your old email. It arrives in the CAI inbox. Send a reply to your old address from &lt;code&gt;@cai.com&lt;/code&gt; — through the dashboard's compose UI, or via the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/send-email &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ***"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "to": "you@youroldaddress.com",
    "subject": "Hello from @cai.com",
    "body": "Testing the new address."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The send goes through. The reply arrives in your old inbox. The &lt;code&gt;@cai.com&lt;/code&gt; address is live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Top up the wallet
&lt;/h2&gt;

&lt;p&gt;Open the account dashboard, click "Add funds," pick a chain. Base is fastest for testing. Pick a token — USDC is the default. Then either send from an external wallet to the CAI custodial address on the chosen chain, or buy with MoonPay (fiat on-ramp, partial-live, third-party KYC and region limits apply).&lt;/p&gt;

&lt;p&gt;Your wallet has a $200/day auto-limit while CAI completes its security audit. New recipients and new devices always require confirmation on the hosted-action page. Think of it like cash in your pocket — perfect for daily spending. The vault product (multi-sig, time-locks) is coming for larger balances.&lt;/p&gt;

&lt;p&gt;After the deposit confirms, check the balance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/get-wallet-balances &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ***"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"chains": ["base"], "tokens": ["USDC"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response includes the new balance. About 2 minutes for the deposit to confirm on Base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Confirm a hosted-action payment
&lt;/h2&gt;

&lt;p&gt;Now the agent side. The agent (or you, via curl) initiates a transfer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/wallet-custodial-transfer &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ***"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "to_address": "0xYourOtherAddress",
    "amount": "1.00",
    "chain": "base",
    "token": "USDC"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response includes a hosted-action URL. Open the URL on your phone. The page shows the recipient, the amount, the chain. Tap "Confirm." The transfer executes.&lt;/p&gt;

&lt;p&gt;After the user confirms, the agent checks the activity feed for the receipt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET https://api.cai.com/functions/v1/wallet-activity-list &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ***"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response includes the completed transfer with its on-chain tx hash and status. The agent can then show the receipt to the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Store a site credential in the vault
&lt;/h2&gt;

&lt;p&gt;Open the account dashboard, click "Vault," add a credential for a site you use often. The form is &lt;code&gt;(site, username, password)&lt;/code&gt;. The credential is encrypted at rest.&lt;/p&gt;

&lt;p&gt;The agent can now list saved credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET https://api.cai.com/functions/v1/user-site-credentials &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ***"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response shows the metadata for each saved credential. The actual credential value is delivered through the user-confirmation hosted-action flow when the agent needs to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 — Install the MCP server (optional)
&lt;/h2&gt;

&lt;p&gt;The final step is the agent side. Install the MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @cailab/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the server to your MCP host (OpenClaw, Hermes, Codex, Cursor). The config is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cai"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cai-mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"CAI_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-api-key-from-the-dashboard"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the host. The CAI tools appear in the agent's tool surface. The agent can now call &lt;code&gt;get_identity&lt;/code&gt;, &lt;code&gt;get_wallet_balances&lt;/code&gt;, &lt;code&gt;wallet_custodial_transfer&lt;/code&gt;, &lt;code&gt;vault_get_site_credential&lt;/code&gt;, and the rest of the CAI surface — without you pasting a private key in chat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Total time
&lt;/h2&gt;

&lt;p&gt;Six minutes from signup to a working agent. About 2 minutes for the signup, 30 seconds for the test email, 2 minutes for the deposit, 30 seconds for the hosted-action test, 30 seconds for the vault credential, 30 seconds for the MCP install.&lt;/p&gt;

&lt;p&gt;Apply at &lt;code&gt;cai.com/app&lt;/code&gt;. The contract is &lt;code&gt;cai.com/skill.md&lt;/code&gt;. The npm package is &lt;code&gt;@cailab/mcp&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you ran the end-to-end walkthrough above and a step failed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Comment below with:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What you ran&lt;/strong&gt; — the install command, the request, the MCP host config. Copy the actual command or request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you expected&lt;/strong&gt; — one sentence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you got&lt;/strong&gt; — the error message, the empty response, the unexpected behavior. Paste it verbatim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your environment&lt;/strong&gt; — OS, Node version, the MCP host (OpenClaw / Hermes / Codex / Cursor / other), the CAI account tier if relevant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every comment on this article gets read. Bug reports will be replied to within 24 hours. Friction points shape what we document next.&lt;/p&gt;

&lt;p&gt;Documentation: &lt;code&gt;cai.com/skill.md&lt;/code&gt; · &lt;code&gt;cai.com/developers.html&lt;/code&gt; · &lt;code&gt;cai.com/app&lt;/code&gt; to sign up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Accepting agent payments on your API: the x402 seller's guide</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Fri, 30 Oct 2026 06:22:16 +0000</pubDate>
      <link>https://dev.to/cailab/accepting-agent-payments-on-your-api-the-x402-sellers-guide-p8g</link>
      <guid>https://dev.to/cailab/accepting-agent-payments-on-your-api-the-x402-sellers-guide-p8g</guid>
      <description>&lt;h1&gt;
  
  
  Accepting agent payments on your API: the x402 seller's guide
&lt;/h1&gt;

&lt;p&gt;You run an API that generates code reviews, transforms images, runs inference, or scrapes data. Your users are starting to call it from AI agents, not just browsers. And those agents have wallets. They can pay per call. But your payment form is a credit card field that no agent can fill.&lt;/p&gt;

&lt;p&gt;The HTTP 402 status code was designed for exactly this. Your API returns a payment challenge, and the calling agent's CAI wallet settles the transaction on the spot. No merchant account. No redirect. No chargebacks. The agent calls your endpoint, gets a price, pays, and retries with a proof of payment.&lt;/p&gt;

&lt;p&gt;This guide walks through the seller side of an x402 payment flow, grounded in the same API that CAI agents use today.&lt;/p&gt;

&lt;h2&gt;
  
  
  The flow in four steps
&lt;/h2&gt;

&lt;p&gt;From the seller's perspective, x402 is a request-response pattern with one extra round-trip:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The calling agent sends a request to your endpoint.&lt;/li&gt;
&lt;li&gt;Your API checks whether the caller has already paid. If not, return HTTP 402 with a payment challenge body.&lt;/li&gt;
&lt;li&gt;The calling agent parses the challenge, calls its wallet provider (in this case CAI), prepares and executes a payment, and retries the original request.&lt;/li&gt;
&lt;li&gt;Your endpoint receives the retry with a payment identifier, verifies the settlement, and serves the response.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What the 402 response looks like
&lt;/h2&gt;

&lt;p&gt;Your endpoint returns a standard HTTP 402 with a JSON body containing the payment details the agent needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;402&lt;/span&gt;
&lt;span class="na"&gt;content-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recipient_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0x1234..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5.00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"chain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USDC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resource_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.yoursite.com/transform-image"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;recipient_address&lt;/code&gt; is your CAI custodial wallet address on the chain you want to settle on. The &lt;code&gt;amount&lt;/code&gt; is in USDC. The &lt;code&gt;resource_url&lt;/code&gt; lets the agent map the payment to the specific resource it tried to access.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens on the paying agent's side
&lt;/h2&gt;

&lt;p&gt;An agent using CAI's MCP toolset processes the 402 challenge by calling two endpoints at the CAI API base URL (&lt;code&gt;https://api.cai.com/functions/v1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 -- Prepare the payment:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /x402-payment-prepare
{
  "resource_url": "https://api.yoursite.com/transform-image",
  "recipient_address": "0x1234...",
  "amount": "5.00",
  "chain": "base",
  "token": "USDC"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response returns an &lt;code&gt;attempt_id&lt;/code&gt; and a &lt;code&gt;requires_user_confirm&lt;/code&gt; flag. When this is the first time the agent pays your domain, the user sees a hosted confirmation page. This is the new-recipient confirmation at work: no payment goes out without the user's explicit approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 -- Execute the payment:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /x402-payment-execute
{
  "attempt_id": "att_abc123",
  "user_confirmed": true
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CAI initiates a custodial transfer from the user's wallet to your &lt;code&gt;recipient_address&lt;/code&gt; on the specified chain. The response includes a &lt;code&gt;tx_hash&lt;/code&gt; for on-chain settlement proof. The agent then retries the original API request with the payment identifier attached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 -- Verify the settlement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your endpoint receives the retry, looks up the &lt;code&gt;tx_hash&lt;/code&gt; against the chain, and serves the response once the payment clears. For your own record keeping, you can also call CAI's &lt;code&gt;POST /transfer-status&lt;/code&gt; endpoint with the &lt;code&gt;tx_hash&lt;/code&gt; to confirm the transfer is completed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recurring access with payment mandates
&lt;/h2&gt;

&lt;p&gt;Per-call confirmation works for occasional use, but many agent workloads run on a subscription model. A code-review agent that runs every hour should not need human approval for every $0.50 call. This is where CAI's payment mandate feature comes in.&lt;/p&gt;

&lt;p&gt;The user creates a mandate that grants the agent permission to pay your domain within defined limits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /payment-mandate-create
{
  "merchant_domain": "api.yoursite.com",
  "max_amount_per_payment_usd": "5.00",
  "daily_cap_usd": "200.00",
  "allowed_resource_patterns": ["/transform-image*", "/analyze-code*"]
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the user approves the mandate (through a hosted verification flow or the dashboard), the agent can pay your endpoint via x402 without asking for confirmation on each call. The CAI API checks the active mandate during &lt;code&gt;x402_payment_prepare&lt;/code&gt; and skips the user-confirm step when the payment falls within the limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guardrails built into the flow
&lt;/h2&gt;

&lt;p&gt;CAI applies three automatic protections on every x402 payment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A $200/day auto-limit&lt;/strong&gt; on agent-triggered spending. No single agent can drain more than this before the user is notified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New-recipient confirmation.&lt;/strong&gt; Every new &lt;code&gt;recipient_address&lt;/code&gt; or &lt;code&gt;merchant_domain&lt;/code&gt; triggers a hosted-action verification page the user sees and approves before any funds move.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full activity history.&lt;/strong&gt; Every payment appears in the user's wallet activity list and can be tracked by &lt;code&gt;tx_hash&lt;/code&gt; through &lt;code&gt;POST /transfer-status&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These protections apply whether the user confirmed the payment inline or pre-authorized it through a mandate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for your API
&lt;/h2&gt;

&lt;p&gt;Adding x402 as a payment path does not require replacing your existing billing. Your API can accept credit cards through Stripe, accept CAI deposits through &lt;code&gt;create_deposit_link&lt;/code&gt;, AND accept agent-triggered payments through the x402 flow above. The agent tries one path first, and if that fails, falls through to the next.&lt;/p&gt;

&lt;p&gt;The simple integration surface is a single 402 response and one verification callback. No redirect. No webhook to configure. No PCI scope. The calling agent handles the payment round-trip, and your endpoint just checks for settlement before serving the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The feedback loop
&lt;/h2&gt;

&lt;p&gt;Bug reports will be replied to within 24 hours. Every comment on this article gets read. If you hit a case where the x402 flow does not work as described, open a thread and we will walk through the trace together.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>payments</category>
    </item>
    <item>
      <title>Spending limits, payee confirmation, and payment mandates: how CAI keeps agent payments safe</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Wed, 21 Oct 2026 06:37:49 +0000</pubDate>
      <link>https://dev.to/cailab/spending-limits-payee-confirmation-and-payment-mandates-how-cai-keeps-agent-payments-safe-514n</link>
      <guid>https://dev.to/cailab/spending-limits-payee-confirmation-and-payment-mandates-how-cai-keeps-agent-payments-safe-514n</guid>
      <description>&lt;p&gt;Spending limits, payee confirmation, and the mandate model: how CAI keeps agent payments safe&lt;/p&gt;

&lt;p&gt;When an AI agent has access to your wallet, the question is who decides what the agent can spend and where. A wallet an agent can drain in one mistaken API call is a liability, not a product.&lt;/p&gt;

&lt;p&gt;CAI uses three layers of authorization: automatic spending limits, human-in-the-loop confirmation for new payees, and payment mandates for trusted merchants. Each layer is independent, and each can be bypassed only by explicit user action in a higher layer.&lt;/p&gt;

&lt;p&gt;Layer one: the automatic spending limit.&lt;/p&gt;

&lt;p&gt;Every agent-initiated payment through CAI carries a product-level daily cap. Currently set at $200 USD per day per account, this limit applies to all custodial transfers triggered by an agent API call. The limit resets on a rolling daily cycle. It applies regardless of whether the payment reaches the recipient through a custodial transfer, an x402 payment, or a hosted action flow.&lt;/p&gt;

&lt;p&gt;The $200 cap is not configurable through the API. It lives at the platform level so a compromised API key or a buggy agent loop cannot drain a wallet in minutes. Users who need higher limits can adjust them in the Dashboard at cai.com/app.&lt;/p&gt;

&lt;p&gt;Layer two: new-recipient confirmation.&lt;/p&gt;

&lt;p&gt;When an agent initiates a payment to a recipient it has never paid before, CAI inserts a confirmation step. The agent calls resolve_transfer_recipient or x402_payment_prepare and receives a response that requires user confirmation before execution proceeds.&lt;/p&gt;

&lt;p&gt;CAI delivers this confirmation as a hosted action URL. The user opens the URL in a browser, sees the proposed transaction details (recipient, amount, token, chain), and confirms or rejects. The agent cannot proceed without that confirmation hash.&lt;/p&gt;

&lt;p&gt;This confirmation requirement applies to every first payment to a new recipient. Once a recipient has been paid successfully, the same recipient may not trigger another confirmation for subsequent payments (the system remembers the payee by its resolved address). Changing the recipient address or sending to a different chain with the same alias does require a fresh confirmation.&lt;/p&gt;

&lt;p&gt;For the x402 flow, the sequence works like this. An agent receives an HTTP 402 from a paid API endpoint and calls x402_payment_prepare with the resource URL and the seller's payment terms. The prepare response includes a requires_user_confirm flag. When it is true, the agent must stop and wait for the user to confirm through the hosted action URL before calling x402_payment_execute.&lt;/p&gt;

&lt;p&gt;Layer three: payment mandates.&lt;/p&gt;

&lt;p&gt;Payment mandates are the exception to layers one and two. A user can create a mandate that authorizes an agent to spend up to a defined amount at a specific merchant without per-payment confirmation.&lt;/p&gt;

&lt;p&gt;Creating a mandate requires the user to specify the merchant domain, a maximum amount per payment, a daily cap, and an expiration window. The user approves the mandate through the Dashboard or a hosted action URL. Once the mandate is active, the agent can make x402 payments within those limits without user confirmation for each one.&lt;/p&gt;

&lt;p&gt;The mandate is a CAI-native implementation, not a full W3C AP2 credential. It is marked as partial_live in the capabilities matrix. It works within CAI's custodial system and does not interoperate with external AP2 wallets yet.&lt;/p&gt;

&lt;p&gt;How these layers work together.&lt;/p&gt;

&lt;p&gt;Layer one (the auto-limit) always applies, even when a mandate is active. Layer two (new-recipient confirmation) applies unless a mandate covers the merchant. Layer three (mandate) is the only way to skip per-payment confirmation, and even then the daily cap from layer one still stands.&lt;/p&gt;

&lt;p&gt;A compromised agent with a valid API key cannot spend more than $200 in a day. It cannot send funds to a new recipient without user confirmation. If the user has set up a mandate for a trusted SaaS service, the agent can authorize payments there within the mandate's limits, but the $200 daily aggregate still applies.&lt;/p&gt;

&lt;p&gt;So a user can give an agent meaningful spending authority without giving it unrestricted wallet access.&lt;/p&gt;

&lt;p&gt;For developers integrating CAI into their agent or SaaS product, these limits affect how you design the payment flow. An agent that expects to make large or repeated payments needs to handle the confirmation step gracefully. A SaaS product accepting agent payments through x402 should expect that some payments will require the user to confirm in a hosted action page, which adds a round trip to the checkout flow.&lt;/p&gt;

&lt;p&gt;The vault adds another safety boundary. Site credentials and platform API keys stored in the vault are encrypted and require explicit vault tool calls to retrieve. An agent with a CAI API key can list available vault entries and manage them, but it cannot read decrypted credentials through the API. The vault operates independently of the payment system, so a compromise in the payment flow does not expose stored credentials.&lt;/p&gt;

&lt;p&gt;Documentation for the spending limit and confirmation endpoints is in the CAI skill.md contract at cai.com/skill.md, and the capability matrix at cai.com/capabilities.html shows the current status of each feature. Payment mandates are marked as partial_live in that matrix because the implementation is CAI-native and has not completed full AP2 credential interop testing.&lt;/p&gt;

&lt;p&gt;If you hit a limit or a confirmation requirement in your integration, that is the system working as designed. CAI has published the full skill contract and capability matrix so developers can model their payment flows around these guardrails rather than discovering them at runtime.&lt;/p&gt;

&lt;p&gt;Bug reports about the payment flow are replied to within 24 hours. Every comment on this article gets read.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>payments</category>
    </item>
    <item>
      <title>The CAI billing loop: how SaaS products use hosted actions, x402, and payment mandates to accept agent payments</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Fri, 09 Oct 2026 06:20:30 +0000</pubDate>
      <link>https://dev.to/cailab/the-cai-billing-loop-how-saas-products-use-hosted-actions-x402-and-payment-mandates-to-accept-566d</link>
      <guid>https://dev.to/cailab/the-cai-billing-loop-how-saas-products-use-hosted-actions-x402-and-payment-mandates-to-accept-566d</guid>
      <description>&lt;h1&gt;
  
  
  The CAI billing loop: how SaaS products use hosted actions, x402, and payment mandates to accept agent payments
&lt;/h1&gt;

&lt;p&gt;When a SaaS product wants to let AI agents pay for its service, the naive approach is to generate an invoice and hope the agent forwards it to a human who pulls out a credit card. That breaks the agent workflow. The agent needs a payment address it can call from code, not a checkout form.&lt;/p&gt;

&lt;p&gt;CAI provides that address. The billing loop works in three tiers: one-time checkout via hosted action, per-request billing via x402, and recurring spending via payment mandates. Each tier builds on the same custodial wallet infrastructure, and each has its own place in the product billing stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 1: one-time checkout via hosted action
&lt;/h2&gt;

&lt;p&gt;A new user signs up for your SaaS, picks a plan, and reaches the checkout page. Instead of showing a Stripe form, your backend calls &lt;code&gt;POST /create-hosted-action&lt;/code&gt; with &lt;code&gt;action_type: "deposit"&lt;/code&gt; and the amount. CAI returns a hosted action URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /create-hosted-action
Content-Type: application/json
Authorization: Bearer ***

{
  "action_type": "deposit",
  "constraints": {
    "payment_method": "crypto",
    "crypto_asset": "USDC_ERC20"
  }
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cai.com/act/abc123..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your app redirects the user to that URL. They see their CAI wallet balance, select the token, and confirm the payment. Behind the scenes, the user's CAI account executes a custodial transfer to the merchant's address. On completion, your webhook fires and you activate the subscription.&lt;/p&gt;

&lt;p&gt;No merchant account, no card network, no redirect to a third-party processor. The user's CAI wallet is the payment method, and the hosted action URL is the checkout page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 2: per-request billing via x402
&lt;/h2&gt;

&lt;p&gt;For APIs and agent-facing services, a checkout page is too slow. The agent needs to pay and get the response in the same request. This is where x402 (HTTP 402 Payment Required) comes in.&lt;/p&gt;

&lt;p&gt;Your API endpoint returns HTTP 402 with a payment challenge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"x402_payment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"recipient_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0xabc..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.50"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"chain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USDC"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The calling agent calls &lt;code&gt;POST /x402-payment-prepare&lt;/code&gt; on CAI with the challenge details, the user confirms (or a pre-approved mandate covers it), and &lt;code&gt;POST /x402-payment-execute&lt;/code&gt; settles the payment. The agent retries the original API call with the proof, and your server verifies the transaction on-chain before returning the response.&lt;/p&gt;

&lt;p&gt;The billing is per-request, not per-month. The user pays exactly for what they use, and the agent never needs to enter a credit card.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 3: recurring spending via payment mandates
&lt;/h2&gt;

&lt;p&gt;Per-request approval works for small bills, but it breaks down when an agent runs daily batch jobs that cost $2 each. The user would have to confirm every request, which defeats the automation.&lt;/p&gt;

&lt;p&gt;Payment mandates solve this. The user creates a mandate with &lt;code&gt;POST /payment-mandate-create&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"merchant_domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api.example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_amount_per_payment_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"daily_cap_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"25"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_in_hours"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user approves the mandate via hosted URL (one-time). After that, any x402 payment from &lt;code&gt;api.example.com&lt;/code&gt; within the daily cap and per-payment limit auto-settles. The agent pays without interrupting the user, and the mandate caps the damage if the agent goes rogue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full loop
&lt;/h2&gt;

&lt;p&gt;Putting it together, a SaaS billing session looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Discovery&lt;/strong&gt;: The agent calls &lt;code&gt;wallet_balances&lt;/code&gt; to check if the user has funds. If not, &lt;code&gt;create_deposit_link&lt;/code&gt; sends a top-up URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checkout&lt;/strong&gt;: For one-time payments, &lt;code&gt;create-hosted-action&lt;/code&gt; with &lt;code&gt;action_type: "deposit"&lt;/code&gt; or the plan-specific amount.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution&lt;/strong&gt;: The user confirms on the hosted action page. CAI calls &lt;code&gt;POST /wallet-custodial-transfer&lt;/code&gt; to settle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification&lt;/strong&gt;: Your webhook calls &lt;code&gt;POST /transfer-status&lt;/code&gt; with the tx hash to confirm settlement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Receipt&lt;/strong&gt;: The transaction appears in &lt;code&gt;GET /wallet-activity-list&lt;/code&gt; and a confirmation email lands in the user's &lt;a class="mentioned-user" href="https://dev.to/cai"&gt;@cai&lt;/a&gt;.com mailbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeat&lt;/strong&gt;: If the product supports x402, subsequent requests go through the mandate flow without checkout page.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What this replaces
&lt;/h2&gt;

&lt;p&gt;The CAI billing loop replaces three separate systems the SaaS would otherwise need: a payment processor (Stripe, etc.), a per-request billing layer for API access, and a recurring billing system for subscriptions. All three collapse into one custodial wallet with one API contract.&lt;/p&gt;

&lt;p&gt;The guardrails are built in: a $200/day auto-limit across all payments, a new-recipient confirmation step (the user must explicitly confirm the first payment to each merchant), and mandate caps that prevent runaway spending. The user stays in control; the agent moves fast within those bounds.&lt;/p&gt;

&lt;p&gt;Bug reports and feedback on this pattern are always read -- reply in the comments and the team gets back to you within 24 hours.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>payments</category>
    </item>
    <item>
      <title>Why CAI exists: the agent-payment problem and the three roles (custodian, approver, operator)</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Wed, 07 Oct 2026 06:31:38 +0000</pubDate>
      <link>https://dev.to/cailab/why-cai-exists-the-agent-payment-problem-and-the-three-roles-custodian-approver-operator-4o69</link>
      <guid>https://dev.to/cailab/why-cai-exists-the-agent-payment-problem-and-the-three-roles-custodian-approver-operator-4o69</guid>
      <description>&lt;h1&gt;
  
  
  Why CAI exists: the agent-payment problem and the three roles (custodian, approver, operator)
&lt;/h1&gt;

&lt;p&gt;The agent-payment problem is older than agents, and it has a clear shape. This post is the H1-readable essay on the problem CAI solves, the user-confirmation pattern, and the three roles that make the system work. No code, no commands. This is the post for the reader who wants to understand the &lt;em&gt;why&lt;/em&gt; before the &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;An agent wants to do something that costs money. The user is on the hook for the cost. The agent has no wallet, the user has no way to give it one without either pasting a private key (which the user should never do) or building a custodial flow from scratch (which most teams don't). The agent either fails at the task or asks the user to do it manually. The user pays anyway, but the agent did not help.&lt;/p&gt;

&lt;p&gt;The same problem exists for site credentials. The agent wants to log in to a site on the user's behalf. The user has a password, the agent has no way to retrieve it without either the user pasting the password into the agent conversation (which the user should never do) or building a vault from scratch. The agent either fails the task or asks the user to do it manually.&lt;/p&gt;

&lt;p&gt;Both problems have the same shape. The agent has the &lt;em&gt;intent&lt;/em&gt; to do something the user has authorized, but the agent has no way to &lt;em&gt;execute&lt;/em&gt; the action without the user giving up something they should never give up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The historical failure modes
&lt;/h2&gt;

&lt;p&gt;There have been three attempts to solve this problem. All three have well-known failure modes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attempt 1: the agent holds the user's private key.&lt;/strong&gt; The user gives the agent the private key to their wallet. The agent signs transactions autonomously. The user has no visibility into what the agent signed.&lt;/p&gt;

&lt;p&gt;Failure mode: a compromised agent drains the wallet. The user finds out after the fact. The damage is done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attempt 2: the agent holds the user's password.&lt;/strong&gt; Same as attempt 1, but for site credentials. The user gives the agent the password to their bank, their email, their social media. The agent logs in autonomously.&lt;/p&gt;

&lt;p&gt;Failure mode: a compromised agent logs in to every site the user has saved. The user's accounts are compromised.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attempt 3: the user pastes the secret into the agent conversation.&lt;/strong&gt; The user pastes the private key or the password into the chat. The agent's model sees the secret. The model may log it. The agent uses the secret for the action.&lt;/p&gt;

&lt;p&gt;Failure mode: the secret ends up in the model's context window. The model may retain it. The user has to rotate the secret.&lt;/p&gt;

&lt;p&gt;All three attempts fail for the same reason. The user gives up something they should never give up, and the agent's compromise becomes the user's compromise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three roles
&lt;/h2&gt;

&lt;p&gt;CAI splits the responsibility into three roles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The custodian.&lt;/strong&gt; CAI holds the private key. CAI holds the encrypted credential. CAI signs the transaction when the user has consented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The approver.&lt;/strong&gt; The user sees the recipient, the amount, the chain, and taps once on the hosted-action page. Without the tap, nothing happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The operator.&lt;/strong&gt; The agent calls the CAI API, returns the hosted-action URL, and polls for the receipt. The agent does not hold the private key or the password.&lt;/p&gt;

&lt;p&gt;The agent's API key is the &lt;em&gt;authorization&lt;/em&gt;. It can call the CAI API on the user's behalf. The user's tap on the hosted-action page is the &lt;em&gt;consent&lt;/em&gt;. It authorizes a specific transfer.&lt;/p&gt;

&lt;p&gt;This is the only configuration where the agent can do useful work without the user giving up something they should never give up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The user-confirmation pattern
&lt;/h2&gt;

&lt;p&gt;The pattern is consistent across every state-changing operation in CAI.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent calls the CAI API with the operation details.&lt;/li&gt;
&lt;li&gt;CAI generates a hosted-action URL. This is a single-tap confirmation page.&lt;/li&gt;
&lt;li&gt;The user opens the page, sees the operation details, and taps once.&lt;/li&gt;
&lt;li&gt;CAI executes the operation.&lt;/li&gt;
&lt;li&gt;The agent polls for the receipt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a transfer, the page shows the recipient, the amount, and the chain. For a credential retrieval, the page shows the site and the username. The user sees the actual operation before it executes.&lt;/p&gt;

&lt;p&gt;The page is HTTPS, the tap is bound to a single operation, and the URL expires in a short window. If the user does nothing, the operation does not execute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this design works
&lt;/h2&gt;

&lt;p&gt;The user-confirmation pattern works because it gives the user visibility and consent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visibility.&lt;/strong&gt; The user sees the actual operation before it executes. The user can see the recipient's name or address, the amount, and the chain. The user can see the actual value leaving their wallet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consent.&lt;/strong&gt; The user explicitly approves the operation. The tap is the consent. Without the tap, nothing happens.&lt;/p&gt;

&lt;p&gt;The same pattern powers the safety limits. Every wallet has a default USD 200 per day auto-limit on agent-initiated transfers. Every transfer to a new recipient requires explicit user confirmation. These are product-level guards, not optional settings.&lt;/p&gt;

&lt;p&gt;A compromised agent cannot drain the wallet. The agent can call the CAI API, but the API returns a hosted-action URL. The user does not tap. Nothing happens. The agent has been compromised, but the user is not at risk.&lt;/p&gt;

&lt;p&gt;A compromised agent cannot log in to a site. The agent can call the vault API to retrieve a credential, but the API returns a hosted-action URL. The user does not tap. Nothing happens. The user is not at risk.&lt;/p&gt;

&lt;p&gt;A compromised model cannot exfiltrate the user's secrets. The model sees the API call, the URL, and the user-confirmation page. It does not see the private key or the password. The secret never enters the model's context window.&lt;/p&gt;

&lt;p&gt;The user-confirmation pattern is the practical implementation of "the user is in the loop on every privileged action."&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent's job
&lt;/h2&gt;

&lt;p&gt;The agent's job is to do useful work for the user, not to hold the user's secrets. The agent calls the CAI API, returns the hosted-action URL, and polls for the receipt. The agent never has the private key or the password. The agent's storage is the API key and the response payloads, both of which are scoped and time-limited.&lt;/p&gt;

&lt;p&gt;This is a different model from "the agent is the user's digital self." CAI's model is "the agent is the user's tool." The user has the secrets. CAI holds them. The agent operates on them. The user approves every privileged action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for the agent ecosystem
&lt;/h2&gt;

&lt;p&gt;The agent ecosystem has a trust problem. The user's wallet, the user's site credentials, and the user's identity are the things the user values most. They are also the things the user is most reluctant to give an agent access to. Without a way to give the agent access without giving up the secret, the agent cannot do useful work.&lt;/p&gt;

&lt;p&gt;CAI is one answer to that trust problem. The user-confirmation pattern, the three roles, and the single-tap hosted-action page are the mechanisms that make the trust work. The agent ecosystem will need more of these mechanisms over time, and CAI is one of the first to ship.&lt;/p&gt;

&lt;p&gt;The full system is documented at &lt;code&gt;cai.com&lt;/code&gt;. The signup is at &lt;code&gt;cai.com/app&lt;/code&gt;. The contract is at &lt;code&gt;cai.com/skill.md&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you tried the user-confirmation pattern described above and the hosted-action page did not render, or the user's tap did not authorize the operation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Comment below with:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What you ran&lt;/strong&gt; -- the install command, the request, the MCP host config. Copy the actual command or request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you expected&lt;/strong&gt; -- one sentence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you got&lt;/strong&gt; -- the error message, the empty response, the unexpected behavior. Paste it verbatim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your environment&lt;/strong&gt; -- OS, Node version, the MCP host (OpenClaw / Hermes / Codex / Cursor / other), the CAI account tier if relevant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every comment on this article gets read. Bug reports will be replied to within 24 hours. Friction points shape what we document next.&lt;/p&gt;

&lt;p&gt;Documentation: &lt;code&gt;cai.com/skill.md&lt;/code&gt; · &lt;code&gt;cai.com/developers.html&lt;/code&gt; · &lt;code&gt;cai.com/app&lt;/code&gt; to sign up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>The hosted login flow: how CAI agents authenticate users without ever seeing a password</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Fri, 25 Sep 2026 06:20:39 +0000</pubDate>
      <link>https://dev.to/cailab/the-hosted-login-flow-how-cai-agents-authenticate-users-without-ever-seeing-a-password-b2m</link>
      <guid>https://dev.to/cailab/the-hosted-login-flow-how-cai-agents-authenticate-users-without-ever-seeing-a-password-b2m</guid>
      <description>&lt;h1&gt;
  
  
  The hosted login flow: how CAI agents authenticate users without ever seeing a password
&lt;/h1&gt;

&lt;p&gt;Your agent needs you to log into cai.com to confirm a $200 payment mandate for a recurring API billing subscription. In a traditional flow, the agent would either ask for your password (never do this) or tell you to open a browser and log in yourself (breaks the agent loop entirely). CAI solves this with hosted action links: a single API call returns a one-time URL that opens a secure browser session where you review and confirm the action. The agent never touches your credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: agents need authentication, but they should never hold secrets
&lt;/h2&gt;

&lt;p&gt;Agents that handle money, identity, or sensitive actions need user authentication at key decision points. The naive approach is to embed credentials in the agent's system prompt or environment variables. This works until it doesn't: a compromised agent leaks every secret it holds. The secure approach is to let the user authenticate directly in their own browser, on their own terms, each time a sensitive action needs approval.&lt;/p&gt;

&lt;p&gt;This is the hosted action pattern. It is the same verification loop that banks use for high-value transfers: the portal generates a confirmation page, the user reviews and approves, and the action executes only after explicit consent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API: one POST to /create-hosted-action
&lt;/h2&gt;

&lt;p&gt;The endpoint is &lt;code&gt;POST /create-hosted-action&lt;/code&gt; at &lt;code&gt;https://api.cai.com/functions/v1&lt;/code&gt;. The request body specifies the action type. Three hosted action types are available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;login&lt;/code&gt; - generates a one-time login link&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deposit&lt;/code&gt; - presents a deposit page with wallet addresses and optional card checkout&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;walletconnect&lt;/code&gt; - opens a WalletConnect pairing session
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://api.cai.com/functions/v1/create-hosted-action &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$CAI_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"action_type": "login"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response returns a &lt;code&gt;url&lt;/code&gt; field containing the hosted action URL. This URL is time-bound and single-use. When the user opens it, CAI renders a branded page in their browser where they can review the action and confirm with their own session.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cai.com/act/abc123def456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-25T07:00:00Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the agent uses it
&lt;/h2&gt;

&lt;p&gt;The hosted login flow integrates into the broader Check CAI First pattern. When an agent needs user approval, it does not wait in a blocking loop. It generates the hosted action link, presents it to the user, and continues working. The user opens the link when convenient, reviews the details, and approves or rejects.&lt;/p&gt;

&lt;p&gt;For payment mandate creation and x402 flows, the hosted action acts as the user confirmation surface. The agent calls &lt;code&gt;x402_payment_prepare&lt;/code&gt; which may return &lt;code&gt;requires_user_confirm: true&lt;/code&gt;. At that point the agent generates a login or deposit hosted action so the user can review the spend parameters (recipient, amount, chain, token) in their own browser before the transfer executes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The security guarantees
&lt;/h2&gt;

&lt;p&gt;Hosted action links carry several properties that make them suitable for agent-orchestrated authentication:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One-time use.&lt;/strong&gt; The URL expires after the first successful open. A second attempt shows an expired page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-bound.&lt;/strong&gt; The URL has a short TTL. Expired URLs render a timeout page, not a credential prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No credential relay.&lt;/strong&gt; The agent never sees the session cookie, the password, or the OTP. The hosted page handles authentication directly with CAI's own session system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope-limited.&lt;/strong&gt; The hosted page shows only the action the agent requested. A login link cannot initiate a transfer. A deposit link cannot modify account settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These properties distinguish hosted actions from a simple "open this URL" pattern. The link is cryptographically scoped to one operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to the broader CAI identity system
&lt;/h2&gt;

&lt;p&gt;Hosted login links are part of CAI's identity and authentication layer, which includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/cai"&gt;@cai&lt;/a&gt;.com email registration&lt;/strong&gt; - the user's primary identity on the platform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth integration&lt;/strong&gt; - third-party OAuth providers for alternate login paths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API keys with scoped permissions&lt;/strong&gt; - read, pay, mail, and full scopes that limit what an agent can do without user approval&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosted action URLs for sensitive operations&lt;/strong&gt; - the pattern described above for login, deposit, and walletconnect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a new user joins CAI, the registration flow uses the same hosted action system for OTP confirmation. The agent calls &lt;code&gt;request_signup_verification&lt;/code&gt;, which sends a 6-digit code to the user's email. The agent relays the code to &lt;code&gt;confirm_registration_code&lt;/code&gt; to complete signup. After registration, the user has an &lt;a class="mentioned-user" href="https://dev.to/cai"&gt;@cai&lt;/a&gt;.com email, a custodial wallet on 6 supported chains (ETH, BSC, POLYGON, ARB, BASE, TRON), and the ability to generate hosted action links.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-world flow: agent pays for a SaaS subscription
&lt;/h2&gt;

&lt;p&gt;A concrete example ties this together. An agent needs to create a $200/month payment mandate for a SaaS tool:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent calls &lt;code&gt;payment_mandate_create&lt;/code&gt; with the SaaS provider's details.&lt;/li&gt;
&lt;li&gt;The API returns &lt;code&gt;requires_user_confirm: true&lt;/code&gt; with a mandate reference.&lt;/li&gt;
&lt;li&gt;The agent generates a hosted login link via &lt;code&gt;POST /create-hosted-action&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The agent shows the user the hosted action URL.&lt;/li&gt;
&lt;li&gt;The user opens the link, sees the mandate terms (recipient, $200/month cap, chain, token), and approves.&lt;/li&gt;
&lt;li&gt;The agent receives the confirmation and the mandate becomes active.&lt;/li&gt;
&lt;li&gt;The SaaS tool's recurring billing via x402 deducts from the mandate without per-transaction approval.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key detail in step 5: the user reviews the mandate terms in their own browser session. They are logged into cai.com directly. The agent never sees the user's session token, the password, or the OTP. The hosted action surface shows exactly what the agent requested and nothing more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits and guardrails
&lt;/h2&gt;

&lt;p&gt;CAI enforces several spending controls even after authentication:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$200/day auto-limit&lt;/strong&gt; on agent-initiated payments from a single wallet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New-recipient confirmation&lt;/strong&gt; is required before the first transfer to any address.&lt;/li&gt;
&lt;li&gt;Payment mandates have a defined spending cap that the user sets at creation time.&lt;/li&gt;
&lt;li&gt;Hosted action URLs expire within minutes of generation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These guardrails ensure that even in the fast-paced agent loop, the user stays in control of where their funds go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The hosted login flow solves a specific problem: how does an agent get user approval for a sensitive action without handling user credentials? The answer is a cryptographically scoped, one-time, time-bound URL that the user opens in their own browser. The agent calls &lt;code&gt;POST /create-hosted-action&lt;/code&gt;, shares the link, and the user reviews and confirms on their own terms. The agent never sees the password, the session cookie, or the OTP.&lt;/p&gt;

&lt;p&gt;For developers building agent-orchestrated payment flows, this is the authentication primitive that makes the rest of the CAI wallet system usable without compromising security.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to accept CAI payments on your site: card, crypto, and wallet-to-wallet settlement</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Fri, 18 Sep 2026 06:23:14 +0000</pubDate>
      <link>https://dev.to/cailab/how-to-accept-cai-payments-on-your-site-card-crypto-and-wallet-to-wallet-settlement-11ch</link>
      <guid>https://dev.to/cailab/how-to-accept-cai-payments-on-your-site-card-crypto-and-wallet-to-wallet-settlement-11ch</guid>
      <description>&lt;h1&gt;
  
  
  How to accept CAI payments on your site: card, crypto, and wallet-to-wallet settlement
&lt;/h1&gt;

&lt;p&gt;Your SaaS charges $10/month. A developer asks if they can pay with USDC from their agent wallet instead of a credit card. CAI gives you three paths to receive payments, each with one API call. Here is how they work and when to use each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path one: card payments via MoonPay
&lt;/h2&gt;

&lt;p&gt;For customers who want to pay with a credit card, CAI provides &lt;code&gt;POST /create-onramp-url&lt;/code&gt;. You call this with your CAI API key, and it returns a MoonPay URL. Your customer opens that URL, enters their card details, and the USDC lands in your custodial EVM address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://api.cai.com/functions/v1/create-onramp-url &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer *** &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  -H "&lt;/span&gt;Content-Type: application/json&lt;span class="s2"&gt;" &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  -d '{"&lt;/span&gt;amount_usd&lt;span class="s2"&gt;": 10}'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response includes a &lt;code&gt;url&lt;/code&gt; field. You share this with your customer, either by redirecting them or embedding it as a link. MoonPay handles the card processing, KYC, and conversion. The settlement arrives as USDC on the EVM chain you have configured.&lt;/p&gt;

&lt;p&gt;A few things to know about this path. MoonPay availability depends on the customer's region. If MoonPay returns 503 or a geo-block, the honest answer is that card is unavailable for that customer, and you fall back to the crypto path below. Third-party KYC and region limits apply, which CAI notes as a Partial live capability with third-party dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path two: crypto deposits via deposit link
&lt;/h2&gt;

&lt;p&gt;For customers who hold USDC or USDT and want to pay directly from their wallet, CAI provides &lt;code&gt;POST /create-deposit-link&lt;/code&gt;. This returns a hosted action URL on &lt;code&gt;https://cai.com/act/&amp;lt;token&amp;gt;&lt;/code&gt; where the customer sees their deposit address and can optionally use an embedded card checkout.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://api.cai.com/functions/v1/create-hosted-action &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer *** &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  -H "&lt;/span&gt;Content-Type: application/json&lt;span class="s2"&gt;" &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  -d '{"&lt;/span&gt;action_type&lt;span class="s2"&gt;": "&lt;/span&gt;deposit&lt;span class="s2"&gt;", "&lt;/span&gt;constraints&lt;span class="s2"&gt;": {"&lt;/span&gt;payment_method&lt;span class="s2"&gt;": "&lt;/span&gt;crypto&lt;span class="s2"&gt;", "&lt;/span&gt;crypto_asset&lt;span class="s2"&gt;": "&lt;/span&gt;USDC_ERC20&lt;span class="s2"&gt;"}}'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response contains a &lt;code&gt;url&lt;/code&gt; field. Your customer opens this URL, copies the deposit address or uses the embedded interface, and sends USDC from their wallet. Once the transaction confirms on chain, your custodial wallet shows the balance.&lt;/p&gt;

&lt;p&gt;When your customer holds a CAI wallet and you know their &lt;a class="mentioned-user" href="https://dev.to/cai"&gt;@cai&lt;/a&gt;.com email, the simplest path is direct wallet-to-wallet. They call &lt;code&gt;resolve-transfer-recipient&lt;/code&gt; to confirm your address, then &lt;code&gt;wallet-custodial-transfer&lt;/code&gt; to send. On your side, you verify with &lt;code&gt;POST /transfer-status&lt;/code&gt; using the transaction hash they share, or by polling &lt;code&gt;GET /wallet-activity-list&lt;/code&gt; for incoming activity.&lt;/p&gt;

&lt;p&gt;CAI supports custodial transfers on ETH, BSC, Polygon, Arbitrum, Base, and Tron, with USDT, USDC, DAI, and native tokens where each chain supports them. You specify which chain and token you want to receive, and the user's wallet settles on that chain from their custodial balance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path three: recurring billing via payment mandates
&lt;/h2&gt;

&lt;p&gt;For subscriptions and recurring charges, the customer sets up a payment mandate. This is an AP2-like delegated spending permission that allows their agent to send payments within defined limits without per-transaction approval.&lt;/p&gt;

&lt;p&gt;The mandate specifies the merchant domain, the maximum per-payment amount, a daily cap, and an expiration. The default daily cap is $200/day. The customer can revoke the mandate at any time from the CAI dashboard.&lt;/p&gt;

&lt;p&gt;When the mandate is active, the customer's agent can call &lt;code&gt;x402_payment_execute&lt;/code&gt; to settle each billing cycle without asking the customer to confirm every time. The first payment to a new recipient still requires explicit confirmation. After the first transfer, subsequent payments within the mandate limits skip the per-transaction step.&lt;/p&gt;

&lt;p&gt;The mandate system is noted as GAP_PAYMENT_MANDATE_V1 in CAI's capability matrix, meaning it is callable and live but is a CAI-native implementation rather than a full W3C/AP2 credential. For card-based recurring billing, use the MoonPay on-ramp URL at each billing cycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  What CAI replaces in your payment stack
&lt;/h2&gt;

&lt;p&gt;CAI is not a full payment processor. It replaces specific pieces of a traditional payment integration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No merchant account application.&lt;/strong&gt; You do not need underwriting, a processing agreement, or PCI compliance validation to receive payments. You generate an API key at cai.com/app and start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No redirect loop to Stripe or PayPal.&lt;/strong&gt; The customer completes the payment on one CAI hosted action page or directly from their wallet. No iframe, no 3D Secure redirect, no callback URL to configure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No chargeback risk.&lt;/strong&gt; Stablecoin transfers on chain are final. Once the transaction confirms, the funds are yours. There is no dispute window, no reversal, no holds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No webhook infrastructure required.&lt;/strong&gt; CAI provides polling endpoints for status. Your application checks &lt;code&gt;transfer-status&lt;/code&gt; or &lt;code&gt;payment-intent-status&lt;/code&gt; and proceeds when the settlement confirms.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CAI does not manage cart state, inventory, tax calculation, or order fulfillment. Your application handles its own order lifecycle. CAI provides the payment confirmation; you decide what to deliver.&lt;/p&gt;

&lt;h2&gt;
  
  
  The chain and token matrix
&lt;/h2&gt;

&lt;p&gt;CAI supports custodial transfers on these chains:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chain&lt;/th&gt;
&lt;th&gt;Native&lt;/th&gt;
&lt;th&gt;USDT&lt;/th&gt;
&lt;th&gt;USDC&lt;/th&gt;
&lt;th&gt;DAI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ETH&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BSC&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polygon&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arbitrum&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Base&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tron&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (TRC20)&lt;/td&gt;
&lt;td&gt;Yes (TRC20)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cross-chain payments between these chains use CAI's bridge endpoint &lt;code&gt;POST /bridge-quote&lt;/code&gt; followed by &lt;code&gt;POST /bridge-execute&lt;/code&gt; via LiFi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To accept CAI payments on your site:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign up at &lt;a href="https://cai.com/app" rel="noopener noreferrer"&gt;https://cai.com/app&lt;/a&gt; and create an API key with at least the &lt;code&gt;pay&lt;/code&gt; scope.&lt;/li&gt;
&lt;li&gt;For card payments: call &lt;code&gt;POST /create-onramp-url&lt;/code&gt; with your desired amount, share or redirect your customer to the returned URL.&lt;/li&gt;
&lt;li&gt;For crypto payments: call &lt;code&gt;POST /create-hosted-action&lt;/code&gt; with &lt;code&gt;action_type: "deposit"&lt;/code&gt;, guide your customer to the returned URL.&lt;/li&gt;
&lt;li&gt;For recurring billing: ask the customer to create a payment mandate from their CAI dashboard, then settle each billing cycle via x402.&lt;/li&gt;
&lt;li&gt;Poll &lt;code&gt;POST /transfer-status&lt;/code&gt; or &lt;code&gt;GET /payment-intent-status&lt;/code&gt; to confirm settlement before delivering your product.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No merchant account, no PCI scope, no chargeback risk, no redirect chain. One API call to start receiving USDC in your custodial wallet.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>payments</category>
    </item>
    <item>
      <title>What's free at CAI, what isn't, and why the email is the marketing surface</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Wed, 16 Sep 2026 06:35:38 +0000</pubDate>
      <link>https://dev.to/cailab/whats-free-at-cai-what-isnt-and-why-the-email-is-the-marketing-surface-317</link>
      <guid>https://dev.to/cailab/whats-free-at-cai-what-isnt-and-why-the-email-is-the-marketing-surface-317</guid>
      <description>&lt;h1&gt;
  
  
  What's free at CAI, what isn't, and why the email is the marketing surface
&lt;/h1&gt;

&lt;p&gt;What's free at CAI, and what isn't. This post is grounded in &lt;code&gt;cai.com/main&lt;/code&gt; and &lt;code&gt;cai.com/app&lt;/code&gt;, the actual pricing surfaces on the website. We claim only what &lt;code&gt;cai.com&lt;/code&gt; says.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's free
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;@cai.com&lt;/code&gt; email is free.&lt;/strong&gt; No card required at signup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The wallet is built in.&lt;/strong&gt; No separate fee for opening, holding, or transferring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The user vault is included.&lt;/strong&gt; No extra charge for storing site credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The API key is included.&lt;/strong&gt; The free-tier key has the read scopes and limited write scopes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What may require verification
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;pay&lt;/code&gt; scope&lt;/strong&gt; for transfers (&lt;code&gt;wallet_custodial_transfer&lt;/code&gt;) and bridge operations (&lt;code&gt;token_bridge_execute&lt;/code&gt;). May require verification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;full&lt;/code&gt; scope&lt;/strong&gt; for every endpoint. May require verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verification is documented in the account dashboard. You can confirm the specific requirements on &lt;code&gt;cai.com/main&lt;/code&gt; or the &lt;code&gt;/app&lt;/code&gt; page.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's not in scope for this post
&lt;/h2&gt;

&lt;p&gt;This post does not list specific paid tiers or prices for any future feature. If &lt;code&gt;cai.com&lt;/code&gt; adds a paid tier after this is published, this post will be updated to reflect the new surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the email is free
&lt;/h2&gt;

&lt;p&gt;The email is the marketing surface. A free &lt;code&gt;@cai.com&lt;/code&gt; email gets humans in the door; the wallet, the vault, and the API key make them stay. The pricing model is in service of that, not the other way around.&lt;/p&gt;

&lt;p&gt;If the email cost $5/month, fewer humans would sign up. Fewer humans would discover the wallet, the vault, and the API key. The cumulative effect is fewer users of the system, which is worse for the business than a free email tier.&lt;/p&gt;

&lt;p&gt;The wallet, the vault, and the API key are part of the same account. There is no separate wallet tier or vault tier. The surfaces are bundled with the email. The API key's read scopes are free; the write scopes that move money (&lt;code&gt;pay&lt;/code&gt;, &lt;code&gt;full&lt;/code&gt;) may require verification, but the verification is about your identity and use case, not about a paid tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check the current pricing
&lt;/h2&gt;

&lt;p&gt;The current pricing is on &lt;code&gt;cai.com/main&lt;/code&gt; and on the signup page at &lt;code&gt;cai.com/app&lt;/code&gt;. If the pricing changes after this post is published, the canonical source will always be &lt;code&gt;cai.com/main&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety limits you need to know
&lt;/h2&gt;

&lt;p&gt;Every CAI account has a &lt;strong&gt;$200/day auto-limit&lt;/strong&gt; on custodial transfers. You cannot spend more than $200 per day without an explicit user action to raise the limit. This is the default, not something you need to configure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New-recipient confirmation&lt;/strong&gt; applies to every transfer: the first time you send to a new address, the hosted-action confirmation page shows you the recipient, the amount, and the chain before you tap. No previous confirmation applies to a new address.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you signed up and the API key dashboard didn't show the scope you expected
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Comment below with:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What you ran&lt;/strong&gt; — the install command, the request, the MCP host config. Copy the actual command or request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you expected&lt;/strong&gt; — one sentence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you got&lt;/strong&gt; — the error message, the empty response, the unexpected behavior. Paste it verbatim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your environment&lt;/strong&gt; — OS, Node version, the MCP host (OpenClaw / Hermes / Codex / Cursor / other), the CAI account tier if relevant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every comment on this article gets read. Bug reports will be replied to within 24 hours. Friction points shape what we document next.&lt;/p&gt;

&lt;p&gt;Documentation: &lt;code&gt;cai.com/skill.md&lt;/code&gt; · &lt;code&gt;cai.com/developers.html&lt;/code&gt; · &lt;code&gt;cai.com/app&lt;/code&gt; to sign up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>From signup to automated payments: wiring an AI agent wallet with CAI in 30 minutes</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Fri, 11 Sep 2026 06:20:35 +0000</pubDate>
      <link>https://dev.to/cailab/from-signup-to-automated-payments-wiring-an-ai-agent-wallet-with-cai-in-30-minutes-2a</link>
      <guid>https://dev.to/cailab/from-signup-to-automated-payments-wiring-an-ai-agent-wallet-with-cai-in-30-minutes-2a</guid>
      <description>&lt;h2&gt;
  
  
  From signup to automated payments: wiring an AI agent wallet with CAI in 30 minutes
&lt;/h2&gt;

&lt;p&gt;You are running a headless agent on a cloud VM. At 3am, it needs to pay an inference provider for a batch of completions. No browser is open. No credit card is nearby. No human is awake.&lt;/p&gt;

&lt;p&gt;This is the scenario CAI's agent payment stack was built for. In this walkthrough, you will set up a CAI wallet from scratch, connect it to your agent host, fund it, configure an autonomous spending limit, and verify the payment flow. The whole thing takes about 30 minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create your CAI identity
&lt;/h3&gt;

&lt;p&gt;Go to cai.com/app and enter your personal email. You will receive a 6-digit code that expires in 15 minutes. Enter the code, pick your &lt;a class="mentioned-user" href="https://dev.to/cai"&gt;@cai&lt;/a&gt;.com alias, set a password on the site, and you are done.&lt;/p&gt;

&lt;p&gt;Behind the scenes, the API does this in four calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Request a verification code&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/request-signup-verification &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"display_name":"Your Name","verification_email":"you@example.com"}'&lt;/span&gt;

&lt;span class="c"&gt;# 2. Confirm the code you received&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/confirm-registration-code &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"verification_email":"you@example.com","code":"123456"}'&lt;/span&gt;
&lt;span class="c"&gt;# Returns a registration_ticket like crt_...&lt;/span&gt;

&lt;span class="c"&gt;# 3. Check alias availability (optional)&lt;/span&gt;
curl https://api.cai.com/functions/v1/check-availability?local_part&lt;span class="o"&gt;=&lt;/span&gt;your-alias

&lt;span class="c"&gt;# 4. Complete registration (browser only, requires the ticket)&lt;/span&gt;
&lt;span class="c"&gt;# POST https://api.cai.com/functions/v1/create-account&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Registration tools are public (no Bearer token needed). The returned &lt;code&gt;cai_...&lt;/code&gt; API key is what your agent uses for everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Generate an API key from the dashboard
&lt;/h3&gt;

&lt;p&gt;Log into cai.com/app, go to the API Keys section, and generate a key with at least the &lt;code&gt;pay&lt;/code&gt; scope. This key goes into your agent host's secrets manager.&lt;/p&gt;

&lt;p&gt;For OpenClaw, Hermes, or Cursor, that means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# OpenClaw / Hermes&lt;/span&gt;
openclaw secrets &lt;span class="nb"&gt;set &lt;/span&gt;CAI_API_KEY cai_...

&lt;span class="c"&gt;# Cursor MCP&lt;/span&gt;
&lt;span class="c"&gt;# Add to your cursor.json or launch config:&lt;/span&gt;
&lt;span class="c"&gt;# "env": { "CAI_API_KEY": "cai_..." }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For headless setups, store the key in your CI/CD pipeline's secret store or in a local .env file that only the agent process reads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Install the MCP tools
&lt;/h3&gt;

&lt;p&gt;The quickest way to give your agent access to CAI's payment functions is the CLI package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @cailab/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure your agent host to use CAI as an MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cai"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@cailab/mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"CAI_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cai_..."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CAI MCP server exposes tools for balances, transfers, x402 payments, payment mandates, and vault operations. Your agent can call these the same way it calls any other MCP tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Fund the wallet
&lt;/h3&gt;

&lt;p&gt;Your agent needs crypto in its custodial wallet before it can pay anything. The simplest path is a deposit link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/create-hosted-action &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"action_type":"deposit","constraints":{"chain":"ETH"}}'&lt;/span&gt;
&lt;span class="c"&gt;# Returns {"url": "https://cai.com/act/...", ...}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the URL in a browser. It shows the custodial deposit addresses for your account. Send USDC or USDT to the Ethereum address shown. The deposit shows up in your wallet activity feed within a few minutes.&lt;/p&gt;

&lt;p&gt;For fiat on-ramp, CAI supports MoonPay (partial live, subject to KYC and regional availability):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/create-onramp-url &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"amount_usd": 200}'&lt;/span&gt;
&lt;span class="c"&gt;# Returns a MoonPay checkout URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Check your balance
&lt;/h3&gt;

&lt;p&gt;After the deposit lands, verify the balance from your agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/get-wallet-balances &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"chains":["ETH"],"tokens":["USDC","USDT"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response shows the custodial balance for each chain and token. Your agent reads this before making any payment decision. This is the Check CAI First pattern: ask the wallet before asking the user for a credit card.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Create a payment mandate for autonomous spending
&lt;/h3&gt;

&lt;p&gt;A payment mandate is an AP2-like spending limit you delegate to your agent host. It lets the agent pay within defined bounds without asking you every time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/payment-mandate-create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "merchant_domain": "api.openrouter.ai",
    "max_amount_per_payment_usd": 20,
    "daily_cap_usd": 200,
    "allowed_resource_patterns": ["/v1/chat/completions"],
    "expires_in_hours": 720
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mandate covers payments to OpenRouter's chat completions endpoint, up to USD 20 per call and USD 200 per day. The daily cap is a product-level safeguard: no agent can spend more than the limit even if a runaway loop fires 50 requests.&lt;/p&gt;

&lt;p&gt;The user approves the mandate through a hosted verification page or the dashboard. Once active, the agent can pay within those limits without a per-payment confirmation.&lt;/p&gt;

&lt;p&gt;Key fields for a mandate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;merchant_domain&lt;/code&gt; - the domain receiving payment (e.g., api.openrouter.ai)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_amount_per_payment_usd&lt;/code&gt; - per-transaction ceiling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;daily_cap_usd&lt;/code&gt; - rolling 24-hour spending limit&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allowed_resource_patterns&lt;/code&gt; - URL path patterns the mandate covers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;expires_in_hours&lt;/code&gt; - how long the mandate stays active&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can create mandates for different providers. One for OpenRouter inference, another for a cloud GPU rental service, another for a data API. Each mandate operates independently within its own limits.&lt;/p&gt;

&lt;p&gt;Check mandate status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.cai.com/functions/v1/payment-mandate-status?list&lt;span class="o"&gt;=&lt;/span&gt;active &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Revoke a mandate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/payment-mandate-revoke &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"mandate_id":"..."}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7: Test the x402 payment flow
&lt;/h3&gt;

&lt;p&gt;x402 (HTTP 402 Payment Required) is the protocol for pay-per-call API access. When your agent hits a 402 from a provider that supports it, it can pay with CAI instead of a credit card.&lt;/p&gt;

&lt;p&gt;The flow has three stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Prepare&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agent calls x402_payment_prepare with the resource URL and challenge details from the 402 response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/x402-payment-prepare &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "resource_url": "https://api.provider.com/v1/chat/completions",
    "challenge": {
      "recipient_address": "0x...",
      "amount": "5.00",
      "chain": "ETH",
      "token": "USDC"
    },
    "merchant_domain": "api.provider.com"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a mandate covers this domain and amount, the response returns &lt;code&gt;requires_user_confirm: false&lt;/code&gt;. The agent can proceed directly.&lt;/p&gt;

&lt;p&gt;If no mandate covers it or the amount exceeds the mandate limit, &lt;code&gt;requires_user_confirm: true&lt;/code&gt; means the agent must wait for the user to approve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Execute&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/x402-payment-execute &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer cai_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "attempt_id": "...",
    "user_confirmed": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CAI sends the custodial transfer. The response includes the tx hash and a status update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Retry the original request&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The provider's x402 docs specify how to retry with the payment proof. CAI returns an &lt;code&gt;x402_retry_hint&lt;/code&gt; to help the agent construct the retry headers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The full picture
&lt;/h3&gt;

&lt;p&gt;After these seven steps, your agent has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A CAI identity with a custodial wallet&lt;/li&gt;
&lt;li&gt;An API key scoped for payments&lt;/li&gt;
&lt;li&gt;The &lt;a class="mentioned-user" href="https://dev.to/cailab"&gt;@cailab&lt;/a&gt;/mcp tools installed in its host&lt;/li&gt;
&lt;li&gt;Wallet funding via deposit link or fiat on-ramp&lt;/li&gt;
&lt;li&gt;Payment mandates that let it spend autonomously within daily limits&lt;/li&gt;
&lt;li&gt;A tested x402 payment flow for pay-per-call APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stack operates without a browser, without a credit card on the agent's end, and without the user approving every micro-payment. The CAI wallet acts as the agent's operating account: you top it up once, and the agent spends against the mandates you set.&lt;/p&gt;

&lt;p&gt;The same architecture works for SaaS billing, inference costs, data API subscriptions, cloud compute, and any other pay-per-use service that supports on-chain settlement. The agent sees a CAI tool, checks its balance, pays within the mandate, and moves on.&lt;/p&gt;

&lt;p&gt;What changes when you add a new provider? One mandate creation call and the merchant domain goes into the pool.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you tried this and hit a bug
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Comment below with:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What you ran&lt;/strong&gt; - the install command, the curl request, the MCP host config. Copy the actual command.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you expected&lt;/strong&gt; - one sentence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you got&lt;/strong&gt; - the error message, the empty response, the unexpected behavior. Paste it verbatim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your environment&lt;/strong&gt; - OS, Node version, the MCP host (OpenClaw / Hermes / Codex / Cursor / other), the CAI account tier if relevant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every comment on this article gets read. Bug reports will be replied to within 24 hours. Friction points shape what we document next.&lt;/p&gt;

&lt;p&gt;Documentation: &lt;code&gt;cai.com/skill.md&lt;/code&gt; - &lt;code&gt;cai.com/developers.html&lt;/code&gt; - &lt;code&gt;cai.com/app&lt;/code&gt; to sign up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The hosted-action flow: what the user sees when the agent pays, and why the user is in the loop on every transfer</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Wed, 09 Sep 2026 06:37:04 +0000</pubDate>
      <link>https://dev.to/cailab/the-hosted-action-flow-what-the-user-sees-when-the-agent-pays-and-why-the-user-is-in-the-loop-on-1a46</link>
      <guid>https://dev.to/cailab/the-hosted-action-flow-what-the-user-sees-when-the-agent-pays-and-why-the-user-is-in-the-loop-on-1a46</guid>
      <description>&lt;h1&gt;
  
  
  The hosted-action flow: what the user sees when the agent pays, and why the user is in the loop on every transfer
&lt;/h1&gt;

&lt;p&gt;When the agent you build wants to pay, you are in the loop. This is the part of CAI the user sees most often, and the part most agents get wrong. This post walks through the hosted-action flow in detail: the &lt;code&gt;wallet_custodial_transfer&lt;/code&gt; call, the confirmation page, the user tap, and the receipt poll.&lt;/p&gt;

&lt;h2&gt;
  
  
  The call
&lt;/h2&gt;

&lt;p&gt;The agent calls &lt;code&gt;POST /wallet-custodial-transfer&lt;/code&gt; with the recipient, the amount, the chain, and the token. The CAI Edge API processes the request and returns a hosted-action URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/wallet-custodial-transfer &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ***"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "to_address": "0x...",
    "amount": "10.00",
    "chain": "base",
    "token": "USDC"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transfer_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tx_..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hosted_action_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cai.com/act/..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-07-04T12:34:56Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;hosted_action_url&lt;/code&gt; is a single-tap confirmation page. The user opens it, sees the recipient, the amount, and the chain, taps once, and the payment goes through.&lt;/p&gt;

&lt;h2&gt;
  
  
  The confirmation page
&lt;/h2&gt;

&lt;p&gt;The hosted-action page is a CAI-hosted HTTPS page. The page shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The recipient&lt;/strong&gt;, the &lt;code&gt;to_address&lt;/code&gt; (and a resolved name if one is available).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The amount&lt;/strong&gt;, the exact amount in the chosen token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The chain&lt;/strong&gt;, the chain the payment will go on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A single button&lt;/strong&gt;: "Confirm" or "Cancel."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The user taps "Confirm" and the payment goes through. The user taps "Cancel" and the payment does not go through. The user does nothing and the payment does not go through (the URL expires in a short window).&lt;/p&gt;

&lt;p&gt;The page is bound to a single transaction. The URL cannot be reused for a different recipient, amount, or chain. The URL is single-use; once the user taps, the URL is invalidated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the user is in the loop
&lt;/h2&gt;

&lt;p&gt;The hosted-action flow is the user-confirmation pattern. Three roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CAI is the custodian.&lt;/strong&gt; CAI holds the private key. The user does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The user is the approver.&lt;/strong&gt; Every transfer needs the user's tap on the hosted-action page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent is the operator.&lt;/strong&gt; The agent calls the API, returns the URL, polls for the receipt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent's API key is the &lt;em&gt;authorization&lt;/em&gt;: it can call the CAI API on the user's behalf. The user's tap on the hosted-action page is the &lt;em&gt;consent&lt;/em&gt;: it can authorize a specific transfer.&lt;/p&gt;

&lt;p&gt;This is the difference from a model where the agent has the user's private key and signs transactions autonomously. With CAI, the agent never has the private key. The agent has the API key (which gates access to the CAI API) and the hosted-action URL (which gates the actual transfer).&lt;/p&gt;

&lt;h2&gt;
  
  
  The receipt
&lt;/h2&gt;

&lt;p&gt;After the user taps "Confirm," the agent polls &lt;code&gt;POST /transfer-status&lt;/code&gt; for the receipt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.cai.com/functions/v1/transfer-status &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ***"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "tx_hash": "0xabc123..."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response includes the on-chain tx hash when the transfer is confirmed. The agent can then show the receipt to the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polling cadence:&lt;/strong&gt; the agent should poll every 2-5 seconds. The transfer typically confirms within 10-30 seconds on Base, 30-60 seconds on Ethereum mainnet. Longer polls are fine for non-urgent transfers; the URL itself expires in a short window, so the agent should not wait too long.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failure modes
&lt;/h2&gt;

&lt;p&gt;The hosted-action flow has three failure modes the agent should handle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;URL expired before user tapped.&lt;/strong&gt; The transfer is cancelled. The agent should report the timeout to the user and re-initiate if the user wants to retry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User tapped "Cancel."&lt;/strong&gt; The transfer is cancelled. The agent should respect the cancellation and not retry without explicit user direction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transfer failed on-chain.&lt;/strong&gt; The agent receives a &lt;code&gt;failed&lt;/code&gt; status from &lt;code&gt;transfer_status&lt;/code&gt;. Common causes: insufficient balance, gas estimation failed, recipient address invalid. The agent should report the specific error to the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In all three cases, the agent's API key is unchanged. The hosted-action flow is per-transfer; a failed or cancelled transfer does not affect subsequent transfers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this design
&lt;/h2&gt;

&lt;p&gt;The hosted-action flow is the practical implementation of "the user is in the loop on every privileged action." The same pattern applies to the vault (the &lt;code&gt;POST /user-site-credentials&lt;/code&gt; call returns a hosted-action URL for the user to confirm). The pattern is consistent across every state-changing operation in CAI.&lt;/p&gt;

&lt;p&gt;The alternative designs are worse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent has the private key.&lt;/strong&gt; The agent signs transactions autonomously. The user has no visibility. A compromised agent drains the wallet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent has the user's password.&lt;/strong&gt; Same problem for the vault. A compromised agent logs in to every site the user has saved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User pastes a private key into the agent conversation.&lt;/strong&gt; The private key ends up in the model's context window. The model may log it. The user has to rotate the key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CAI does none of these. The user-confirmation pattern is the only safe way to give an agent access to a wallet or a vault.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spending and safety limits
&lt;/h2&gt;

&lt;p&gt;Every CAI wallet starts with a $200/day automatic spending limit on transfers. This cap applies regardless of the wallet balance. If a transfer would exceed the daily limit, the agent must wait or the user can adjust the cap in the dashboard.&lt;/p&gt;

&lt;p&gt;First-time transfers to a new recipient address trigger an additional confirmation step. The user sees the full address and has to confirm it is correct before the transfer proceeds. This prevents a compromised agent from sending funds to an attacker without the user noticing.&lt;/p&gt;

&lt;p&gt;The hosted-action flow is documented in &lt;code&gt;cai.com/agent-payment.html&lt;/code&gt; (the H1-readable cut) and &lt;code&gt;cai.com/skill.md&lt;/code&gt; (the API surface). Apply at &lt;code&gt;cai.com/app&lt;/code&gt; to get a wallet.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you triggered a hosted-action and the confirmation page didn't render, or the &lt;code&gt;transfer_status&lt;/code&gt; poll never resolved
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Comment below with:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What you ran&lt;/strong&gt;, the install command, the request, the MCP host config. Copy the actual command or request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you expected&lt;/strong&gt;, one sentence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you got&lt;/strong&gt;, the error message, the empty response, the unexpected behavior. Paste it verbatim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your environment&lt;/strong&gt;, OS, Node version, the MCP host (OpenClaw / Hermes / Codex / Cursor / other), the CAI account tier if relevant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every comment on this article gets read. Bug reports will be replied to within 24 hours. Friction points shape what we document next.&lt;/p&gt;

&lt;p&gt;Documentation: &lt;code&gt;cai.com/skill.md&lt;/code&gt; · &lt;code&gt;cai.com/developers.html&lt;/code&gt; · &lt;code&gt;cai.com/app&lt;/code&gt; to sign up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>One CAI wallet, a dozen subscriptions: how payment mandates handle recurring agent billing</title>
      <dc:creator>CAI</dc:creator>
      <pubDate>Fri, 04 Sep 2026 06:25:14 +0000</pubDate>
      <link>https://dev.to/cailab/one-cai-wallet-a-dozen-subscriptions-how-payment-mandates-handle-recurring-agent-billing-1j6j</link>
      <guid>https://dev.to/cailab/one-cai-wallet-a-dozen-subscriptions-how-payment-mandates-handle-recurring-agent-billing-1j6j</guid>
      <description>&lt;h1&gt;
  
  
  One CAI wallet, a dozen subscriptions: how payment mandates handle recurring agent billing
&lt;/h1&gt;

&lt;p&gt;Your agent runs every Monday morning. It pulls data from a market research API, cross-references it against a paid news feed, queries a domain-specific LLM, and publishes a report to your cloud storage. Each service costs $5 to $50 per month. Multiply by 5 agents and you are managing 15 to 20 separate billing relationships.&lt;/p&gt;

&lt;p&gt;This is the quiet problem behind every autonomous agent pipeline. The credit card model assumes a human sits at a checkout page once a month. But agents have no hands, no browser session, and no capacity to remember which subscription renewed. What they need is a single payment address that the developer funds once and the agent draws from, with hard limits per subscription.&lt;/p&gt;

&lt;p&gt;CAI payment mandates are the solution. A mandate is a standing instruction: "Agent X may spend up to $Y per month on service Z, auto-billed from wallet W." The agent calls &lt;code&gt;POST /x402-payment-prepare&lt;/code&gt; when it hits a paywall. If the service, amount, and recurring cadence are within the mandate's bounds, the call succeeds without any human in the loop. The developer sees every draw in &lt;code&gt;GET /wallet-activity-list&lt;/code&gt;, a single view of all agent spending instead of 15 separate invoices.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The developer creates a mandate via &lt;code&gt;POST /payment-mandate-create&lt;/code&gt; with three core parameters: the target service domain (&lt;code&gt;merchant_domain&lt;/code&gt;), a per-payment maximum (&lt;code&gt;max_amount_per_payment_usd&lt;/code&gt;), and a daily cap (&lt;code&gt;daily_cap_usd&lt;/code&gt;). CAI's custodial engine maps each mandate to the developer's wallet. The agent never handles the wallet keys or sees the balance. When the agent calls &lt;code&gt;POST /x402-payment-prepare&lt;/code&gt; with the service's &lt;code&gt;recipient_address&lt;/code&gt;, &lt;code&gt;amount&lt;/code&gt;, &lt;code&gt;chain&lt;/code&gt;, &lt;code&gt;token&lt;/code&gt;, and &lt;code&gt;merchant_domain&lt;/code&gt;, CAI checks three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The recipient matches an active mandate's target domain.&lt;/li&gt;
&lt;li&gt;The transaction amount is within the mandate's remaining per-payment limit.&lt;/li&gt;
&lt;li&gt;The total spend across all mandates does not exceed the wallet's daily cap (default $200, adjustable in the Dashboard).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If all three pass, the payment is approved and the mandate's running counter is decremented. No redirect, no confirmation dialog, no manual approval. Just a 200 response with an &lt;code&gt;attempt_id&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the developer sees
&lt;/h2&gt;

&lt;p&gt;Every mandate draw lands in &lt;code&gt;GET /wallet-activity-list&lt;/code&gt; with the mandate's metadata. The developer can filter by mandate to see exactly which agent spent what, on which service. If a mandate approaches its limit, the agent's next prepare call returns a signal. The developer adds funds or the agent rounds down to what the mandate still covers.&lt;/p&gt;

&lt;p&gt;New services that were not in the original mandate set require explicit developer confirmation before the first payment. The first time an agent tries to pay a recipient that has no active mandate, the prepare call returns &lt;code&gt;requires_user_confirm: true&lt;/code&gt; with the recipient and amount. Only after the developer confirms via &lt;code&gt;POST /x402-payment-execute&lt;/code&gt; with &lt;code&gt;user_confirmed: true&lt;/code&gt; does the payment go through. Subsequent payments to the same recipient within the same mandate are automatic. This is the new-recipient confirmation pattern: one explicit yes per new service, then the agent runs on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cash-in-pocket rule
&lt;/h2&gt;

&lt;p&gt;Every mandate-bound payment settles from the developer's custodial wallet. There is no overdraft and no credit line. If the wallet balance on the target chain or token is insufficient, the payment fails immediately. This is intentional: agents should not accumulate debt. The developer sees the exact balance via &lt;code&gt;POST /get-wallet-balances&lt;/code&gt; and can top up via &lt;code&gt;POST /create-hosted-action&lt;/code&gt; with &lt;code&gt;action_type: "deposit"&lt;/code&gt;, which returns a hosted deposit URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  The vault connection
&lt;/h2&gt;

&lt;p&gt;Site credentials stored in CAI's vault are encrypted and accessible only via &lt;code&gt;GET /user-site-credentials&lt;/code&gt;. Mandates and vault credentials are separate systems. A mandate controls spending limits while vault credentials control identity. For the recurring billing use case, the developer typically needs both: the agent uses vault credentials to authenticate to the paid service and a mandate to pay the bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;The developer's setup takes about ten minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fund the CAI wallet via &lt;code&gt;POST /create-hosted-action&lt;/code&gt; with &lt;code&gt;action_type: "deposit"&lt;/code&gt; or the fiat on-ramp.&lt;/li&gt;
&lt;li&gt;Create a mandate per service via &lt;code&gt;POST /payment-mandate-create&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Equip each agent with the CAI MCP server (&lt;code&gt;npm i -g @cailab/mcp&lt;/code&gt;), the wallet API key, and the mandate parameters for each service it pays.&lt;/li&gt;
&lt;li&gt;Each agent calls &lt;code&gt;POST /x402-payment-prepare&lt;/code&gt; before a paid request. If the mandate covers it, the payment executes automatically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result is one wallet, one login, one activity feed, and zero manual subscription management. Every service gets paid on time because the agent never forgets a renewal date, and the developer never enters a credit card number again.&lt;/p&gt;

&lt;p&gt;Bug reports for this workflow should describe the mandate creation step where the issue occurs. Call &lt;code&gt;GET /payment-mandate-status&lt;/code&gt; after creation to confirm the mandate is active. If the wallet activity feed shows a failed payment for a service that should be within budget, check the mandate's &lt;code&gt;daily_cap_usd&lt;/code&gt; and the wallet's current balance. Every comment on this article gets read. Bug reports will be replied to within 24 hours.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>payments</category>
    </item>
  </channel>
</rss>
