{"openapi":"3.0.3","info":{"title":"Topaz Agent API","version":"0.18.1","description":"Agentic ve(3,3) DeFi execution and strategy API for Topaz Dex on BNB Chain. Non-custodial: builds wallet-ready calldata but never signs or broadcasts transactions.","contact":{"name":"Topaz Dex","url":"https://topazdex.com"}},"servers":[{"url":"https://agents.topazdex.com","description":"Production"}],"components":{"schemas":{"AgentResponse":{"type":"object","properties":{"kind":{"type":"string","enum":["quote","recommendation","built_calldata","approval_needed","error"]},"chainId":{"type":"integer","example":56},"timestamp":{"type":"string","format":"date-time"},"summary":{"type":"string"},"data":{"type":"object"},"transactions":{"type":"array","items":{"$ref":"#/components/schemas/Transaction"}},"risks":{"type":"array","items":{"type":"string"}},"sources":{"type":"array","items":{"type":"string"}}},"required":["kind","chainId","timestamp","summary","data"]},"Transaction":{"type":"object","properties":{"to":{"type":"string","description":"Target contract address"},"data":{"type":"string","description":"Encoded calldata"},"value":{"type":"string","description":"BNB value in wei ('0' for token txs)"},"label":{"type":"string"},"deadline":{"type":"integer"},"slippageBps":{"type":"integer"}},"required":["to","data","value","label"]},"ErrorResponse":{"type":"object","properties":{"kind":{"type":"string","enum":["error"]},"chainId":{"type":"integer"},"timestamp":{"type":"string","format":"date-time"},"summary":{"type":"string","description":"Human-readable error message"},"data":{}}},"QuoteData":{"type":"object","properties":{"bestSource":{"type":"string","enum":["topaz-v2","topaz-v3","none"]},"sellToken":{"type":"string"},"buyToken":{"type":"string"},"sellAmount":{"type":"string"},"topazV2Quote":{"type":"object","nullable":true,"properties":{"available":{"type":"boolean"},"expectedOut":{"type":"string"},"expectedOutHuman":{"type":"string"},"route":{"type":"string"},"priceImpactPct":{"type":"number","nullable":true}}},"topazV3Quote":{"type":"object","nullable":true,"properties":{"available":{"type":"boolean"},"expectedOut":{"type":"string"},"expectedOutHuman":{"type":"string"},"route":{"type":"string"},"priceImpactPct":{"type":"number","nullable":true}}}}},"LpRecommendation":{"type":"object","properties":{"pool":{"type":"string","example":"WBNB/USDT"},"poolAddress":{"type":"string"},"poolType":{"type":"string","enum":["v2-volatile","v2-stable","v3-cl"]},"allocationPct":{"type":"integer"},"totalApr":{"type":"number"},"feeApr":{"type":"number"},"emissionApr":{"type":"number"},"bribeApr":{"type":"number"},"tvlUsd":{"type":"number"},"riskFlags":{"type":"array","items":{"type":"string"}},"reason":{"type":"string"}}},"VoteRecommendation":{"type":"object","properties":{"gauge":{"type":"string"},"pool":{"type":"string"},"poolLabel":{"type":"string"},"weightPct":{"type":"integer"},"expectedBribeApr":{"type":"number"},"expectedFeeApr":{"type":"number"},"expectedTotalVoteApr":{"type":"number"},"reason":{"type":"string"}}},"BribeCampaignPlan":{"type":"object","properties":{"recommendedPool":{"type":"string"},"recommendedPoolType":{"type":"string"},"weeklyBribeBudgetUsd":{"type":"number"},"expectedLpAprRange":{"type":"string"},"recommendedActions":{"type":"array","items":{"type":"string"}}}},"GaugeInfo":{"type":"object","properties":{"pool":{"type":"string"},"poolAddress":{"type":"string"},"gaugeAddress":{"type":"string"},"type":{"type":"string"},"alive":{"type":"boolean"},"stakedTvlUsd":{"type":"number"},"emissionApr":{"type":"number"},"feeApr":{"type":"number"},"bribeApr":{"type":"number"},"totalApr":{"type":"number"},"totalVoteWeight":{"type":"string"},"foundationVoteWeight":{"type":"string"}}}}},"paths":{"/health":{"get":{"summary":"Health check","operationId":"getHealth","responses":{"200":{"description":"Service healthy"}}}},"/status":{"get":{"summary":"Agent status with live protocol stats","operationId":"getStatus","responses":{"200":{"description":"Agent status"}}}},"/agent.json":{"get":{"summary":"Agent identity and capabilities","operationId":"getAgentInfo","responses":{"200":{"description":"Agent metadata"}}}},"/api/chat":{"post":{"summary":"Chat with Topaz Agent (AI-powered)","operationId":"postChat","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Natural language message"},"sessionId":{"type":"string","description":"Session ID for conversation continuity"}}}}}},"responses":{"200":{"description":"Agent response","content":{"application/json":{"schema":{"type":"object","properties":{"response":{"type":"string"},"sessionId":{"type":"string"},"toolsUsed":{"type":"array","items":{"type":"string"}},"stepsUsed":{"type":"integer"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/wallet-agent":{"post":{"summary":"Topaz AI Wallet conversational agent (manages self-custody CL positions)","description":"Backs the Topaz AI Wallet. The caller passes the user's live positions and WBNB-paired pools as `context`; the agent converses and, when ready, returns a semantic `proposal` (zap/exit/claim/rebalance/stake actions) for the wallet to resolve into simulated, user-signed calldata. Never returns calldata itself.","operationId":"postWalletAgent","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message","context"],"properties":{"message":{"type":"string","description":"Natural language message from the user"},"sessionId":{"type":"string","description":"Session ID for conversation continuity"},"context":{"type":"object","required":["userAddress","accountAddress"],"properties":{"userAddress":{"type":"string","description":"User EOA (signer)"},"accountAddress":{"type":"string","description":"Topaz smart account holding the positions"},"positions":{"type":"array","items":{"type":"object"},"description":"User's CL positions in the smart account (staked unless the item carries staked:false)"},"pools":{"type":"array","items":{"type":"object"},"description":"WBNB-paired pools available for new zaps"},"votablePools":{"type":"array","items":{"type":"object"},"description":"Every pool with a live gauge — the complete ve_vote target set. Uncapped and NOT emission-filtered, unlike the deployment lists: a gauge paying nothing yet is still a legal vote. Omit it and vote targets fall back to the gauged entries in pools/v2Pools."}}}}}}}},"responses":{"200":{"description":"Agent reply, optionally with a transaction proposal","content":{"application/json":{"schema":{"type":"object","properties":{"reply":{"type":"string"},"sessionId":{"type":"string"},"proposal":{"type":"object","nullable":true,"properties":{"summary":{"type":"string"},"actions":{"type":"array","items":{"type":"object"}}}}}}}}},"400":{"description":"Missing message or context","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/pools/top":{"get":{"summary":"Top pools by TVL, volume, or APR","operationId":"getTopPools","parameters":[{"name":"sort","in":"query","schema":{"type":"string","enum":["tvl","volume24h","fees24h","apr"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":10}},{"name":"type","in":"query","schema":{"type":"string","enum":["v2","v3","all"]}}],"responses":{"200":{"description":"Pool list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}}}},"/api/gauges/top":{"get":{"summary":"Top active gauges with APR breakdown, vote weights, and emissions","operationId":"getTopGauges","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Gauge list","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentResponse"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GaugeInfo"}}}}]}}}}}}},"/api/swap/quote":{"post":{"summary":"Get best swap quote across v2 and v3","operationId":"postSwapQuote","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sellToken","buyToken","sellAmount"],"properties":{"sellToken":{"type":"string","description":"Token address or symbol (e.g. 'WBNB')"},"buyToken":{"type":"string","description":"Token address or symbol"},"sellAmount":{"type":"string","description":"Amount in human units (e.g. '1.5')"}}}}}},"responses":{"200":{"description":"Swap quote","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentResponse"},{"properties":{"data":{"$ref":"#/components/schemas/QuoteData"}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/swap/build":{"post":{"summary":"Build wallet-ready swap calldata","operationId":"postSwapBuild","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sellToken","buyToken","sellAmount","taker"],"properties":{"sellToken":{"type":"string"},"buyToken":{"type":"string"},"sellAmount":{"type":"string"},"taker":{"type":"string","description":"Wallet address that will sign"},"slippageBps":{"type":"integer","default":100,"description":"Slippage in basis points (100 = 1%)"}}}}}},"responses":{"200":{"description":"Built calldata with transactions array","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/lp/recommend":{"post":{"summary":"Recommend LP positions based on risk and preferences","operationId":"postLpRecommend","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amountUsd":{"type":"number","default":5000},"risk":{"type":"string","enum":["low","moderate","high"]},"preferredTokens":{"type":"array","items":{"type":"string"}},"includeCL":{"type":"boolean","default":true},"minTvlUsd":{"type":"number","description":"Override minimum TVL filter"}}}}}},"responses":{"200":{"description":"LP recommendations","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentResponse"},{"properties":{"data":{"properties":{"recommendations":{"type":"array","items":{"$ref":"#/components/schemas/LpRecommendation"}}}}}}]}}}}}}},"/api/vote/recommend":{"post":{"summary":"Recommend veTOPAZ gauge votes for current epoch","operationId":"postVoteRecommend","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"strategy":{"type":"string","enum":["max-yield","support-protocol","balanced"]},"maxPools":{"type":"integer","default":5}}}}}},"responses":{"200":{"description":"Vote recommendations","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentResponse"},{"properties":{"data":{"properties":{"votes":{"type":"array","items":{"$ref":"#/components/schemas/VoteRecommendation"}}}}}}]}}}}}}},"/api/vote/build":{"post":{"summary":"Build vote calldata for Voter.vote()","operationId":"postVoteBuild","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tokenId","pools","weights","taker"],"properties":{"tokenId":{"type":"string"},"pools":{"type":"array","items":{"type":"string"}},"weights":{"type":"array","items":{"type":"number"}},"taker":{"type":"string"}}}}}},"responses":{"200":{"description":"Built vote calldata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid input or gauge not found"},"403":{"description":"Not approved for veNFT"},"409":{"description":"Already voted or wrong timing"}}}},"/api/bribe/recommend":{"post":{"summary":"Plan a bribe campaign for a token","operationId":"postBribeRecommend","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectToken","budgetUsd"],"properties":{"projectToken":{"type":"string"},"budgetUsd":{"type":"number"},"targetLiquidityUsd":{"type":"number","default":500000},"durationWeeks":{"type":"integer","default":4},"preferredQuoteToken":{"type":"string"}}}}}},"responses":{"200":{"description":"Bribe campaign plan","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentResponse"},{"properties":{"data":{"$ref":"#/components/schemas/BribeCampaignPlan"}}}]}}}}}}},"/api/bribe/build":{"post":{"summary":"Build bribe deposit calldata","operationId":"postBribeBuild","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pool","token","amount","taker"],"properties":{"pool":{"type":"string"},"token":{"type":"string"},"amount":{"type":"string"},"taker":{"type":"string"}}}}}},"responses":{"200":{"description":"Built bribe deposit calldata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}}}},"/api/rewards/build-claim":{"post":{"summary":"Build reward claiming calldata (fees, bribes, emissions, rebase)","operationId":"postRewardsBuildClaim","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tokenId","taker"],"properties":{"tokenId":{"type":"string"},"taker":{"type":"string"},"claimTypes":{"type":"array","items":{"type":"string","enum":["emissions","fees","bribes","rebase"]}}}}}}},"responses":{"200":{"description":"Built claim calldata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}}}},"/api/strategy/weekly":{"get":{"summary":"Weekly ve(3,3) strategy report","operationId":"getWeeklyStrategy","responses":{"200":{"description":"Comprehensive weekly report with protocol stats, top gauges, vote and LP recommendations, recent bribes, and insights"}}}},"/api/ve/locks/{wallet}":{"get":{"summary":"Personal veTOPAZ locks: amount, voting power, votes, claimables, manual-vs-relay status","operationId":"getUserVeLocks","parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"veTOPAZ locks for the wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid wallet address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/positions/{wallet}":{"get":{"summary":"A wallet's Topaz DEX positions: v2/v3 LP, staked/unstaked, in-range status, claimables, value","description":"Public, rate-limited read of on-chain/subgraph position state. Returns v3 CL positions (staked and wallet-held), v2 LP positions (loose and gauge-staked), in-range status, claimable rewards/fees, approximate USD value, and per-source status. Never reports 'no positions' when a source is unavailable — check `data.sourceStatus`.","operationId":"getUserDexPositions","parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"DEX positions for the wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid wallet address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/relays":{"get":{"summary":"List Topaz relays (managed veTOPAZ) with live state and health","operationId":"getRelays","responses":{"200":{"description":"Relay discovery + health","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}}}},"/api/relays/positions/{wallet}":{"get":{"summary":"A wallet's managed veTOPAZ relay positions (share, votes, claimable distribution)","operationId":"getUserRelayPositions","parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Relay positions for the wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid wallet address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/relays/compare":{"get":{"summary":"Compare manual veTOPAZ vs Maxi vs Reward & Distribute and recommend a mode","operationId":"getRelayCompare","parameters":[{"name":"preference","in":"query","schema":{"type":"string"},"description":"e.g. 'growth', 'stable income', 'control', 'low maintenance', 'optimize bribes'"},{"name":"wallet","in":"query","schema":{"type":"string"},"description":"Optional wallet to personalize"}],"responses":{"200":{"description":"Strategy comparison","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid wallet address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/relays/monitor":{"get":{"summary":"Operator relay health + weekly performance summary","operationId":"getRelayMonitor","responses":{"200":{"description":"Relay monitor report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}}}},"/api/relays/monitor/notify":{"post":{"summary":"Run the relay monitor and push alerts to Telegram (admin-gated)","operationId":"postRelayMonitorNotify","description":"Requires the `X-Admin-Secret` header. Sends only when the report is not healthy unless `force` is true.","parameters":[{"name":"X-Admin-Secret","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"force":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"Monitor result and delivery status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"403":{"description":"Missing or invalid admin secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/relays/alerts/{wallet}":{"get":{"summary":"Per-wallet actionable veTOPAZ alerts (claimable, unclaimed, unvoted)","operationId":"getUserRelayAlerts","parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"veTOPAZ alerts for the wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid wallet address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/relays/deposit/build":{"post":{"summary":"Build Voter.depositManaged calldata to put a lock into a relay","operationId":"postRelayDepositBuild","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tokenId","relay","taker"],"properties":{"tokenId":{"type":"string"},"relay":{"type":"string","description":"\"maxi\", \"reward-distribute\", or a relay address"},"taker":{"type":"string"}}}}}},"responses":{"200":{"description":"Built deposit calldata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid input"},"403":{"description":"Not approved for veNFT"},"409":{"description":"Lock ineligible or wrong timing"}}}},"/api/relays/withdraw/build":{"post":{"summary":"Build Voter.withdrawManaged calldata to pull a lock out of its relay","operationId":"postRelayWithdrawBuild","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tokenId","taker"],"properties":{"tokenId":{"type":"string"},"taker":{"type":"string"}}}}}},"responses":{"200":{"description":"Built withdraw calldata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid input"},"403":{"description":"Not approved for veNFT"},"409":{"description":"Not in a relay or same-epoch/window block"}}}},"/api/relays/claim/build":{"post":{"summary":"Build FreeManagedReward.getReward calldata to claim a relay's USDT distribution","operationId":"postRelayClaimBuild","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tokenId","taker"],"properties":{"tokenId":{"type":"string"},"taker":{"type":"string"}}}}}},"responses":{"200":{"description":"Built claim calldata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid input"},"403":{"description":"Not approved for veNFT"},"409":{"description":"Nothing claimable or relay has no distribution"}}}},"/api/agent/auth/nonce":{"post":{"summary":"Mint a single-use SIWE (EIP-4361) sign-in challenge for a wallet","description":"Step 1 of browser wallet-session auth. Requires an allowlisted `Origin`. Returns a domain-bound message for the wallet to sign. Used so frontends can talk to /api/agent/respond directly without a backend proxy.","operationId":"postAgentAuthNonce","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["wallet"],"properties":{"wallet":{"type":"string"},"chainId":{"type":"integer","enum":[56],"default":56}}}}}},"responses":{"200":{"description":"Challenge","content":{"application/json":{"schema":{"type":"object","properties":{"nonce":{"type":"string"},"message":{"type":"string"},"expiresAt":{"type":"string"}}}}}},"400":{"description":"Missing wallet or Origin"},"403":{"description":"Origin/wallet not eligible"},"503":{"description":"Wallet session auth not configured"}}}},"/api/agent/auth/verify":{"post":{"summary":"Verify a signed SIWE challenge and issue a wallet-session JWT","description":"Step 2 of browser wallet-session auth. Returns a Bearer token to send to /api/agent/respond.","operationId":"postAgentAuthVerify","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message","signature"],"properties":{"message":{"type":"string"},"signature":{"type":"string"}}}}}},"responses":{"200":{"description":"Issued session","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"wallet":{"type":"string"},"chainId":{"type":"integer"},"expiresAt":{"type":"string"},"tokenType":{"type":"string"}}}}}},"400":{"description":"Missing message/signature"},"401":{"description":"Invalid/expired challenge or signature"},"503":{"description":"Wallet session auth not configured"}}}},"/api/agent/respond":{"post":{"summary":"Browser wallet-authenticated agent chat (positions-aware, page-context-aware, proposal-capable)","description":"Shared dApp assistant. Auth is a wallet-session Bearer token from /api/agent/auth/verify (EOA or smart-contract wallet via ERC-1271); the subject wallet comes from the verified token (a body `identity.wallet` that disagrees returns 403). Exposes the read-only tool set (getUserDexPositions, getTopPools, quoteSwap, …). For `app: \"topaz_dapp\"`, supplying a `walletContext` whose `userAddress` is the authenticated wallet upgrades the turn to the proposal-capable path: the reply may include a semantic `proposal` (never calldata — the dApp resolves, simulates, and signs it), plus page-aware `suggestions`, `navigation` hotlinks, and `labels`.","operationId":"postAgentRespond","parameters":[{"name":"Authorization","in":"header","required":true,"schema":{"type":"string"},"description":"Bearer <wallet-session JWT>"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["app","message"],"properties":{"app":{"type":"string","enum":["topaz_dapp","topaz_id","ai_wallet","vaults","market_intel","telegram"]},"channel":{"type":"string","enum":["web","telegram","discord","api"],"default":"web"},"message":{"type":"string","maxLength":4000},"sessionId":{"type":"string"},"identity":{"type":"object","properties":{"wallet":{"type":"string"},"chainId":{"type":"integer","enum":[56]},"accountAddress":{"type":"string"}}},"contextHints":{"type":"object","description":"Untrusted UI state (currentPage, routeName, mode, poolAddress, pair, positionId, lockId, gaugeAddress, …)"},"capabilities":{"type":"array","items":{"type":"string"}},"walletContext":{"type":"object","description":"Live wallet/account state (userAddress, accountAddress, positions, pools, balances, veLocks, relays, …) for proposal-capable turns. Honored only for topaz_dapp/ai_wallet when userAddress === the authenticated wallet; validated leniently (a malformed enrichment degrades that field, never drops the item)."}}}}}},"responses":{"200":{"description":"Agent reply, optionally with a semantic transaction proposal + page-aware UX hints","content":{"application/json":{"schema":{"type":"object","properties":{"reply":{"type":"string"},"sessionId":{"type":"string"},"wallet":{"type":"string"},"proposal":{"type":"object","nullable":true,"description":"Semantic action batch (summary + actions[]) for the dApp to resolve, simulate, and sign. Never calldata.","properties":{"summary":{"type":"string"},"actions":{"type":"array","items":{"type":"object"}}}},"labels":{"type":"array","items":{"type":"string","enum":["answer","proposal"]}},"suggestions":{"type":"array","items":{"type":"string"},"description":"Page-aware starter chips (topaz_dapp only)."},"navigation":{"type":"array","items":{"type":"object","properties":{"to":{"type":"string"},"label":{"type":"string"},"reason":{"type":"string"}}},"description":"App-relative hotlinks to the proposed actions' review pages (topaz_dapp only; empty on plain answer turns)."},"toolsUsed":{"type":"array","items":{"type":"string"}},"stepsUsed":{"type":"integer"}}}}}},"400":{"description":"Invalid request"},"401":{"description":"Missing/invalid wallet session"},"403":{"description":"Body wallet does not match session"},"503":{"description":"Wallet session auth not configured"}}}}}}