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" }
}
FieldTypeNotes
promptstringRequired, ≤ 2000 chars.
balancesarrayRequired, 1–50 rows of { token, balance }. balance is a decimal string (bigint-safe at the HTTP boundary). Unknown tokens → 400.
contextobjectuserAddress + privateTreasuryAddress.
policyobject{ 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": 
}
FieldNotes
summaryPrivacy-minimized portfolio (aggregates only).
proposalValidated structured proposal incl. optional insight.
verdictDeterministic policy result; amountBaseUnits is a decimal string.
policyEffective guardrail to re-run client-side before execution.
addresses.verificationprivy (server-verified) or client-claimed.
proposalExpiresAtms 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 constraints are rejected.

Error states

StatusCause
400Invalid body, prompt, balances, unsupported token, or out-of-bounds policy.
422The AI produced an invalid/unsupported proposal.
502AI provider not configured, analysis failed, or prices could not be resolved.
429Rate 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).