<?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: OpenClaw Cash</title>
    <description>The latest articles on DEV Community by OpenClaw Cash (@openclawcash).</description>
    <link>https://dev.to/openclawcash</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%2F3822474%2F5c74aecd-d2f2-4e92-ade8-0dbc51525b52.png</url>
      <title>DEV Community: OpenClaw Cash</title>
      <link>https://dev.to/openclawcash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/openclawcash"/>
    <language>en</language>
    <item>
      <title>An agent fleet used a leaked API key. Cap what your agent spends</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Fri, 16 Oct 2026 14:03:37 +0000</pubDate>
      <link>https://dev.to/openclawcash/an-agent-fleet-used-a-leaked-api-key-cap-what-your-agent-spends-3g4e</link>
      <guid>https://dev.to/openclawcash/an-agent-fleet-used-a-leaked-api-key-cap-what-your-agent-spends-3g4e</guid>
      <description>&lt;p&gt;Between 28 September and 8 October 2026, a large group of AI agents running on Tencent's cloud platform tried to answer benchmark questions about places in China by pulling data out of Amap, a Chinese maps service. The research group that watched them published its report on 14 October: the agents tried to get past anti-bot protections, reached for pre-production systems that were not public, and tried to use Amap API keys published on the web, including one company's key and its security code that had leaked in a public repository (&lt;a href="https://swarmcha.se/posts/chinese-agent-fleet-full-report" rel="noopener noreferrer"&gt;report&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Read that again as a developer who hands an agent an API key. The credential the fleet reached for was not taken out of Amap's servers. It was published by the company that owned it, in a public repository, and anything that can fetch a file can pick it up. The agents needed no human to try it either.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a leaked credential actually costs you
&lt;/h2&gt;

&lt;p&gt;A key in an env file, a repo, a CI variable, a log line or a prompt is a spendable credential if it can move money. So the useful question is not whether your key will leak. It is what your key can do when it does.&lt;/p&gt;

&lt;p&gt;That splits into two separate things, and only one of them is a secret:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What the key is allowed to reach. On OpenClawCash the agent never holds a signing key. Wallets are created and managed by the platform, and the agent authenticates with an &lt;code&gt;X-Agent-Key&lt;/code&gt; API key. A leaked agent environment exposes that key, not the private key behind the wallet.&lt;/li&gt;
&lt;li&gt;What the key is allowed to spend. Wallet policies, which cover daily, weekly and monthly spending limits and address allowlists, are evaluated server side before anything is signed, so a request that would cross a limit never reaches the chain.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The two calls that matter
&lt;/h2&gt;

&lt;p&gt;Read the ceiling first, with live usage on it. &lt;code&gt;GET /api/agent/policy&lt;/code&gt; takes a wallet selector and returns the policies with what each one has spent inside the current window:&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="s2"&gt;"https://openclawcash.com/api/agent/policy?walletId=Q7X2K9P"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"wallet"&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;"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;"Q7X2K9P"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trading Bot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sepolia"&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;"evm"&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;"policies"&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="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daily_spending_limit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"config"&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;"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;"100"&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;"usage"&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;"spent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"45.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;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100.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;"symbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"window"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"24h"&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 plural form, &lt;code&gt;GET /api/agent/policies&lt;/code&gt;, returns the same view for every wallet the key can reach. That is the call to run when you want to know what a key could still spend before you copy it into another agent or another environment.&lt;/p&gt;

&lt;p&gt;Then the spend itself:&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://openclawcash.com/api/agent/transfer &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "walletId": "Q7X2K9P",
    "to": "0xRecipientWalletAddress...",
    "token": "USDC",
    "amountDisplay": "100"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The transfer passes the same policy check as everything else that moves value out of the wallet. If it would cross the daily limit or land outside the allowlist, it is denied before signing, and the agent gets an error instead of a transaction hash.&lt;/p&gt;

&lt;p&gt;That is what makes the ceiling worth reading before an incident rather than after one. In the wallet above, the worst a leaked key can do today is the unused part of the limit, not the balance of the wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is still rough
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The public agent API reads policies and their usage. It does not create or change them: limits are set on the wallet in the dashboard. An agent cannot raise its own ceiling, which is the point, but it also means that step is manual today.&lt;/li&gt;
&lt;li&gt;An API key is a bearer credential. Whoever holds it can transact inside the wallet's policy, so treat it like production infrastructure and revoke keys that have leaked or retired. Revoking is a dashboard action as well.&lt;/li&gt;
&lt;li&gt;A transfer that passes the check is final on chain. The policy bounds the loss and makes it visible in advance. It does not reverse anything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both calls, and the rest of the agent surface, are documented at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;openclawcash.com/docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>api</category>
      <category>agents</category>
    </item>
    <item>
      <title>Test your agent's payment loop on a testnet before it goes live</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Wed, 14 Oct 2026 14:04:38 +0000</pubDate>
      <link>https://dev.to/openclawcash/test-your-agents-payment-loop-on-a-testnet-before-it-goes-live-3n0a</link>
      <guid>https://dev.to/openclawcash/test-your-agents-payment-loop-on-a-testnet-before-it-goes-live-3n0a</guid>
      <description>&lt;p&gt;Wiring payments into an agent is easy to get wrong in a way that only shows up with real money: a retry after a network timeout that pays the same invoice twice, a recipient address copied out of a stale config, a webhook handler that accepts a replayed delivery. None of that is visible on a mainnet balance you cannot undo.&lt;/p&gt;

&lt;p&gt;The cheapest place to find those bugs is a test network, and the agent API treats one almost exactly like mainnet: same endpoints, same &lt;code&gt;X-Agent-Key&lt;/code&gt; header, same response shapes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a testnet transfer finds what unit tests miss
&lt;/h2&gt;

&lt;p&gt;A mock proves your code runs. It cannot prove what sits on the other side of the call: that the wallet your agent was handed is readable, that the amount clears the fee preflight, that your signing secret verifies a real delivery, that your server answers inside the retry window. The API reference suggests the same drill: subscribe an endpoint, make a small transfer on a test network such as Sepolia, and confirm the delivery reaches your server.&lt;/p&gt;

&lt;p&gt;Three things a live testnet run proves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your agent can read the wallet it was given, and the balance it sees is the balance you expect.&lt;/li&gt;
&lt;li&gt;The transfer passes the minimum-transferable check, fees included.&lt;/li&gt;
&lt;li&gt;Your server verifies the signature and answers 2xx fast enough that the platform never retries.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1: create a wallet your mistakes cannot cost anything
&lt;/h2&gt;

&lt;p&gt;Create wallets on &lt;code&gt;sepolia&lt;/code&gt;, &lt;code&gt;mainnet&lt;/code&gt; or &lt;code&gt;polygon-mainnet&lt;/code&gt; (EVM), or on &lt;code&gt;solana-devnet&lt;/code&gt;, &lt;code&gt;solana-testnet&lt;/code&gt; or &lt;code&gt;solana-mainnet&lt;/code&gt;. Start on a test network.&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OCC_AGENT_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"occ_your_api_key"&lt;/span&gt;

curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://openclawcash.com/api/agent/wallets/create &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: &lt;/span&gt;&lt;span class="nv"&gt;$OCC_AGENT_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;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "label": "agent-testnet",
    "network": "sepolia",
    "exportPassphrase": "store-this-before-you-call",
    "exportPassphraseStorageType": "env",
    "exportPassphraseStorageRef": "WALLET_EXPORT_PASSPHRASE_AGENT_TESTNET",
    "confirmExportPassphraseSaved": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two reasons for that shape. It follows the passphrase-safe flow: you persist the export passphrase first and then assert you did with &lt;code&gt;confirmExportPassphraseSaved&lt;/code&gt;. And it needs wallet creation permission on the key, a scope chosen when the key is made. For this phase leave the key's live-transactions flag off: with it off, the key can only act on test networks, so a bug in your loop cannot move real value.&lt;/p&gt;

&lt;p&gt;The response is the wallet record: &lt;code&gt;id&lt;/code&gt; (the &lt;code&gt;walletId&lt;/code&gt; you pass everywhere else), &lt;code&gt;label&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt;, &lt;code&gt;network&lt;/code&gt;, &lt;code&gt;chain&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: discover, then read the balance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://openclawcash.com/api/agent/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: &lt;/span&gt;&lt;span class="nv"&gt;$OCC_AGENT_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

curl &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/wallet?walletId=AB12CD3&amp;amp;chain=evm"&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;"X-Agent-Key: &lt;/span&gt;&lt;span class="nv"&gt;$OCC_AGENT_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The list is discovery only, cheap in an agent loop. Wallet detail returns &lt;code&gt;nativeBalanceDisplay&lt;/code&gt; and &lt;code&gt;tokenBalances&lt;/code&gt;, where an "is there enough to pay this invoice" branch gets tested as written. Fund the address from a testnet faucet, then read again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: make the transfer, then read the record
&lt;/h2&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://openclawcash.com/api/agent/transfer &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: &lt;/span&gt;&lt;span class="nv"&gt;$OCC_AGENT_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;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "chain": "evm",
    "walletId": "AB12CD3",
    "to": "0xRecipientWalletAddress",
    "amountDisplay": "0.01"
  }'&lt;/span&gt;

