Skip to main content

Intents API

The Intents API lets an agent submit on-chain transactions — transfers, swaps, contract calls — while never having access to the raw private key. The server signs the transaction using keys stored in the vault and broadcasts it through a dedicated RPC for the target chain.

How it works

Agent                       1claw Vault                  Blockchain
│ │ │
│ POST /v1/agents/:id/ │ │
│ transactions │ │
│ { chain, to, value, │ │
│ data, signing_key_path } │ │
│ ─────────────────────────► │ │
│ │ 1. Decrypt private key │
│ │ from vault via HSM │
│ │ 2. Build & sign tx │
│ │ 3. Broadcast via RPC ───► │
│ │ │
│ ◄───────────────────────── │ tx_hash, status │
│ { id, tx_hash, status } │ │
  1. The agent calls POST /v1/agents/:agent_id/transactions with the chain, recipient, value, calldata, and the vault path to the signing key.
  2. The vault decrypts the private key inside the HSM boundary, constructs and signs the transaction, and broadcasts it to the chain's RPC endpoint.
  3. The agent receives an id and tx_hash — it never sees the raw key material.

Enabling the Intents API

Set intents_api_enabled: true when registering or updating an agent:

curl -X POST "https://api.1claw.xyz/v1/agents" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "DeFi Bot",
"intents_api_enabled": true
}'

What changes when enabled

Behaviourintents_api_enabled: falseintents_api_enabled: true
Read api_key, password, etc.AllowedAllowed
Read private_key or ssh_keyAllowedBlocked (403)
Submit proxy transactionsNot availableAllowed
Audit trail per transactionN/AFull trace with tx_id

The enforcement is two-sided: the flag both grants access to the transaction endpoints and blocks direct reads of signing keys through the standard secrets endpoint. This guarantees the agent can only use keys through the proxy.

Submitting a transaction

curl -X POST "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chain": "ethereum",
"to": "0xRecipientAddress",
"value": "1.0",
"data": "0x",
"signing_key_path": "wallets/hot-wallet"
}'

Response

{
"id": "a7e2c...",
"tx_hash": "0xabc123...",
"chain": "ethereum",
"status": "broadcast"
}

Querying transactions

# List all transactions for this agent
curl "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions" \
-H "Authorization: Bearer $AGENT_TOKEN"

# Get a specific transaction
curl "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions/$TX_ID" \
-H "Authorization: Bearer $AGENT_TOKEN"

Transaction simulation (Tenderly)

Every transaction can be simulated before signing. Simulation executes the full transaction against the current chain state in a sandboxed environment, returning decoded traces, balance changes, gas estimates, and human-readable error messages — without consuming real gas.

Standalone simulation

Call the simulate endpoint to preview a transaction without committing:

curl -X POST "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions/simulate" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chain": "base",
"to": "0xRecipientAddress",
"value": "0.5",
"data": "0x",
"signing_key_path": "wallets/hot-wallet"
}'

The response includes:

{
"simulation_id": "sim_a7e2c...",
"status": "success",
"gas_used": 21000,
"balance_changes": [
{ "address": "0xSender...", "token": "ETH", "before": "2.5", "after": "1.99", "change": "-0.51" },
{ "address": "0xRecipient...", "token": "ETH", "before": "0.0", "after": "0.5", "change": "+0.5" }
],
"tenderly_dashboard_url": "https://dashboard.tenderly.co/..."
}

Simulate-then-sign (single call)

Add "simulate_first": true to the standard transaction submission. The server simulates first; if the simulation reverts, it returns HTTP 422 and does not sign or broadcast:

curl -X POST "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chain": "base",
"to": "0xRecipientAddress",
"value": "0.5",
"simulate_first": true
}'

Bundle simulation

Simulate multiple transactions sequentially (e.g. ERC-20 approve followed by a swap):

