Treasury Spend Policies
Spend policies constrain treasury wallet sends and swaps before the server signs. Platform developers set app-level defaults; optional per-user overrides apply to individual connected users.
Full field reference and examples: Embedded wallets — Spend policies.
Quick reference
| Endpoint | Who | Purpose |
|---|---|---|
POST /v1/platform/apps/{id}/spend-policies | plt_ or user JWT | App-level default |
GET /v1/platform/apps/{id}/spend-policies | plt_ or user JWT | List app policies |
PUT /v1/platform/connections/{id}/spend-policy | plt_ or user JWT | Per-user override |
GET /v1/treasury/wallets/spend-policy | User JWT | Effective policy for caller |
DELETE /v1/platform/apps/{id}/spend-policies/{pid} | plt_ or user JWT | Deactivate policy |
Effective policy resolution
- Per-user override (most recently updated active row for that user)
- App-level default (
user_id = null) - No policy → unrestricted (subject to step-up auth only)
Override replaces the app default — fields are not merged.
User-facing read
curl "https://api.1claw.xyz/v1/treasury/wallets/spend-policy" \
-H "Authorization: Bearer $USER_JWT"
Response:
{
"policy": {
"max_value_per_tx_eth": "0.1",
"daily_limit_eth": "1.0",
"allowed_chains": ["ethereum", "base"],
"to_allowlist": [],
"is_active": true
}
}
Or { "policy": null } when no policy applies.
SDK
// Platform operator
await platform.platform.createSpendPolicy(appId, {
max_value_per_tx_eth: "0.1",
daily_limit_eth: "1.0",
allowed_chains: ["ethereum", "base"],
});
// End-user effective policy
const { data } = await userClient.treasuryWallets.getEffectiveSpendPolicy();
// data.policy may be null
SDK response shape
The HTTP API wraps the policy in { "policy": ... }. The SDK getEffectiveSpendPolicy() returns the inner policy object directly when present.
Enforcement
validate_wallet_send() runs on:
POST /v1/treasury/wallets/{chain}/sendPOST /v1/treasury/wallets/{chain}/swap
Violations return 403 with a descriptive detail message. Sends and swaps are recorded in wallet_send_ledger for rolling 24-hour limits.