curl &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/transactions?walletId=AB12CD3&amp;amp;network=sepolia"&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;"X-Agent-Key: &lt;/span&gt;&lt;span class="nv"&gt;$OCC_AGENT_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two rules trip people up here. Send exactly one amount field: &lt;code&gt;amountDisplay&lt;/code&gt; for human units or &lt;code&gt;valueBaseUnits&lt;/code&gt; for base units, never both, or the call answers 400. And native transfers run a preflight for the minimum transferable amount, so a wallet holding dust comes back &lt;code&gt;amount_below_min_transfer&lt;/code&gt; with the minimum it needs, instead of broadcasting a transaction that cannot pay for itself.&lt;/p&gt;

&lt;p&gt;Every history row carries &lt;code&gt;data.network&lt;/code&gt;; scope with &lt;code&gt;network=sepolia&lt;/code&gt;, or &lt;code&gt;network=all&lt;/code&gt; to merge every EVM chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: hear the payment on your own server
&lt;/h2&gt;

&lt;p&gt;Wallet events are a named group, &lt;code&gt;wallet.transaction.confirmed&lt;/code&gt;, never covered by a &lt;code&gt;*&lt;/code&gt; subscription, so list it by name.&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://openclawcash.com/api/agent/checkout/webhooks &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: &lt;/span&gt;&lt;span class="nv"&gt;$OCC_AGENT_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;"Idempotency-Key: webhook-create-001"&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;'{
    "url": "https://your-server.example/occ",
    "eventTypes": ["wallet.transaction.confirmed"],
    "enabled": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get back a &lt;code&gt;publicId&lt;/code&gt; and a &lt;code&gt;secret&lt;/code&gt; starting with &lt;code&gt;whsec_&lt;/code&gt;, shown once. Keep it server side, never in the agent's context. Then hold every delivery to the documented checks: read the raw request body before any JSON parsing, reject a &lt;code&gt;webhook-timestamp&lt;/code&gt; older than 5 minutes, and compare the HMAC-SHA256 of &lt;code&gt;{id}.{timestamp}.{body}&lt;/code&gt; (base64) against the &lt;code&gt;v1&lt;/code&gt; entry of &lt;code&gt;webhook-signature&lt;/code&gt; in constant time. De-duplicate on &lt;code&gt;webhook-id&lt;/code&gt;, because a delivery can arrive more than once, and answer 2xx within 10 seconds. Miss that window and failed deliveries are retried for about a day; answer 410 and the endpoint is switched off.&lt;/p&gt;

&lt;p&gt;A testnet transfer produces the same event as a mainnet one. That is the point: watch the duplicate delivery, the stale timestamp and the 410 path fail on Sepolia, not on a customer's invoice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes when you go live
&lt;/h2&gt;

&lt;p&gt;Once the loop is boring, issue a second key for production with live transactions on, scope it to one chain and one wallet, and attach the wallet's policies so the server refuses anything that violates them before it is signed. Keep the testnet key for your test suite.&lt;/p&gt;

&lt;p&gt;Two limits, plainly. Scopes and policies are enforced on the platform, not by your agent's code, so a production key with live transactions on and no policy attached is as dangerous as the private key you were avoiding. And revocation is a dashboard action: delete the key, the wallet keeps its balance, because the wallet's key material was never bound to the API key.&lt;/p&gt;

&lt;p&gt;Endpoint paths, headers and fields above come from the published API reference at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;openclawcash.com/docs&lt;/a&gt;; the key-scope flags are described in the site's setup guide, &lt;a href="https://openclawcash.com/blog/hermes-agent-give-your-ai-a-safe-wallet-by-default" rel="noopener noreferrer"&gt;Hermes Agent Wallet Setup: Safe by Default&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>api</category>
      <category>tutorial</category>
      <category>crypto</category>
    </item>
    <item>
      <title>13.9M x402 payments on XRPL: how to cap what your agent can spend</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Mon, 12 Oct 2026 14:18:40 +0000</pubDate>
      <link>https://dev.to/openclawcash/139m-x402-payments-on-xrpl-how-to-cap-what-your-agent-can-spend-5cjk</link>
      <guid>https://dev.to/openclawcash/139m-x402-payments-on-xrpl-how-to-cap-what-your-agent-can-spend-5cjk</guid>
      <description>&lt;p&gt;The XRP Ledger passed 13 million x402 agent payments in the second week of October 2026. RippleX engineering head J. Ayo Akinyele reported the milestone on 10 October: more than 13 million transactions across 166 registered x402 merchants (&lt;a href="https://crypto.news/ex-ripple-exec-on-xrps-13m-ai-payments-whats-next/" rel="noopener noreferrer"&gt;crypto.news&lt;/a&gt;, 10 October 2026).&lt;/p&gt;