curl -X POST "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions/simulate-bundle" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transactions": [
{ "chain": "base", "to": "0xToken", "value": "0", "data": "0xapprove..." },
{ "chain": "base", "to": "0xRouter", "value": "0", "data": "0xswap..." }
]
}'

Enforcing simulation

Org admins can require simulation for all agent transactions by setting the intents_api.require_simulation org setting to "true" via PUT /v1/admin/settings/intents_api.require_simulation. When enabled, any transaction submitted without simulate_first: true will be automatically simulated, and reverts will block signing.

EIP-1559 (Type 2) transactions

Set max_fee_per_gas and max_priority_fee_per_gas instead of gas_price to use EIP-1559 fee mode:

curl -X POST "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions" \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chain": "base",
"to": "0xRecipientAddress",
"value": "0.1",
"max_fee_per_gas": "30000000000",
"max_priority_fee_per_gas": "1500000000",
"simulate_first": true
}'

MCP tools

The MCP server provides two transaction tools:

simulate_transaction — simulate without signing:

Tool: simulate_transaction
Args:
chain: "base"
to: "0xRecipientAddress"
value: "0.5"
signing_key_path: "wallets/hot-wallet"

submit_transaction — sign and broadcast (simulation on by default):

Tool: submit_transaction
Args:
chain: "base"
to: "0xRecipientAddress"
value: "0.5"
signing_key_path: "wallets/hot-wallet"
simulate_first: true

Supported chains

The proxy can broadcast transactions to any chain in the registry. All mainnet chains below are configured with dedicated dRPC endpoints for reliable transaction delivery.

Querying chains via API

You can always fetch the live list with GET /v1/chains. The response includes chain_id, rpc_url, explorer_url, and native_currency for every chain.

Mainnet chains (28)

ChainChain IDNative tokenExplorer
Ethereum1ETHetherscan.io
Optimism10ETHoptimistic.etherscan.io
Cronos25CROcronoscan.com
BNB Smart Chain56BNBbscscan.com
Gnosis100xDAIgnosisscan.io
Polygon137POLpolygonscan.com
Sonic146Ssonicscan.org
Fantom250FTMftmscan.com
zkSync Era324ETHexplorer.zksync.io
World Chain480ETHworldscan.org
Metis1088METISandromeda-explorer.metis.io
Polygon zkEVM1101ETHzkevm.polygonscan.com
Moonbeam1284GLMRmoonscan.io
Sei1329SEIseitrace.com
Mantle5000MNTmantlescan.xyz
Kaia8217KAIAkaiascan.io
Base8453ETHbasescan.org
Mode34443ETHmodescan.io
Arbitrum One42161ETHarbiscan.io
Arbitrum Nova42170ETHnova.arbiscan.io
Celo42220CELOceloscan.io
Avalanche C-Chain43114AVAXsnowtrace.io
Linea59144ETHlineascan.build
Berachain80094BERAberascan.com
Blast81457ETHblastscan.io
Taiko167000ETHtaikoscan.io
Scroll534352ETHscrollscan.com
Zora7777777ETHexplorer.zora.energy

Testnet chains

ChainChain IDNative token
Sepolia11155111ETH
Base Sepolia84532ETH

Adding a chain

Admins can add new chains via the admin API:

curl -X POST "https://api.1claw.xyz/v1/admin/chains" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-chain",
"display_name": "My Chain",
"chain_id": 12345,
"rpc_url": "https://rpc.mychain.io",
"explorer_url": "https://explorer.mychain.io",
"native_currency": "MCH"
}'

See the Admin API reference for update and delete endpoints.


Transaction guardrails

Per-agent controls can be set when registering or updating an agent to limit what transactions the proxy will sign:

