ORRANGE / Developer
API Reference
The treasury analysis endpoint. It is the only AI-facing API in the core product.
POST /api/ai/analyze
Analyzes a treasury prompt against the user’s private balances, returns a structured proposal and a deterministic policy verdict. Authorization is optional: a valid Privy session JWT (Bearer) enables server-verified addresses; without it, addresses are treated as client-claimed and non-authoritative.
Request
POST /api/ai/analyze
Content-Type: application/json
{
"prompt": "Make my treasury safer.",
"balances": [ { "token": "0x…", "balance": "500000000000000000000" } ],
"context": {
"userAddress": "0x…",
"privateTreasuryAddress": "0x…"
},
"policy": { "preset": "balanced" }
}| Field | Type | Notes |
|---|---|---|
prompt | string | Required, ≤ 2000 chars. |
balances | array | Required, 1–50 rows of { token, balance }. balance is a decimal string (bigint-safe at the HTTP boundary). Unknown tokens → 400. |
context | object | userAddress + privateTreasuryAddress. |
policy | object | { preset, custom? }. Preset: conservative | balanced | flexible | custom. Custom limits are bounds-validated server-side. |
Response
{
"summary": { "totalUsd": 183.16, "positions": [ … ] },
"proposal": {
"intent": "rebalance",
"reason": "Reduce concentration.",
"action": { "type": "private_transfer", … },
"insight": { "diagnosis": "…", … }
},
"verdict": { "allowed": true, "checks": [ … ], "amountBaseUnits": "100000000000000000000" },
"policy": { … effective guardrail … },
"addresses": { "verification": "privy" },
"trust": { … },
"proposalExpiresAt": …
}| Field | Notes |
|---|---|
summary | Privacy-minimized portfolio (aggregates only). |
proposal | Validated structured proposal incl. optional insight. |
verdict | Deterministic policy result; amountBaseUnits is a decimal string. |
policy | Effective guardrail to re-run client-side before execution. |
addresses.verification | privy (server-verified) or client-claimed. |
proposalExpiresAt | ms epoch; proposals expire after 120 s. |
Validation rules
- Prompt required, ≤ 2000 chars.
- Balances 1–50; every token must be a configured supported token; balances must be non-negative decimal strings.
- Policy presets must be known; custom limits must be within bounds (floor 0–$1M, cap 1–100%, tx $1–$10M).
- Model output is schema-validated; model-injected
constraintsare rejected.
Error states
| Status | Cause |
|---|---|
400 | Invalid body, prompt, balances, unsupported token, or out-of-bounds policy. |
422 | The AI produced an invalid/unsupported proposal. |
502 | AI provider not configured, analysis failed, or prices could not be resolved. |
429 | Rate limit exceeded. |
Rate limits
An in-memory sliding window allows 20 requests / 60s per IP (best-effort; not a security boundary).
Security considerations
- The server fetches fresh prices and rebuilds the portfolio itself.
- Destinations come only from the verified user + server allowlist; the AI cannot add one.
- Addresses are server-verified when a valid Privy session is presented.
- The response verdict is advisory; real execution re-checks state client-side.
This is the only AI-facing API in the core product. There is no OpenAPI spec — the request and response above match the implementation exactly (
src/app/api/ai/analyze/route.ts).