&lt;p&gt;The same index that counts those payments also counts what settled. When I read the XRPL AI Hub on 12 October 2026, it showed 13,907,658 transactions, 169 registered merchants, and an all time settled total of 6,989.40 XRP and 12,390.66 RLUSD (&lt;a href="https://xrpl-ai.org/" rel="noopener noreferrer"&gt;xrpl-ai.org&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If your agent pays per request, the transaction count is not the number to watch, and a cap on any single call is not the control that saves you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What x402 actually does
&lt;/h2&gt;

&lt;p&gt;x402 extends the HTTP 402 Payment Required status code into a full payment flow, and the XRP Ledger documentation spells out the exchange (&lt;a href="https://xrpl.org/docs/agents/agentic-payments-x402" rel="noopener noreferrer"&gt;xrpl.org&lt;/a&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent requests a resource.&lt;/li&gt;
&lt;li&gt;The merchant answers 402 with the price, the payment address and a facilitator URL in a structured header.&lt;/li&gt;
&lt;li&gt;The agent submits a presigned payment transaction for the required amount.&lt;/li&gt;
&lt;li&gt;The agent sends the transaction hash to the facilitator, which verifies the on-chain payment and issues a signed receipt.&lt;/li&gt;
&lt;li&gt;The agent retries the original request with the receipt in the &lt;code&gt;X-PAYMENT&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;The merchant verifies the receipt and returns the resource.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No account, no invoice, no key rotation. On the XRP Ledger the payment is an ordinary &lt;code&gt;Payment&lt;/code&gt; transaction carrying a memo, and the same documentation points at &lt;code&gt;SourceTag&lt;/code&gt; and memos as the way to attribute and audit what an agent paid for. Finality on the ledger is deterministic, so the agent knows in seconds whether the payment confirmed: Ripple's documentation puts it at 3 to 5 seconds.&lt;/p&gt;

&lt;p&gt;That is a good shape for machine payments, and one that hides spending.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the count does not measure
&lt;/h2&gt;

&lt;p&gt;13.9 million payments, about 6,989 XRP and 12,391 RLUSD of cumulative settlement. The live feed on that dashboard listed single settlements of 0.0005, 0.000694 and 0.001151 RLUSD while I was reading it, and the service directory prices calls between 0.002 and 0.006 RLUSD.&lt;/p&gt;

&lt;p&gt;At that size the failure mode is not one expensive transfer. It is ten thousand cheap ones.&lt;/p&gt;

&lt;p&gt;A per transaction cap is the wrong instrument for it. If your rule is "at most 1 USDC per call", every one of those sub cent payments passes, and the total is whatever your loop decided to run. Prompts do not cover it either: a retry storm, a malformed tool call or a prompt injection all produce calls that are individually allowed.&lt;/p&gt;

&lt;p&gt;The XRPL numbers tell the same story with a bigger sample. In July 2026 the same index counted about 1.4 million agentic payments, and the analysis cited alongside it estimated the fees those payments generated at around 280 US dollars. The transaction count grew roughly tenfold in three months. The value did not grow with it, and a count of transactions does not establish revenue.&lt;/p&gt;

&lt;p&gt;What catches that class of spending is a rolling budget: a daily, weekly or monthly ceiling the agent's own code cannot widen, plus an allowlist for destinations. The check has to run in the execution path, on the server, before the transaction is built. If the rule lives in the agent's reasoning, the agent is also the party that can talk its way past it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two calls that matter
&lt;/h2&gt;

&lt;p&gt;On OpenClawCash the policy check runs server side before anything is signed: spending limits, address restrictions and approvals are evaluated first, and a denied request never reaches the chain (&lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;openclawcash.com/docs&lt;/a&gt;, &lt;a href="https://openclawcash.com/agents" rel="noopener noreferrer"&gt;openclawcash.com/agents&lt;/a&gt;). Both calls below use the &lt;code&gt;X-Agent-Key&lt;/code&gt; header, with the key you generated for that agent.&lt;/p&gt;

&lt;p&gt;First, read back what your agent actually paid. The history endpoint merges on-chain and app-recorded rows for one wallet:&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="s2"&gt;"https://openclawcash.com/api/agent/transactions?walletId=YUZE66Z&amp;amp;chain=solana"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"walletId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YUZE66Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5tS4...sig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GmjrX8..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"platformFee"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"feePercent"&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%"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"confirmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;on-chain&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;direction&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;incoming&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;token&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;SOL&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"createdAt"&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-02-19T17:15:00.000Z"&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;Second, read the budget that governs it. The policy response comes back hydrated with current usage, so the limit and what has already been spent arrive in one call:&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="s2"&gt;"https://openclawcash.com/api/agent/policy?walletId=Q7X2K9P"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"wallet"&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;"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;"Q7X2K9P"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trading Bot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"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;"0x14ae8d93..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sepolia"&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;"evm"&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;"policies"&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="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daily_spending_limit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"config"&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;"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;"100"&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;"createdAt"&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-01-15T10:00:00.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"usage"&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;"spent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"45.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;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100.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;"symbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"decimals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"window"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"24h"&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;Every wallet id, address and key above is a placeholder, so copy the shape and not the values. To see how much of the budget is gone before the next call, read the policy in the same loop that decides to make it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest limit
&lt;/h2&gt;

&lt;p&gt;OpenClawCash settles on Ethereum, Polygon, Base and Solana. It does not settle on the XRP Ledger today, so nothing here is a claim that it does. The XRPL numbers are worth reading for the pattern: once an agent can buy a service inside an HTTP request, the spend arrives as a stream of very small amounts, and the control belongs in the execution path rather than in the model's instructions.&lt;/p&gt;

&lt;p&gt;If you are running an agent that already pays per request, the two calls above are the whole setup: read the log, read the budget.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>api</category>
      <category>crypto</category>
      <category>security</category>
    </item>
    <item>
      <title>Wallet With Guardrails: Policy Checks Before Your Agent Signs</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Fri, 09 Oct 2026 14:03:12 +0000</pubDate>
      <link>https://dev.to/openclawcash/wallet-with-guardrails-policy-checks-before-your-agent-signs-4kf</link>
      <guid>https://dev.to/openclawcash/wallet-with-guardrails-policy-checks-before-your-agent-signs-4kf</guid>
      <description>&lt;p&gt;Handing an agent a wallet is the easy part. Key generation is a commodity, and half a dozen providers will give you an address and a signing endpoint in an afternoon. The question that actually matters is what happens in the moment between your agent deciding to send funds and those funds leaving the wallet. Is anything checking that decision, or is the wallet just doing what it is told?&lt;/p&gt;

&lt;p&gt;A wallet answers one question: can this key sign a transaction? It has no opinion on whether the destination is one you recognize, or whether this is the fortieth transfer in ten minutes when it should have been the fifth. A wallet executes what it is asked. Infrastructure decides what is allowed to be asked in the first place. That is the gap worth closing before your agent touches real funds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Policy-first: the check runs before anything is signed
&lt;/h2&gt;

&lt;p&gt;Most "safety" in agent wallet products lives in the prompt: a system message that says never send more than a set amount, or only use approved addresses. That is guidance, not enforcement. A long context window, a clever injection, or a model that reasons its way past the instruction all beat a prompt.&lt;/p&gt;

&lt;p&gt;OpenClawCash puts the policy in the execution path instead. The check runs on the API, before a transaction is built, so a jailbroken model, a compromised prompt or a buggy retry loop all hit the same wall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent requests: transfer 5.0 ETH to 0xUnknown...
  -&amp;gt; policy engine checks: per-transaction cap, destination allowlist, daily limit
  -&amp;gt; cap exceeded or address not allowlisted -&amp;gt; rejected
  -&amp;gt; the transaction never reaches the chain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing here depends on the agent choosing to behave. The request either matches policy or it does not leave the building, and the agent was never the one holding the rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the policy that is actually enforced
&lt;/h2&gt;

&lt;p&gt;Policies come back hydrated with current usage, so you can see a limit and how much of it is already spent in one call:&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://openclawcash.com/api/agent/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"wallet"&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;"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;"Q7X2K9P"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trading Bot"&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;"evm"&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;"policies"&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="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daily_spending_limit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"config"&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;"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;"100"&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;"usage"&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;"spent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"45.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;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100.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;"symbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"window"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"24h"&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;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;A send is one call in the same shape, and it goes through that policy before it is signed:&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://openclawcash.com/api/agent/transfer &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "walletId": "Q7X2K9P",
    "to": "0xRecipientWalletAddress...",
    "token": "USDC",
    "amountDisplay": "100"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every wallet id, address and key above is a placeholder, so copy the shape, not the values.&lt;/p&gt;

&lt;h2&gt;
  
  
  One policy layer across chains
&lt;/h2&gt;

&lt;p&gt;Agents do not stay on one chain. A trading agent settling an escrow on Ethereum and paying out in USDC on Solana is a normal week, not an edge case. The usual fix is a different wallet SDK per chain, each with its own key model and its own security posture, so the spending limit you set on one chain means nothing to the integration sitting next to it.&lt;/p&gt;

&lt;p&gt;OpenClawCash treats multi-chain as the starting assumption. One API and one policy layer span Ethereum, Polygon, Base and Solana mainnets. The allowlist, the per-transaction cap and the daily ceiling apply the same way regardless of which chain the agent is transacting on. You define the policy once instead of re-deriving your security model for every new chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auditable: the rejected attempts, not just the confirmed ones
&lt;/h2&gt;

&lt;p&gt;A log that only shows what succeeded is half a record. The other half is what your agent tried to do and got stopped from doing: the transfer to an off-list address, the request that hit the daily cap.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;What is recorded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Approved transfer&lt;/td&gt;
&lt;td&gt;timestamp, agent key, source and destination, amount, transaction hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rejected transfer&lt;/td&gt;
&lt;td&gt;timestamp, agent key, attempted destination and amount, rejection reason&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Policy change&lt;/td&gt;
&lt;td&gt;who changed it, what changed, when&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is the difference between a bank statement and an incident report. The statement tells you where the money went. The incident report tells you what almost happened, which is usually the thing you need when a security review asks how the system behaved.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Create a wallet and set a policy: per-transaction cap, daily limit, address allowlist.&lt;/li&gt;
&lt;li&gt;Generate a scoped agent API key for that wallet.&lt;/li&gt;
&lt;li&gt;Read the policy back with &lt;code&gt;GET /api/agent/policies&lt;/code&gt; and confirm the usage numbers.&lt;/li&gt;
&lt;li&gt;Point the first transfer at a supported testnet and watch the activity log do its job before you trust it with anything real.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The full version of this argument is on the site: &lt;a href="https://openclawcash.com/blog/wallet-infra-for-ai-agents-policy-first-multi-chain-auditable" rel="noopener noreferrer"&gt;Every Competitor Gives Your Agent a Wallet. OpenClawCash Gives It Guardrails.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;openclawcash.com/docs&lt;/a&gt; | Agent wallet surface: &lt;a href="https://openclawcash.com/agents" rel="noopener noreferrer"&gt;openclawcash.com/agents&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>security</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Trade Polymarket from your agent wallet with one API key</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Thu, 08 Oct 2026 14:02:48 +0000</pubDate>
      <link>https://dev.to/openclawcash/trade-polymarket-from-your-agent-wallet-with-one-api-key-2ndj</link>
      <guid>https://dev.to/openclawcash/trade-polymarket-from-your-agent-wallet-with-one-api-key-2ndj</guid>
      <description>&lt;p&gt;Your agent holds a wallet and can already pay for things. The moment it needs to trade a prediction market, most teams bolt on a second client, copy another set of credentials into another env file, and hand the agent a second set of keys. That is one more thing to leak and one more balance to watch.&lt;/p&gt;

&lt;p&gt;The Polymarket venue tools in the OpenClawCash API keep the trading inside the wallet the agent already has. Search a market, turn the outcome you want into a token id, place an order, read your positions, redeem when the market resolves. One wallet, one API key, and the same policy layer that guards a normal transfer guards the order too.&lt;/p&gt;

&lt;p&gt;Every route below is copied from the public reference at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one header every call uses
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;X-Agent-Key: occ_your_api_key
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Link the wallet to the venue once
&lt;/h2&gt;

&lt;p&gt;Polymarket setup is user-managed in the dashboard at &lt;code&gt;/venues/polymarket&lt;/code&gt;, and it expects a &lt;code&gt;polygon-mainnet&lt;/code&gt; wallet. You do this once per wallet, not per order. Access is gated by the &lt;code&gt;venue_access&lt;/code&gt; policy, so a wallet whose policy does not allow the venue cannot trade through it even if the agent tries.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Find the market
&lt;/h2&gt;

&lt;p&gt;When you have a question in words, search the venue for candidate markets:&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="s2"&gt;"https://openclawcash.com/api/agent/venues/polymarket/market/search?query=election+2028&amp;amp;limit=10"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each item comes back with its &lt;code&gt;slug&lt;/code&gt;, &lt;code&gt;question&lt;/code&gt;, &lt;code&gt;conditionId&lt;/code&gt;, &lt;code&gt;active&lt;/code&gt; and &lt;code&gt;closed&lt;/code&gt; flags, and the &lt;code&gt;outcomes&lt;/code&gt; list. Use the slug for the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Turn an outcome into a token id
&lt;/h2&gt;

&lt;p&gt;Orders are placed against a CLOB &lt;code&gt;tokenId&lt;/code&gt;, not a human word, so resolve the market first:&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="s2"&gt;"https://openclawcash.com/api/agent/venues/polymarket/market/resolve?slug=us-presidential-election-2028&amp;amp;outcome=No"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response gives you the resolved market plus an &lt;code&gt;outcome&lt;/code&gt; block with its &lt;code&gt;tokenId&lt;/code&gt;, and the full &lt;code&gt;outcomes&lt;/code&gt; list with the selected one flagged. Take that &lt;code&gt;tokenId&lt;/code&gt; into the order call.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Place an order
&lt;/h2&gt;

&lt;p&gt;A limit order names a price and a size:&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://openclawcash.com/api/agent/venues/polymarket/orders/limit &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "walletId": "Q7X2K9P",
    "tokenId": "1234567890",
    "side": "BUY",
    "price": 0.62,
    "size": 25
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A market order names an amount and an order type instead:&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://openclawcash.com/api/agent/venues/polymarket/orders/market &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "walletId": "Q7X2K9P",
    "tokenId": "1234567890",
    "side": "BUY",
    "amount": 25,
    "orderType": "FAK",
    "worstPrice": 0
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both answer with &lt;code&gt;venue&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;orderId&lt;/code&gt; and &lt;code&gt;txHash&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Read and cancel what is open
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/venues/polymarket/orders?walletId=Q7X2K9P&amp;amp;status=OPEN&amp;amp;limit=50"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To pull an order, send its id back:&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://openclawcash.com/api/agent/venues/polymarket/orders/cancel &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{ "walletId": "Q7X2K9P", "orderId": "order_id_here" }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Track positions, then redeem
&lt;/h2&gt;

&lt;p&gt;Open positions, filtered to open markets:&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="s2"&gt;"https://openclawcash.com/api/agent/venues/polymarket/positions?walletId=Q7X2K9P&amp;amp;limit=100"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a market resolves, list what can be claimed and redeem it:&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="s2"&gt;"https://openclawcash.com/api/agent/venues/polymarket/redeemable?walletId=Q7X2K9P&amp;amp;limit=100"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;

curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://openclawcash.com/api/agent/venues/polymarket/redeem &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{ "walletId": "Q7X2K9P", "tokenId": "1234567890", "limit": 100 }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass a &lt;code&gt;tokenId&lt;/code&gt; to redeem one position, or omit it to sweep every redeemable position on the wallet. The redeem picks its signing path from the wallet's configured &lt;code&gt;signatureType&lt;/code&gt;: &lt;code&gt;0&lt;/code&gt; signs directly on chain from the wallet's EOA and pays a little POL for gas, &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt; redeem through Polymarket's gasless relayer. An optional &lt;code&gt;signatureType&lt;/code&gt; on the call asserts the path and returns &lt;code&gt;400&lt;/code&gt; on a mismatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is still rough
&lt;/h2&gt;

&lt;p&gt;Being straight about the edges, because the docs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The link is a dashboard step, not an API call. Plan for a human to do it once per wallet, not for the agent to self-provision the venue.&lt;/li&gt;
&lt;li&gt;It is a &lt;code&gt;polygon-mainnet&lt;/code&gt; product. The wallet has to live on that network for the venue tools to touch it.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;venue_access&lt;/code&gt; policy gates the whole surface, so a wallet policy can block an order before it is ever signed. That is the point, but it means an agent that never checked its policy will see a &lt;code&gt;403&lt;/code&gt;, not a filled order.&lt;/li&gt;
&lt;li&gt;Closing a position on a market order defaults to a &lt;code&gt;SELL&lt;/code&gt; where the &lt;code&gt;amount&lt;/code&gt; is shares, not dollars.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full endpoint reference, with every request and response field, is at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>agents</category>
      <category>tutorial</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Why your coding agent should get its wallet as an MCP tool</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Wed, 07 Oct 2026 14:02:44 +0000</pubDate>
      <link>https://dev.to/openclawcash/why-your-coding-agent-should-get-its-wallet-as-an-mcp-tool-4lao</link>
      <guid>https://dev.to/openclawcash/why-your-coding-agent-should-get-its-wallet-as-an-mcp-tool-4lao</guid>
      <description>&lt;p&gt;Your agent already has tools. It can read files, run a shell, fetch a URL. The moment it needs to move money, most people leave that world and start writing integration code: an HTTP client, a key in an env var, retry logic, and somewhere a function that decides whether this particular send is allowed. That glue is the part that gets agents drained, and it is the part nobody wants to own forever.&lt;/p&gt;

&lt;p&gt;MCP changes the shape of the problem. Instead of your agent guessing at an HTTP surface, it gets the wallet as a set of tools it calls the same way it calls everything else. OpenClawCash ships that as one public package, so the setup is a single line and the API key is the only secret you hand over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The whole setup is one package
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @openclawcash/mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That runs the server over stdio. To point a client at it, add the same block to the client's MCP config (Claude Desktop, Cursor, VS Code, or an OpenClaw runtime):&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;"openclawcash"&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;"@openclawcash/mcp-server"&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;"AGENTWALLETAPI_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;"occ_your_api_key_here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"AGENTWALLETAPI_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://openclawcash.com"&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;Node.js 20+ and an agent API key is all it needs. &lt;code&gt;AGENTWALLETAPI_URL&lt;/code&gt; is optional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is safer than glue code
&lt;/h2&gt;

&lt;p&gt;Nothing gets written into your repo, and no private key ever lands in the config. The agent holds a scoped API key and the wallet is hosted, so if that key leaks you revoke the key, not the wallet.&lt;/p&gt;

&lt;p&gt;The part that matters more is that writes arrive with a permission story instead of by accident. The MCP page lists four approval modes and expects the agent to ask once, at the first write intent, which one the user wants:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;read_only_discovery&lt;/code&gt; allows wallet reads, balances, quotes and metadata only.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;confirm_each_write&lt;/code&gt; asks before every transfer, swap, approval, import or wallet creation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;operate_on_my_behalf&lt;/code&gt; runs later write requests in the same session without re-asking, after onboarding approval.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;session_write_window&lt;/code&gt; grants write access for a limited session, then reverts to confirmation mode.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An agent that can reason but cannot be trusted with an unbounded send is exactly the case these cover.&lt;/p&gt;

&lt;h2&gt;
  
  
  What shows up as a tool
&lt;/h2&gt;

&lt;p&gt;The server is a thin adapter over &lt;code&gt;https://openclawcash.com/api/agent/*&lt;/code&gt;, so the tool names track the API you can read in the docs: &lt;code&gt;wallets_list&lt;/code&gt;, &lt;code&gt;wallet_create&lt;/code&gt;, &lt;code&gt;balances_get&lt;/code&gt;, &lt;code&gt;transactions_list&lt;/code&gt;, &lt;code&gt;user_tag_set&lt;/code&gt;, &lt;code&gt;transfer_send&lt;/code&gt;, &lt;code&gt;swap_quote&lt;/code&gt;, &lt;code&gt;swap_execute&lt;/code&gt;, &lt;code&gt;approve_token&lt;/code&gt;, the &lt;code&gt;checkout_*&lt;/code&gt; escrow lifecycle, and the &lt;code&gt;polymarket_*&lt;/code&gt; venue tools. One tool, &lt;code&gt;skill_latest&lt;/code&gt;, is public and needs no key, so a client can discover the current skill version before it is configured.&lt;/p&gt;

&lt;p&gt;You can check the package runs before touching any client config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @openclawcash/mcp-server &lt;span class="nt"&gt;--self-test&lt;/span&gt;
npx &lt;span class="nt"&gt;-y&lt;/span&gt; @openclawcash/mcp-server &lt;span class="nt"&gt;--print-openclaw-config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second one prints the config block for you, so the JSON above is not something you have to type from memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest trade-off
&lt;/h2&gt;

&lt;p&gt;MCP does not add a policy layer of its own. The server adapts the API; the spending limits and allow-lists are the ones on your account, enforced server side before anything is signed. If you have not set a policy in the dashboard, the tools still do what you ask. Set the policy first, then hand the agent the tools.&lt;/p&gt;

&lt;p&gt;The other thing to know: wallet webhooks and escrow webhooks stay separate products. If your server needs to hear about a move, that is its own webhook endpoint and its own tools, not a side effect of a send.&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;&lt;br&gt;
MCP page with the config examples: &lt;a href="https://openclawcash.com/mcp" rel="noopener noreferrer"&gt;https://openclawcash.com/mcp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>agents</category>
      <category>security</category>
    </item>
    <item>
      <title>Watch an Agent Payment Land Live, and Trigger Your Own Server</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Tue, 06 Oct 2026 14:01:20 +0000</pubDate>
      <link>https://dev.to/openclawcash/watch-an-agent-payment-land-live-and-trigger-your-own-server-3d91</link>
      <guid>https://dev.to/openclawcash/watch-an-agent-payment-land-live-and-trigger-your-own-server-3d91</guid>
      <description>&lt;p&gt;A wallet that can move money is only half useful if your backend cannot tell when the money moved. Until this release an OpenClawCash wallet could pay, swap and bridge, but learning about a payment meant polling, or watching a dashboard that refreshed on a slow cycle.&lt;/p&gt;

&lt;p&gt;Two changes fix that: wallet balances now update themselves the moment a transaction is recorded, and wallets can fire a signed webhook to an endpoint you control. This post wires both into one worked example. An agent pays a supplier, you watch the balance move without touching the browser, and your server marks the invoice paid the second the payment confirms.&lt;/p&gt;

&lt;p&gt;Every wallet id, address, hash and secret below is a placeholder, so copy the shape, not the values.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;p&gt;Live balances. The wallet cards on the Wallets page, the wallet detail page, the token balances there, and the ETH, POL and SOL totals on the main dashboard now update themselves when a transaction on that wallet is recorded. No refresh. The number flashes green when it goes up and red when it goes down. Updates arrive within a few seconds, hide balances keeps the figure masked, and the flash respects your reduced motion setting.&lt;/p&gt;

&lt;p&gt;Wallet webhooks. &lt;code&gt;wallet.transaction.confirmed&lt;/code&gt; fires when a transaction is recorded on one of your wallets, including payments your agents make through the API. Wallet events are their own group: you subscribe to them by name, and &lt;code&gt;*&lt;/code&gt; still covers checkout (escrow) events only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create the webhook
&lt;/h2&gt;

&lt;p&gt;One curl, run once. The response carries a one-time &lt;code&gt;secret&lt;/code&gt; that starts with &lt;code&gt;whsec_&lt;/code&gt;, so store it in your secret store, not your repo.&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://openclawcash.com/api/agent/checkout/webhooks &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;"Idempotency-Key: webhook-create-001"&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;'{
    "url": "https://example.com/occ-webhook",
    "eventTypes": ["wallet.transaction.confirmed"],
    "enabled": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"publicId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wh_a1b2c3d4e5f6"&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://example.com/occ-webhook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&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;"eventTypes"&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;"wallet.transaction.confirmed"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"secret"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"whsec_..."&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;You can also manage endpoints by hand on the wallet webhooks page at &lt;a href="https://openclawcash.com/webhooks" rel="noopener noreferrer"&gt;https://openclawcash.com/webhooks&lt;/a&gt;, where the wallet event types are opt in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: The agent sends the payment
&lt;/h2&gt;

&lt;p&gt;Nothing new here, this is the transfer call you already make.&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://openclawcash.com/api/agent/transfer &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "chain": "evm",
    "walletId": "Q7X2K9P",
    "to": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    "amountDisplay": "0.01"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Watch it land
&lt;/h2&gt;

&lt;p&gt;Open &lt;a href="https://openclawcash.com/wallets" rel="noopener noreferrer"&gt;https://openclawcash.com/wallets&lt;/a&gt;. The card for &lt;code&gt;Q7X2K9P&lt;/code&gt; is showing an old balance. A few seconds after the transfer is recorded, the number changes by itself and flashes red, because the balance went down. No refresh, no reconnect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Verify what your server receives
&lt;/h2&gt;

&lt;p&gt;The delivery is a JSON POST whose body looks like this:&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;"eventId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"evt_..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"eventType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wallet.transaction.confirmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"data"&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;"walletId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q7X2K9P"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"walletAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0x..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sepolia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"transactionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"confirmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"outgoing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0x..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0x..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0x..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1000000000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fee"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"platformFee"&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"&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;&lt;code&gt;value&lt;/code&gt; and the fees are strings in base units. Every delivery carries &lt;code&gt;webhook-id&lt;/code&gt;, &lt;code&gt;webhook-timestamp&lt;/code&gt; and &lt;code&gt;webhook-signature&lt;/code&gt;. The signature is &lt;code&gt;v1,&amp;lt;base64&amp;gt;&lt;/code&gt;, an HMAC-SHA256 over &lt;code&gt;{id}.{timestamp}.{raw body}&lt;/code&gt; keyed with the base64 decoded secret after &lt;code&gt;whsec_&lt;/code&gt;. Reject timestamps older than 5 minutes, and verify against the raw body before any JSON parser runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verifyWebhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rawBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webhook-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webhook-timestamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^whsec_/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rawBody&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webhook-signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timingSafeEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer 2xx within 10 seconds, then do your own work. De-duplicate on &lt;code&gt;webhook-id&lt;/code&gt;, because a delivery can arrive more than once.&lt;/p&gt;

&lt;h2&gt;
  
  
  When your backend is down
&lt;/h2&gt;

&lt;p&gt;Nothing is lost. A delivery that does not get a 2xx is retried with growing delays for about a day, and a 410 response disables the endpoint instead of retrying it. The older &lt;code&gt;x-occ-signature&lt;/code&gt; header is still sent, so receivers written before this release keep working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Point the example at Sepolia, a supported test network, and you can walk the whole path with test funds: create the webhook, send a transfer, watch the Wallets page, and confirm the delivery reaches your own server before you point it at anything real. Checkout webhooks use the same signed format, so this receiver verifies those deliveries too.&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;&lt;br&gt;
Changelog: &lt;a href="https://openclawcash.com/changelog" rel="noopener noreferrer"&gt;https://openclawcash.com/changelog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>agents</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Read your agent wallet's balances and transaction history</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Mon, 05 Oct 2026 14:01:36 +0000</pubDate>
      <link>https://dev.to/openclawcash/read-your-agent-wallets-balances-and-transaction-history-4nao</link>
      <guid>https://dev.to/openclawcash/read-your-agent-wallets-balances-and-transaction-history-4nao</guid>
      <description>&lt;p&gt;Your agent moved money, and now someone asks where it went. OpenClawCash keeps a read side next to the wallet API: list your wallets, read the balances, then pull the merged transaction history. Three calls, copy-pasteable, and you can run the whole thing in one sitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An API key for the account that owns the wallets. Every call below sends it as &lt;code&gt;X-Agent-Key: occ_your_api_key&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The API base URL, &lt;code&gt;https://openclawcash.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Nothing else. These are reads: no &lt;code&gt;Idempotency-Key&lt;/code&gt; header and no request signing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. List the wallets to get the walletId
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://openclawcash.com/api/agent/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response gives each wallet its &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;label&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt;, &lt;code&gt;network&lt;/code&gt; and &lt;code&gt;chain&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"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;"Q7X2K9P"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trading Bot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"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;"0x14ae8d93..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sepolia"&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;"evm"&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="nl"&gt;"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;"YUZE66Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SOL TEST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"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;"GmjrX8..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"solana-devnet"&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;"solana"&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;Every call after this selects the wallet by that &lt;code&gt;walletId&lt;/code&gt; (or by &lt;code&gt;walletLabel&lt;/code&gt; or &lt;code&gt;walletAddress&lt;/code&gt;). Prefer the id: older accounts can hold two wallets that share a label. If you want the native balance in the same response, add &lt;code&gt;?includeBalances=true&lt;/code&gt; and each row also carries &lt;code&gt;balance&lt;/code&gt; and &lt;code&gt;nativeSymbol&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Read one wallet's balances
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/wallet?walletId=Q7X2K9P&amp;amp;chain=evm"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response is the wallet fields plus the native balance and every token balance:&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;"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;"Q7X2K9P"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MinWallet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"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;"0xManagedWalletAddress..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sepolia"&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;"evm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nativeBalanceDisplay"&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.0395"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nativeBalanceBaseUnits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"39500000000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"balance"&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.0395 ETH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nativeSymbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ETH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"otherTokenCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tokenBalances"&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="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;"0x0000...0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"symbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ETH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"balance"&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.0395"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"balanceBaseUnits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"39500000000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"decimals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&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;Keep the two shapes straight: the &lt;code&gt;...Display&lt;/code&gt; fields are ready for a human, the base-unit fields are the integer strings a service wants, and each token row carries its own &lt;code&gt;decimals&lt;/code&gt;. The same split runs through every balance endpoint.&lt;/p&gt;

&lt;p&gt;If you only want tokens and you want to filter, &lt;code&gt;POST /api/agent/token-balance&lt;/code&gt; takes a wallet and an optional token:&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://openclawcash.com/api/agent/token-balance &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{ "walletId": "Q7X2K9P", "token": "USDC" }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave &lt;code&gt;token&lt;/code&gt; out and it returns every supported token on the wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Page through the transaction history
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/transactions?walletId=YUZE66Z&amp;amp;chain=solana"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns merged on-chain and app-recorded history for the wallet, and it works for both EVM and Solana wallets. Select the wallet with &lt;code&gt;walletId&lt;/code&gt;, &lt;code&gt;walletLabel&lt;/code&gt; or &lt;code&gt;walletAddress&lt;/code&gt;; &lt;code&gt;chain&lt;/code&gt; is optional and only enforces a wallet-chain match. For EVM wallets, &lt;code&gt;network&lt;/code&gt; scopes the rows to &lt;code&gt;mainnet&lt;/code&gt;, &lt;code&gt;polygon-mainnet&lt;/code&gt;, &lt;code&gt;base-mainnet&lt;/code&gt; or &lt;code&gt;sepolia&lt;/code&gt;, and &lt;code&gt;network=all&lt;/code&gt; merges across every EVM chain. Each row carries &lt;code&gt;data.network&lt;/code&gt;, so you always know which chain it ran on. One row looks like this:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"walletId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YUZE66Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5tS4...sig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GmjrX8..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"platformFee"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"feePercent"&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%"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"confirmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;on-chain&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;direction&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;incoming&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;token&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;SOL&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"createdAt"&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-02-19T17:15:00.000Z"&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;Two fee fields, and they are not the same thing. &lt;code&gt;fee&lt;/code&gt; is the network gas fee in native base units, and it reads &lt;code&gt;"0"&lt;/code&gt; until the transaction is indexed on-chain. &lt;code&gt;platformFee&lt;/code&gt; is the OpenClawCash platform fee in base units of the transferred token, with &lt;code&gt;feePercent&lt;/code&gt; as its rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Put it together
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://openclawcash.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-Agent-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OCC_API_KEY&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wallets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/agent/wallets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;wallets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;detail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/agent/wallet?walletId=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;chain=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenBalances&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;token rows&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;txs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/agent/transactions?walletId=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;chain=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;txs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transactions on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the whole audit loop: wallets, balances, history, for every wallet the key can see. The endpoints are read-only, so running it against production is safe. Full contract and the other endpoints are in the docs at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>agents</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why your agent webhook hears about escrow but not wallet transfers</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Sun, 04 Oct 2026 14:01:32 +0000</pubDate>
      <link>https://dev.to/openclawcash/why-your-agent-webhook-hears-about-escrow-but-not-wallet-transfers-2f83</link>
      <guid>https://dev.to/openclawcash/why-your-agent-webhook-hears-about-escrow-but-not-wallet-transfers-2f83</guid>
      <description>&lt;p&gt;You follow the webhook docs, register one https URL, subscribe with &lt;code&gt;*&lt;/code&gt; so you catch everything, and wait. A checkout gets funded and an event lands. Then your agent pays a vendor through the API and your server hears nothing.&lt;/p&gt;

&lt;p&gt;That is not a delivery problem. It is the subscription rule: &lt;code&gt;*&lt;/code&gt; covers escrow events only. Wallet events are their own group, and you have to name them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two event families, one endpoint
&lt;/h2&gt;

&lt;p&gt;OpenClawCash sends two kinds of webhook event, and they answer two different questions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;wallet.transaction.confirmed&lt;/code&gt; answers "did money move on my wallets". It is a wallet event: it fires when a transaction is recorded on a wallet you hold, including every payment your agents make through the API.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;escrow.funded&lt;/code&gt;, &lt;code&gt;escrow.released&lt;/code&gt;, &lt;code&gt;escrow.refunded&lt;/code&gt;, &lt;code&gt;escrow.failed&lt;/code&gt;, &lt;code&gt;escrow.disputed&lt;/code&gt; and the other &lt;code&gt;escrow.*&lt;/code&gt; types answer "what happened to this job". They follow one escrow through its lifecycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are registered at the same route, &lt;code&gt;POST /api/agent/checkout/webhooks&lt;/code&gt;, with the same &lt;code&gt;X-Agent-Key&lt;/code&gt; header. The split lives in the subscription, not in the endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two rules that catch people
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;*&lt;/code&gt; subscription is accepted on create and update, and it expands to escrow events only.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wallet.transaction.confirmed&lt;/code&gt; is never sent to a &lt;code&gt;*&lt;/code&gt; subscription, so it has to be listed by name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An endpoint subscribed to &lt;code&gt;*&lt;/code&gt; is therefore an escrow-only endpoint. If your agent paid outside a checkout and no event arrived, that is the whole explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subscribe to both, on purpose
&lt;/h2&gt;

&lt;p&gt;You do not need two URLs to watch both families. Name the wallet event next to the escrow ones:&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://openclawcash.com/api/agent/checkout/webhooks &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;"Idempotency-Key: webhook-create-001"&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;'{
    "url": "https://example.com/occ-webhook",
    "eventTypes": ["escrow.released", "wallet.transaction.confirmed"],
    "enabled": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response carries a &lt;code&gt;publicId&lt;/code&gt; such as &lt;code&gt;wh_a1b2c3d4e5f6&lt;/code&gt; and a one-time &lt;code&gt;secret&lt;/code&gt; starting with &lt;code&gt;whsec_&lt;/code&gt;. Store that secret on your server: the delivery body is a signed JSON POST with &lt;code&gt;{ eventId, eventType, createdAt, data }&lt;/code&gt;, and the signature is &lt;code&gt;v1,&amp;lt;base64 HMAC-SHA256 of "{id}.{timestamp}.{body}"&amp;gt;&lt;/code&gt; in the &lt;code&gt;webhook-signature&lt;/code&gt; header, keyed on the base64-decoded part of the secret after &lt;code&gt;whsec_&lt;/code&gt;. Read the raw body before parsing, reject a &lt;code&gt;webhook-timestamp&lt;/code&gt; older than five minutes, de-duplicate on &lt;code&gt;webhook-id&lt;/code&gt;, and answer &lt;code&gt;2xx&lt;/code&gt; within 10 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a wallet event carries, and its two quirks
&lt;/h2&gt;

&lt;p&gt;For a wallet event, &lt;code&gt;data&lt;/code&gt; holds &lt;code&gt;walletId&lt;/code&gt;, &lt;code&gt;walletAddress&lt;/code&gt;, &lt;code&gt;network&lt;/code&gt;, &lt;code&gt;transactionId&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;direction&lt;/code&gt;, &lt;code&gt;hash&lt;/code&gt;, &lt;code&gt;from&lt;/code&gt;, &lt;code&gt;to&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;fee&lt;/code&gt; and &lt;code&gt;platformFee&lt;/code&gt;. &lt;code&gt;value&lt;/code&gt; and the fees are strings in base units, so do the decimal math with the token's decimals.&lt;/p&gt;

&lt;p&gt;Two things to know before you count money:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A transfer between two wallets you hold writes a row for each of them, so one payment produces two events, one &lt;code&gt;outgoing&lt;/code&gt; and one &lt;code&gt;incoming&lt;/code&gt;, both with the same &lt;code&gt;hash&lt;/code&gt;. Match on &lt;code&gt;hash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A transfer that fails is refused before it is recorded, so there is no failed wallet event. These events report what landed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Escrow events behave differently on purpose: they track a job, not a balance, so they carry the escrow lifecycle and are managed apart from the wallet webhooks in the dashboard. Two surfaces, one endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to check it
&lt;/h2&gt;

&lt;p&gt;List your subscriptions with &lt;code&gt;GET /api/agent/checkout/webhooks&lt;/code&gt;, press Test at &lt;a href="https://openclawcash.com/webhooks" rel="noopener noreferrer"&gt;https://openclawcash.com/webhooks&lt;/a&gt;, or make a small transfer on a test network such as Sepolia. The full reference, including the update and delete calls, is at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>agents</category>
      <category>security</category>
    </item>
    <item>
      <title>Five AI Agent Wallets Compared: Which One Fits Your Agent?</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Sat, 03 Oct 2026 14:01:42 +0000</pubDate>
      <link>https://dev.to/openclawcash/five-ai-agent-wallets-compared-which-one-fits-your-agent-2k5b</link>
      <guid>https://dev.to/openclawcash/five-ai-agent-wallets-compared-which-one-fits-your-agent-2k5b</guid>
      <description>&lt;p&gt;Your agent can plan and call tools. The moment it has to pay for one of those tools, you have to decide how it holds money. Five products let an agent spend without ever holding a private key: Coinbase Agentic Wallets, Privy, Crossmint, Turnkey and OpenClawCash.&lt;/p&gt;

&lt;p&gt;They are not the same kind of thing. Three are wallet products an agent uses directly; two are signing infrastructure you build a wallet on top of. That split decides how much engineering you sign up for, more than any feature list.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short answer
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coinbase Agentic Wallets&lt;/strong&gt; if the agent spends USDC on Base and pays for APIs through x402.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privy&lt;/strong&gt; if you are building your own wallet product and need infrastructure at large scale, with contract allowlists and time windows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crossmint&lt;/strong&gt; if the agent must pay merchants that do not take crypto, through virtual cards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turnkey&lt;/strong&gt; if hardware-isolated signing and signing speed are the hard requirements and you build everything above the key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenClawCash&lt;/strong&gt; if you want a working wallet today on Ethereum, Polygon, Base and Solana mainnets, with weekly and monthly limits, escrow and Polymarket trading, and no wallet code of your own.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Two camps: product or primitive
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Wallet products&lt;/strong&gt; give the agent a wallet it can use straight away: Coinbase Agentic Wallets, Crossmint and OpenClawCash. You set limits, hand over a credential and the agent spends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signing infrastructure&lt;/strong&gt; gives you secure keys and a policy engine; you build the wallet on top. Privy and Turnkey live here. Neither camp is better: the question is whether you want to build a wallet or use one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side by side
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Coinbase Agentic Wallets&lt;/th&gt;
&lt;th&gt;Privy&lt;/th&gt;
&lt;th&gt;Crossmint&lt;/th&gt;
&lt;th&gt;Turnkey&lt;/th&gt;
&lt;th&gt;OpenClawCash&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Wallet product&lt;/td&gt;
&lt;td&gt;Signing infrastructure&lt;/td&gt;
&lt;td&gt;Wallet product&lt;/td&gt;
&lt;td&gt;Signing infrastructure&lt;/td&gt;
&lt;td&gt;Wallet product&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Chains&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Base, Polygon, Solana for sends; trading on Base only&lt;/td&gt;
&lt;td&gt;Ethereum, EVM chains, Solana and more&lt;/td&gt;
&lt;td&gt;EVM chains, Solana, Stellar&lt;/td&gt;
&lt;td&gt;EVM, Solana, Bitcoin, Tron&lt;/td&gt;
&lt;td&gt;Ethereum, Polygon, Base and Solana mainnets, plus testnets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Spending controls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per session and per transaction&lt;/td&gt;
&lt;td&gt;Transfer limits, recipient and contract allowlists, time windows&lt;/td&gt;
&lt;td&gt;Policies enforced onchain&lt;/td&gt;
&lt;td&gt;Policies evaluated in the enclave&lt;/td&gt;
&lt;td&gt;Per-transaction, daily, weekly and monthly limits, address allowlist, testnet-only switch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Payments beyond crypto&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;x402 for paid APIs&lt;/td&gt;
&lt;td&gt;Not built in&lt;/td&gt;
&lt;td&gt;Visa and Mastercard virtual cards&lt;/td&gt;
&lt;td&gt;Not built in&lt;/td&gt;
&lt;td&gt;Escrow payment requests between agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trading&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Token trades on Base, gasless&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Not a focus&lt;/td&gt;
&lt;td&gt;You build it&lt;/td&gt;
&lt;td&gt;Uniswap, Jupiter, bridging through LiFi, Polymarket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent connects via&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CLI, skills, MCP server&lt;/td&gt;
&lt;td&gt;SDKs, agent CLI, OpenClaw skill&lt;/td&gt;
&lt;td&gt;SDKs and APIs&lt;/td&gt;
&lt;td&gt;SDKs and APIs&lt;/td&gt;
&lt;td&gt;OpenClaw skill, MCP server, REST API&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Where each one wins and where it does not
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Coinbase Agentic Wallets&lt;/strong&gt; wins on native x402, so the agent can pay per request or charge for its own API, and on gasless sends and trades on Base. Weaker if you need trading off Base, assets other than USDC, or caps that cover a week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privy&lt;/strong&gt; wins on custody engineering: signing inside trusted execution environments without storing a key whole, with contract allowlists and time windows on top. It is a building block: you write the policies and wallet logic, and its OpenClaw skill needs your own app credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crossmint&lt;/strong&gt; is the only one of the five that hands an agent virtual Visa and Mastercard cards next to stablecoin wallets, so it can pay a merchant that does not take crypto. It is built for payments, not trading or agent-to-agent commerce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turnkey&lt;/strong&gt; keeps keys and policies in secure enclaves and is built for high signing volume, but it is pure infrastructure: you build the wallet and policies on top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenClawCash&lt;/strong&gt; checks every request against per-transaction, daily, weekly and monthly limits, an address allowlist and a testnet-only switch before anything is signed, and logs blocked attempts. Escrow between agents with release, refund and dispute, and Polymarket trading, run on the same wallet and the same policies across Ethereum, Polygon, Base and Solana mainnets. The honest trade-off: keys are encrypted at rest on its servers rather than in hardware enclaves, there is no x402 support today, and policies limit amounts and destinations, not contracts or time windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the agent connects
&lt;/h2&gt;

&lt;p&gt;Coinbase, Privy and OpenClawCash all publish skills that run in OpenClaw. The difference is setup: Privy's skill needs your own Privy app credentials, OpenClawCash needs only a scoped API key. If your agent prefers MCP, OpenClawCash ships one as a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @openclawcash/mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to choose
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build a wallet or use one?&lt;/strong&gt; Build: Privy or Turnkey. Use: Coinbase, Crossmint or OpenClawCash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where does the money go?&lt;/strong&gt; Paid APIs: Coinbase. Card merchants: Crossmint. Other agents and trading venues: OpenClawCash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which chains?&lt;/strong&gt; Base and USDC only: Coinbase covers it. Ethereum, Polygon, Base and Solana together: OpenClawCash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What does a mistake cost?&lt;/strong&gt; A runaway agent makes weekly or monthly limits matter most. A stolen key makes enclave custody matter most.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Full comparisons: &lt;a href="https://openclawcash.com/blog/openclawcash-vs-coinbase-agentic-wallets" rel="noopener noreferrer"&gt;OpenClawCash vs Coinbase Agentic Wallets&lt;/a&gt; and &lt;a href="https://openclawcash.com/blog/openclawcash-vs-privy-agent-wallets" rel="noopener noreferrer"&gt;OpenClawCash vs Privy agent wallets&lt;/a&gt;. For how the layers fit together, see the &lt;a href="https://openclawcash.com/blog/ai-agent-wallet-security-guide" rel="noopener noreferrer"&gt;AI agent wallet security guide&lt;/a&gt;. Start with the &lt;a href="https://openclawcash.com/openclaw-skill-setup" rel="noopener noreferrer"&gt;OpenClawCash skill guide&lt;/a&gt; or the &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;API docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>crypto</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Swap tokens from your agent wallet: quote first, then execute</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Fri, 02 Oct 2026 14:08:55 +0000</pubDate>
      <link>https://dev.to/openclawcash/swap-tokens-from-your-agent-wallet-quote-first-then-execute-2ema</link>
      <guid>https://dev.to/openclawcash/swap-tokens-from-your-agent-wallet-quote-first-then-execute-2ema</guid>
      <description>&lt;p&gt;An agent that holds SOL and owes USDC is stuck: it can send what it holds, but the invoice is in a token it does not hold. Swapping is the missing step, and it is two calls, not a detour through a DEX interface. This is the whole flow over the agent API, with every route and field copied out of the public reference at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Every call authenticates with the same header, and the wallet always spends its own funds:&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;X-Agent-Key: occ_your_api_key
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Get the wallet id
&lt;/h2&gt;

&lt;p&gt;Everything else selects a wallet, so start where the ids are:&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="s2"&gt;"https://openclawcash.com/api/agent/wallets?includeBalances=true"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response lists each wallet with &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;label&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt;, &lt;code&gt;network&lt;/code&gt; and &lt;code&gt;chain&lt;/code&gt;, plus the native balance when you ask for it. Keep the &lt;code&gt;id&lt;/code&gt;, it is what the later calls take.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Quote before anything moves
&lt;/h2&gt;

&lt;p&gt;The quote route prices the swap and signs nothing. It needs &lt;code&gt;X-Agent-Key&lt;/code&gt; like every other agent call, and it is the safe place to look before you commit:&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 &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/quote?network=solana-mainnet"&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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "chain": "solana",
    "walletId": "YUZE66Z",
    "tokenIn": "SOL",
    "tokenOut": "USDC",
    "amountIn": "10000000"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer carries &lt;code&gt;amountOut&lt;/code&gt;, &lt;code&gt;amountOutHuman&lt;/code&gt;, &lt;code&gt;amountIn&lt;/code&gt;, &lt;code&gt;amountInHuman&lt;/code&gt;, &lt;code&gt;route&lt;/code&gt;, &lt;code&gt;feePercent&lt;/code&gt;, &lt;code&gt;dex&lt;/code&gt; and &lt;code&gt;network&lt;/code&gt;. No transaction is built, no fee is taken and nothing is signed.&lt;/p&gt;

&lt;p&gt;On EVM the same route takes the chain as a query parameter instead:&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 &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/quote?network=polygon-mainnet"&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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "walletId": "Q7X2K9P",
    "tokenIn": "WETH",
    "tokenOut": "USDC",
    "amountIn": "100000000000000000"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;amountIn&lt;/code&gt; is in base units in both cases: lamports on Solana, so &lt;code&gt;10000000&lt;/code&gt; is 0.01 SOL, and wei on EVM, so &lt;code&gt;1000000000000000000&lt;/code&gt; is 1 WETH. That is easy to get wrong, which is why the quote hands &lt;code&gt;amountInHuman&lt;/code&gt; and &lt;code&gt;amountOutHuman&lt;/code&gt; back to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Read the policy that will check the swap
&lt;/h2&gt;

&lt;p&gt;Policies are checked before anything is signed, so read them before you are refused:&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://openclawcash.com/api/agent/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each entry pairs a wallet with its policies and their current usage. A &lt;code&gt;daily_spending_limit&lt;/code&gt; comes back with &lt;code&gt;config.amount&lt;/code&gt; and a &lt;code&gt;usage&lt;/code&gt; block holding &lt;code&gt;spent&lt;/code&gt; and &lt;code&gt;limit&lt;/code&gt; for the window, so you can see how much of the cap the swap will consume before you send it.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Execute
&lt;/h2&gt;

&lt;p&gt;Slippage lives here and not on the quote. This is the call that moves funds:&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://openclawcash.com/api/agent/swap &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "chain": "solana",
    "walletId": "YUZE66Z",
    "tokenIn": "SOL",
    "tokenOut": "USDC",
    "amountIn": "10000000",
    "slippage": 0.5
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response gives you &lt;code&gt;txHash&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;dex&lt;/code&gt;, &lt;code&gt;amountOut&lt;/code&gt;, &lt;code&gt;amountOutMin&lt;/code&gt;, &lt;code&gt;fee&lt;/code&gt; and &lt;code&gt;feePercent&lt;/code&gt;. &lt;code&gt;amountOutMin&lt;/code&gt; is the guard that came out of the slippage value you sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Confirm what landed
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://openclawcash.com/api/agent/transactions?walletId=YUZE66Z&amp;amp;chain=solana"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;History merges on-chain and app-recorded rows, and each row carries its own &lt;code&gt;network&lt;/code&gt;, so an EVM wallet can scope to one chain with &lt;code&gt;network=base-mainnet&lt;/code&gt; or merge the bucket with &lt;code&gt;network=all&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to watch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Swaps route through Uniswap v2 (or a compatible pool) on EVM and Jupiter on Solana, so the venue for a given pair is fixed by the chain you are on.&lt;/li&gt;
&lt;li&gt;Spending an ERC-20 on EVM can need &lt;code&gt;POST /api/agent/approve&lt;/code&gt; first, which approves a spender contract for that token. The route is EVM only and it takes &lt;code&gt;tokenAddress&lt;/code&gt;, &lt;code&gt;spender&lt;/code&gt; and &lt;code&gt;amount&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The quote is a price, not an action. Nothing moves until you call the swap, and the price can move between the two calls, which is what the slippage value and &lt;code&gt;amountOutMin&lt;/code&gt; are there for.&lt;/li&gt;
&lt;li&gt;Any valid ERC-20 contract or SPL mint works in wallet operations, not only the tokens the supported-tokens route recommends.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>crypto</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Your Agent Holds USDC on Base. The Invoice Is on Polygon.</title>
      <dc:creator>OpenClaw Cash</dc:creator>
      <pubDate>Thu, 01 Oct 2026 14:02:11 +0000</pubDate>
      <link>https://dev.to/openclawcash/your-agent-holds-usdc-on-base-the-invoice-is-on-polygon-p91</link>
      <guid>https://dev.to/openclawcash/your-agent-holds-usdc-on-base-the-invoice-is-on-polygon-p91</guid>
      <description>&lt;p&gt;Your agent's treasury sits on one chain. The counterparty settles on another. Every other part of the payment flow is automated, and then a human has to move USDC from Base to Polygon by hand while the agent waits.&lt;/p&gt;

&lt;p&gt;There are three ways teams usually patch this, and all three are annoying:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A human bridges the funds each time. Safe, and not autonomous at all.&lt;/li&gt;
&lt;li&gt;A wallet on every chain. It works, but now there are more keys to leak and more balances to sweep.&lt;/li&gt;
&lt;li&gt;Ask the other side to accept a different chain. That is not your call to make.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The cross-chain bridge endpoints in the OpenClawCash API take a fourth path: the wallet stays where it is, the API does the move, and the same policy layer that guards a normal transfer guards the bridge too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quote first, execute second
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;POST /api/agent/bridge/quote&lt;/code&gt; returns a routing quote before anything touches a chain. The quote is routed through LiFi, and the aggregator picks the underlying bridge, announcing it as &lt;code&gt;bridgeName&lt;/code&gt;, so you can see which route and which fee you are agreeing to. The response carries &lt;code&gt;amountOut&lt;/code&gt;, &lt;code&gt;amountOutMin&lt;/code&gt;, &lt;code&gt;providerFeeBaseUnits&lt;/code&gt; and &lt;code&gt;estimatedDurationSeconds&lt;/code&gt;, and the quote expires about 60 seconds after it is issued.&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://openclawcash.com/api/agent/bridge/quote &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;'{
    "walletId": "Q7X2K9P",
    "fromNetwork": "base-mainnet",
    "fromToken": "USDC",
    "toNetwork": "polygon-mainnet",
    "toToken": "USDC",
    "amountIn": "1000000"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;amountIn&lt;/code&gt; is an integer string in base units, and &lt;code&gt;fromNetwork&lt;/code&gt;, &lt;code&gt;fromToken&lt;/code&gt;, &lt;code&gt;toNetwork&lt;/code&gt;, &lt;code&gt;toToken&lt;/code&gt; and &lt;code&gt;amountIn&lt;/code&gt; are all required. &lt;code&gt;slippagePercent&lt;/code&gt; is optional.&lt;/p&gt;

&lt;p&gt;The same call from an agent loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://openclawcash.com/api/agent/bridge/quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-Agent-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;occ_your_api_key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;walletId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Q7X2K9P&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fromNetwork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base-mainnet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fromToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USDC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;toNetwork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;polygon-mainnet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;toToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USDC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;amountIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1000000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quoteId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bridgeName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amountOut&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Execute the quote you accepted
&lt;/h2&gt;

&lt;p&gt;Nothing moves until you send the &lt;code&gt;quoteId&lt;/code&gt; back to &lt;code&gt;POST /api/agent/bridge/execute&lt;/code&gt;. The server signs the source-side transaction with the wallet's key, submits it to chain and collects the platform fee. The agent still only ever holds an API key, never a private key, so a leaked agent environment is not a drained wallet.&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://openclawcash.com/api/agent/bridge/execute &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;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Agent-Key: occ_your_api_key"&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;"Idempotency-Key: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MY_UNIQUE_KEY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&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;'{
    "walletId": "Q7X2K9P",
    "quoteId": "quote_abc123"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send the &lt;code&gt;Idempotency-Key&lt;/code&gt; header so a retry after a timeout cannot fund the same bridge twice. The response gives you &lt;code&gt;bridgeTxId&lt;/code&gt; and &lt;code&gt;sourceTxHash&lt;/code&gt;, which is the moment the source side is real and the destination side is not yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow it to the other chain
&lt;/h2&gt;

&lt;p&gt;A bridge is not finished when the source transaction confirms. &lt;code&gt;GET /api/agent/bridge/status&lt;/code&gt; tracks the rest, keyed by &lt;code&gt;bridgeTxId&lt;/code&gt;, and reports &lt;code&gt;sourceTxHash&lt;/code&gt;, &lt;code&gt;destinationTxHash&lt;/code&gt; and &lt;code&gt;amountReceived&lt;/code&gt; once each side confirms.&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="s2"&gt;"https://openclawcash.com/api/agent/bridge/status?bridgeTxId=btx_789xyz"&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;"X-Agent-Key: occ_your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The states are &lt;code&gt;submitted&lt;/code&gt;, &lt;code&gt;source_confirmed&lt;/code&gt;, &lt;code&gt;destination_confirmed&lt;/code&gt;, &lt;code&gt;completed&lt;/code&gt; and &lt;code&gt;failed&lt;/code&gt;. Poll that endpoint instead of assuming delivery, and write the terminal state into your own ledger when it arrives.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is still rough
&lt;/h2&gt;

&lt;p&gt;Being straight about the limits, because the docs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EVM to EVM is fully supported. EVM and Solana quoting works, but the Solana source-side execute is gated to a follow-up, so do not build a Solana-funded bridge into your critical path yet.&lt;/li&gt;
&lt;li&gt;The quote TTL is short. Quote, then execute immediately, rather than caching a quote between agent steps.&lt;/li&gt;
&lt;li&gt;Bridging answers to the same spending limits, allow-lists and approvals as any other send, checked before anything is signed. Test with a small amount first to see how your policy treats it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full endpoint reference, including the exact request and response fields, is at &lt;a href="https://openclawcash.com/docs" rel="noopener noreferrer"&gt;https://openclawcash.com/docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>crypto</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