FieldTypeDescription
tx_allowed_chainsstring[]Restrict to specific chain names (e.g. ["ethereum", "base"]). Empty = all chains allowed.
tx_to_allowliststring[]Restrict recipient addresses. Empty = any address allowed.
tx_max_value_ethstringMaximum value per transaction in ETH (e.g. "1.0"). Null = no per-tx limit.
tx_daily_limit_ethstringRolling 24-hour spend limit in ETH. Null = no daily limit.
curl -X PATCH "https://api.1claw.xyz/v1/agents/$AGENT_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tx_allowed_chains": ["ethereum", "base"],
"tx_to_allowlist": ["0xSafeAddress1", "0xSafeAddress2"],
"tx_max_value_eth": "0.5",
"tx_daily_limit_eth": "5.0"
}'

When a transaction violates any guardrail, the proxy returns 403 Forbidden with a descriptive detail message.


Shroud TEE signing (optional)

When Shroud is deployed, transaction signing moves into a Trusted Execution Environment (AMD SEV-SNP on GKE). The POST /v1/agents/:id/transactions endpoint on shroud.1claw.xyz uses Shroud's own signing engine — private keys are only decrypted inside confidential memory. All other Intents API endpoints (list, get, simulate, simulate-bundle) are proxied to the Vault API.

Both api.1claw.xyz and shroud.1claw.xyz serve the full Intents API. Choose based on your security requirements:

SurfaceSubmitList/Get/SimulateKey isolation
api.1claw.xyzHSM-backed signing (Cloud Run)DirectCloud KMS HSM
shroud.1claw.xyzTEE signing (GKE SEV-SNP)Proxied to Vault APITEE + KMS

Shroud also provides LLM proxy capabilities — see the Shroud guide.

Security model

  • Keys never leave the HSM boundary — the vault decrypts the key, signs the transaction, and zeroes the memory. The plaintext key is never returned to the caller.
  • Full audit trail — every transaction is logged with the agent ID, chain, recipient, value, and resulting tx_hash.
  • Policy enforcement — the agent still needs a policy granting access to the vault path that holds the signing key. The proxy doesn't bypass access control.
  • Transaction guardrails — per-agent chain allowlists, recipient allowlists, per-tx caps, and daily spend limits enforced server-side before signing.
  • Rate limiting — standard rate limits apply to transaction endpoints.

Replay protection

Idempotency-Key header

Submit an Idempotency-Key header (e.g. a UUID) with POST /v1/agents/:id/transactions to prevent duplicate submissions. If the same key is sent within 24 hours, the server returns the cached transaction response instead of signing and broadcasting again.

The SDK and MCP server auto-generate an idempotency key on every submitTransaction call. You can override with your own key for explicit retry control.

ScenarioResponse
First request with key201 Created (normal flow)
Duplicate request (completed)200 OK (cached response)
Duplicate request (in progress)409 Conflict (retry later)
No headerNo idempotency enforcement

Server-side nonce management

When the nonce field is omitted, the server atomically reserves the next nonce per agent+chain+address combination. This prevents nonce collisions when multiple transactions are submitted concurrently. The server tracks the highest nonce used and takes the maximum of its tracked value and the on-chain pending nonce.

Response field gating

By default, the signed_tx field (raw signed transaction hex) is omitted from GET responses to reduce exfiltration risk. Pass ?include_signed_tx=true to include it:

curl "https://api.1claw.xyz/v1/agents/$AGENT_ID/transactions?include_signed_tx=true" \
-H "Authorization: Bearer $AGENT_TOKEN"

The initial POST submission always returns signed_tx for the originating caller.

Best practices

  1. One key per agent — give each agent its own signing key in its own vault path so you can revoke independently.
  2. Set expires_at — register agents with an expiry so leaked API keys have a bounded blast radius.
  3. Use scoped policies — grant the agent access only to the specific vault path containing its signing key, not the entire vault.
  4. Monitor transactions — query GET /v1/agents/:id/transactions regularly or set up audit webhooks.
  5. Use testnets first — store a testnet key (Sepolia, Base Sepolia) and verify the flow before moving to mainnet.