{"openapi":"3.1.0","info":{"title":"Project Zero Agent API","version":"0.1.0","description":"Agent-facing REST surface for the Project Zero lending protocol on Solana. All transaction endpoints return UNSIGNED base64 transactions — the caller's wallet signs; this service never holds keys. The same capabilities are available over MCP at POST /mcp."},"servers":[{"url":"https://ai.0.xyz"}],"paths":{"/v1/banks":{"get":{"operationId":"getBanks","summary":"List lending banks with rates, sizes, weights, and e-mode","parameters":[{"name":"venue","in":"query","schema":{"type":"string"},"description":"P0 | Kamino | Drift | JupLend (case-insensitive)"},{"name":"mint","in":"query","schema":{"type":"string"},"description":"Token mint address (base58)"},{"name":"symbol","in":"query","schema":{"type":"string"},"description":"Token symbol, case-insensitive"},{"name":"include_inactive","in":"query","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Banks list","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"_meta":{"type":"object","properties":{"cached_at":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Upstream snapshot time, unix ms — oldest of the composed sources"},"source":{"type":"string","const":"monitor"},"max_age_sec":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Data is refreshed at most this often"}},"required":["cached_at","source","max_age_sec"],"additionalProperties":false},"bank_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"banks":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","description":"Bank address (base58). Pass this as `bank` to action tools/endpoints."},"symbol":{"type":"string","description":"Token symbol, e.g. \"USDC\""},"name":{"type":"string","description":"Token name, e.g. \"USD Coin\""},"venue":{"type":"string","description":"Lending venue backing this bank: \"P0\" | \"Kamino\" | \"Drift\" | \"JupLend\""},"asset_group":{"type":"string","description":"Asset bucket, e.g. \"stablecoins\", \"sol-lst\", \"governance\""},"mint":{"type":"string","description":"Token mint address (base58)"},"mint_decimals":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Token decimals"},"price_usd":{"type":"string","description":"Oracle price in USD, decimal string"},"asset_tag":{"type":"string","enum":["default","sol","staked","kamino","drift","solend","juplend","unknown"],"description":"Asset class; \"staked\" banks are not actionable via this service in v1"},"risk_tier":{"type":"string","description":"\"Collateral\" (usable as collateral) or \"Isolated\""},"operational_state":{"type":"string","description":"\"Operational\" | \"Paused\" | \"ReduceOnly\" — only Operational banks accept new actions"},"rates":{"type":"object","properties":{"deposit_apy_pct":{"type":"number","description":"Base deposit APY in percent (4.2 = 4.2% APY), venue-correct"},"borrow_apy_pct":{"type":"number","description":"Base borrow APY in percent"},"utilization_pct":{"type":"number","description":"Utilization in percent (0-100)"},"lending_emissions_apy_pct":{"type":"number","description":"Extra APY from active lending emissions, percent (0 when none)"},"borrowing_emissions_apy_pct":{"type":"number","description":"Emissions APY paid to borrowers, percent (0 when none)"},"total_deposit_apy_pct":{"type":"number","description":"deposit_apy_pct + lending_emissions_apy_pct"},"total_borrow_apy_pct":{"type":"number","description":"Net borrow cost: borrow_apy_pct - borrowing_emissions_apy_pct"}},"required":["deposit_apy_pct","borrow_apy_pct","utilization_pct","lending_emissions_apy_pct","borrowing_emissions_apy_pct","total_deposit_apy_pct","total_borrow_apy_pct"],"additionalProperties":false},"size":{"type":"object","properties":{"deposits_usd":{"type":"string","description":"Total deposits, USD decimal string"},"borrows_usd":{"type":"string","description":"Total borrows, USD decimal string"},"available_liquidity_usd":{"type":"string","description":"Withdrawable/borrowable liquidity in the bank, USD decimal string"},"deposit_limit_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Deposit cap, USD decimal string; null = uncapped"},"borrow_limit_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Borrow cap, USD decimal string; null = uncapped"},"deposit_capacity_remaining_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Remaining room under the deposit cap, USD decimal string; null = uncapped"},"borrow_capacity_remaining_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Remaining room under the borrow cap, USD decimal string; null = uncapped"}},"required":["deposits_usd","borrows_usd","available_liquidity_usd","deposit_limit_usd","borrow_limit_usd","deposit_capacity_remaining_usd","borrow_capacity_remaining_usd"],"additionalProperties":false},"weights":{"type":"object","properties":{"asset_weight_init":{"type":"number","description":"Initial collateral weight (0-1); deposits count at this fraction for new borrows"},"asset_weight_maint":{"type":"number","description":"Maintenance collateral weight (0-1)"},"liability_weight_init":{"type":"number","description":"Initial liability weight (>=1)"},"liability_weight_maint":{"type":"number","description":"Maintenance liability weight (>=1)"}},"required":["asset_weight_init","asset_weight_maint","liability_weight_init","liability_weight_maint"],"additionalProperties":false},"emode":{"anyOf":[{"type":"object","properties":{"tag":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"This bank's e-mode tag (as a liability)"},"entries":{"type":"array","items":{"type":"object","properties":{"collateral_bank_emode_tag":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"e-mode tag of the collateral bank this override applies to"},"asset_weight_init":{"type":"number","description":"Overridden initial collateral weight"},"asset_weight_maint":{"type":"number","description":"Overridden maintenance collateral weight"}},"required":["collateral_bank_emode_tag","asset_weight_init","asset_weight_maint"],"additionalProperties":false}}},"required":["tag","entries"],"additionalProperties":false},{"type":"null"}],"description":"When borrowing this bank against collateral whose tag matches an entry, the entry's better weights apply. null = no e-mode."},"positions":{"type":"object","properties":{"lenders":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Open lending positions"},"borrowers":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Open borrowing positions"}},"required":["lenders","borrowers"],"additionalProperties":false}},"required":["address","symbol","name","venue","asset_group","mint","mint_decimals","price_usd","asset_tag","risk_tier","operational_state","rates","size","weights","emode","positions"],"additionalProperties":false}}},"required":["_meta","bank_count","banks"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/strategies":{"get":{"operationId":"getStrategies","summary":"Ranked leveraged yield strategies (rate-arb loops + directional)","parameters":[{"name":"group","in":"query","schema":{"type":"string"},"description":"stablecoins | sol_lst | sol | eth | btc | jlp"},{"name":"direction","in":"query","schema":{"type":"string","enum":["long","short"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Strategies, best first","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"_meta":{"type":"object","properties":{"cached_at":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Upstream computation time, unix ms"},"source":{"type":"string","const":"monitor"},"max_age_sec":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["cached_at","source","max_age_sec"],"additionalProperties":false},"strategy_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Total strategies matching the filter (before `limit` truncation)"},"strategies":{"type":"array","items":{"type":"object","properties":{"group":{"type":"string","description":"\"stablecoins\" | \"sol_lst\" (rate-arb loops) or a directional asset: \"sol\" | \"eth\" | \"btc\" | \"jlp\""},"direction":{"anyOf":[{"type":"string","enum":["long","short"]},{"type":"null"}],"description":"Directional exposure; null for rate-arbitrage loop strategies"},"supply":{"type":"object","properties":{"bank":{"type":"string","description":"Bank address (base58) for this leg"},"symbol":{"type":"string"},"mint":{"type":"string"},"venue":{"type":"string","description":"Venue name matching /v1/banks: \"P0\" | \"Kamino\" | \"Drift\" | \"JupLend\""}},"required":["bank","symbol","mint","venue"],"additionalProperties":false,"description":"The asset deposited (the supply/collateral leg)"},"borrow":{"type":"object","properties":{"bank":{"type":"string","description":"Bank address (base58) for this leg"},"symbol":{"type":"string"},"mint":{"type":"string"},"venue":{"type":"string","description":"Venue name matching /v1/banks: \"P0\" | \"Kamino\" | \"Drift\" | \"JupLend\""}},"required":["bank","symbol","mint","venue"],"additionalProperties":false,"description":"The asset borrowed against it"},"rates":{"type":"object","properties":{"supply_apy_pct":{"type":"number","description":"Total supply-leg APY in percent, including native yield and emissions"},"borrow_apy_pct":{"type":"number","description":"Total borrow-leg cost APY in percent, including native yield and emissions"},"supply_native_apy_pct":{"type":"number","description":"Native (e.g. staking) yield portion of the supply APY"},"borrow_native_apy_pct":{"type":"number","description":"Native yield portion of the borrow APY"},"supply_emissions_apy_pct":{"type":"number","description":"Emissions portion of the supply APY"},"borrow_emissions_apy_pct":{"type":"number","description":"Emissions portion of the borrow APY"},"net_apy_base_pct":{"type":"number","description":"Net APY at 1x (no leverage), percent"},"net_apy_at_max_leverage_pct":{"type":"number","description":"Net APY at max_leverage, percent"}},"required":["supply_apy_pct","borrow_apy_pct","supply_native_apy_pct","borrow_native_apy_pct","supply_emissions_apy_pct","borrow_emissions_apy_pct","net_apy_base_pct","net_apy_at_max_leverage_pct"],"additionalProperties":false},"max_leverage":{"type":"number","description":"Maximum achievable leverage for this pair"},"available_strategy_size_usd":{"type":"string","description":"Remaining deployable capacity for this strategy, USD decimal string"},"capacity_is_estimate":{"type":"boolean","description":"true when capacity is a proxy estimate rather than an exact figure"},"binding_constraint":{"type":"string","description":"What limits capacity, e.g. \"deposit_cap\", \"borrow_cap\", \"rate_convergence\", \"liquidity\""},"emode_applied":{"type":"boolean","description":"Whether e-mode weight overrides apply to this pair"},"capacity_adjusted_score":{"type":"number","description":"Ranking score (higher = better yield weighted by deployable size) — the list is sorted by this"}},"required":["group","direction","supply","borrow","rates","max_leverage","available_strategy_size_usd","capacity_is_estimate","binding_constraint","emode_applied","capacity_adjusted_score"],"additionalProperties":false}}},"required":["_meta","strategy_count","strategies"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/wallet/{address}":{"get":{"operationId":"getWallet","summary":"Wallet token holdings with USD values","parameters":[{"name":"address","in":"path","required":true,"description":"Wallet public key (base58)","schema":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"}}],"responses":{"200":{"description":"Holdings, sorted by value","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"_meta":{"type":"object","properties":{"cached_at":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Fetch time, unix ms; upstream caches ~30s"},"source":{"type":"string","const":"app"},"max_age_sec":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["cached_at","source","max_age_sec"],"additionalProperties":false},"wallet":{"type":"string","description":"The wallet address queried (base58)"},"total_value_usd":{"type":"string","description":"Sum of all token values, USD decimal string"},"token_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tokens":{"type":"array","items":{"type":"object","properties":{"mint":{"type":"string","description":"Token mint (base58). Native SOL is reported under the wrapped-SOL mint with is_native_sol=true."},"symbol":{"type":"string","description":"\"SOL\" = native SOL; \"WSOL\" = wrapped SOL token accounts"},"name":{"type":"string"},"is_native_sol":{"type":"boolean","description":"true for the native SOL balance entry"},"decimals":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"amount_ui":{"type":"number","description":"Balance in UI token units (1.5 = 1.5 tokens)"},"amount_base_units":{"type":"string","description":"Exact balance in base units (integer string)"},"price_usd":{"type":"string","description":"Token price in USD, decimal string"},"value_usd":{"type":"string","description":"Position value in USD, decimal string"}},"required":["mint","symbol","name","is_native_sol","decimals","amount_ui","amount_base_units","price_usd","value_usd"],"additionalProperties":false},"description":"Sorted by value_usd descending; tokens unknown to Jupiter are omitted"}},"required":["_meta","wallet","total_value_usd","token_count","tokens"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/account/{address}":{"get":{"operationId":"getAccount","summary":"Positions, health, and capacity (fresh on-chain compute)","parameters":[{"name":"address","in":"path","required":true,"description":"Wallet address (returns all its accounts) or marginfi account address","schema":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"}},{"name":"borrow_bank","in":"query","schema":{"type":"string"},"description":"Bank address to compute max borrow for"}],"responses":{"200":{"description":"Account read","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"_meta":{"type":"object","properties":{"computed_at":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Computation time, unix ms — account state is fetched fresh from RPC"},"source":{"type":"string","const":"rpc"},"oracle_max_age_sec":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Market context (banks/prices) is at most this old"}},"required":["computed_at","source","oracle_max_age_sec"],"additionalProperties":false},"query":{"type":"string","description":"The address that was queried"},"resolved_as":{"type":"string","enum":["account","authority"],"description":"\"account\" = query was a marginfi account address; \"authority\" = query was a wallet, all its accounts are returned"},"account_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"accounts":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","description":"Marginfi account address (base58). SAVE THIS — action tools take it as `account`."},"authority":{"type":"string","description":"The wallet that owns this account"},"health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false},"equity":{"type":"object","properties":{"total_assets_usd":{"type":"string","description":"Unweighted total assets, USD"},"total_liabilities_usd":{"type":"string"},"net_value_usd":{"type":"string","description":"Assets minus liabilities, USD"}},"required":["total_assets_usd","total_liabilities_usd","net_value_usd"],"additionalProperties":false},"net_apy_pct":{"type":"number","description":"Blended APY across all positions, percent (negative = paying more than earning)"},"emode_active":{"type":"boolean","description":"Whether e-mode weight overrides are currently active"},"positions":{"type":"array","items":{"type":"object","properties":{"bank":{"type":"string","description":"Bank address (base58) — pass as `bank` to action tools"},"symbol":{"type":"string"},"mint":{"type":"string"},"venue":{"type":"string","description":"\"P0\" | \"Kamino\" | \"Drift\" | \"JupLend\""},"side":{"type":"string","enum":["lend","borrow"],"description":"lend = deposited collateral; borrow = debt"},"amount_ui":{"type":"number","description":"Position size in UI token units of the underlying"},"amount_usd":{"type":"string","description":"Position value in USD, decimal string"},"apy_pct":{"type":"number","description":"Current bank APY for this side, percent (earned for lend, paid for borrow)"},"liquidation_price_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Price of this asset at which the account becomes liquidatable; null when not applicable (e.g. no debt)"},"max_withdraw_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"For lend positions: how much can be withdrawn right now (health-, liquidity-, and venue-capped — the same math the withdraw builder enforces). null for borrow positions."}},"required":["bank","symbol","mint","venue","side","amount_ui","amount_usd","apy_pct","liquidation_price_usd","max_withdraw_ui"],"additionalProperties":false}},"max_borrow":{"anyOf":[{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"type":"string"},"max_borrow_ui":{"type":"number","description":"Max borrowable now in UI units — same math the borrow builder enforces (0.92 volatility factor)"}},"required":["bank","symbol","max_borrow_ui"],"additionalProperties":false},{"type":"null"}],"description":"Populated only when a borrow_bank was passed in the request"}},"required":["address","authority","health","equity","net_apy_pct","emode_active","positions","max_borrow"],"additionalProperties":false},"description":"Empty when the wallet has no marginfi account yet — create one to start"}},"required":["_meta","query","resolved_as","account_count","accounts"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/health/{account}":{"get":{"operationId":"getHealth","summary":"Light health check for one account","parameters":[{"name":"account","in":"path","required":true,"description":"Marginfi account address, or a wallet owning exactly one account","schema":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"}}],"responses":{"200":{"description":"Health summary"},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/activity/{authority}":{"get":{"operationId":"getActivity","summary":"Recent protocol actions for a wallet (indexer-lagged)","parameters":[{"name":"authority","in":"path","required":true,"description":"Wallet (authority) address","schema":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"next_cursor from a previous page"}],"responses":{"200":{"description":"Activity list, newest first","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"_meta":{"type":"object","properties":{"source":{"type":"string","const":"monitor"},"note":{"type":"string","description":"Freshness caveat"}},"required":["source","note"],"additionalProperties":false},"authority":{"type":"string"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Pass as `cursor` to fetch the next page; null = no more"},"activities":{"type":"array","items":{"type":"object","properties":{"signature":{"type":"string","description":"Transaction signature — verify on-chain or in an explorer"},"action":{"type":"string","description":"\"deposit\" | \"borrow\" | \"repay\" | \"withdraw\" | ..."},"account":{"type":"string","description":"Marginfi account address the action touched"},"timestamp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Unix seconds"},"bank":{"type":"string"},"symbol":{"type":"string"},"mint":{"type":"string"},"amount_ui":{"type":"string","description":"Amount in UI token units, decimal string"},"amount_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"USD value at the time, decimal string; null when unpriced"}},"required":["signature","action","account","timestamp","bank","symbol","mint","amount_ui","amount_usd"],"additionalProperties":false},"description":"Newest first"}},"required":["_meta","authority","count","next_cursor","activities"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/create-account":{"post":{"operationId":"buildCreateAccountTx","summary":"Build a create-account transaction","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"authority":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"The wallet that will own and sign for the new account"}},"required":["authority"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"action":{"type":"string"},"authority":{"type":"string","description":"The wallet that must SIGN and submit (echoed)"},"account":{"type":"string","description":"The marginfi account acted on (or to be created). SAVE THIS for subsequent calls."},"bank":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bank acted on (echoed); null for create_account"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Amount in UI token units (echoed)"},"submit":{"type":"string","enum":["sequential","bundle"],"description":"How to submit: \"sequential\" = sign and send in array order, waiting for each to confirm; \"bundle\" = ALL transactions must be signed with the returned blockhash and submitted together as ONE atomic Jito bundle — sending them one by one will fail or leave a half-open position"},"leverage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Target leverage for loop actions; null otherwise"},"legs":{"anyOf":[{"type":"object","properties":{"deposit":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false},"borrow":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false}},"required":["deposit","borrow"],"additionalProperties":false},{"type":"null"}],"description":"Per-leg sizing for flash-loan actions (loop / close_position); null otherwise"},"swap":{"anyOf":[{"type":"object","properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregator that won the route, e.g. \"JUPITER\" or \"TITAN\""},"in_amount_ui":{"type":"number","description":"Swap input in UI units of the input token"},"out_amount_ui":{"type":"number","description":"Quoted swap output (UI units)"},"min_out_amount_ui":{"type":"number","description":"Guaranteed minimum output after slippage — the deposit is sized to this"},"price_impact_pct":{"anyOf":[{"type":"number"},{"type":"null"}]},"slippage_bps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["provider","in_amount_ui","out_amount_ui","min_out_amount_ui","price_impact_pct","slippage_bps"],"additionalProperties":false},{"type":"null"}],"description":"Swap route inside the flash loan; null when no swap"},"bridge_mint":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when the loop had to route through a bridge token (two-hop); null otherwise"},"transactions":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string","description":"UNSIGNED base64-encoded Solana v0 transaction — sign with the authority wallet and submit"},"type":{"type":"string","description":"Machine tag for this transaction's role, e.g. \"CRANK\", \"DEPOSIT\""},"label":{"type":"string","description":"Human-readable label"}},"required":["base64","type","label"],"additionalProperties":false},"description":"Sign and submit per `submit`: in array order (sequential) or as one atomic bundle"},"action_tx_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Index of the main action tx; earlier entries are oracle cranks that must land first"},"blockhash":{"type":"object","properties":{"value":{"type":"string"},"last_valid_block_height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Transactions expire past this block height (~60s) — rebuild if expired"}},"required":["value","last_valid_block_height"],"additionalProperties":false},"simulation":{"type":"object","properties":{"success":{"type":"boolean","const":true,"description":"Builds are returned only when the preview simulation succeeded"},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false,"description":"The account's health AFTER this action lands"},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking risk warnings — surface these to the user before signing"}},"required":["success","post_health","warnings"],"additionalProperties":false}},"required":["action","authority","account","bank","symbol","amount_ui","submit","leverage","legs","swap","bridge_mint","transactions","action_tx_index","blockhash","simulation"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/deposit":{"post":{"operationId":"buildDepositTx","summary":"Build a deposit (auto-creates an account for first-timers)","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"authority":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"The signing wallet (base58)"},"account":{"description":"Marginfi account; required if the wallet owns several","type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Bank address from p0_get_banks / GET /v1/banks"},"amount":{"type":"number","exclusiveMinimum":0,"description":"Amount in UI token units (1.5 = 1.5 tokens)"}},"required":["authority","bank","amount"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"action":{"type":"string"},"authority":{"type":"string","description":"The wallet that must SIGN and submit (echoed)"},"account":{"type":"string","description":"The marginfi account acted on (or to be created). SAVE THIS for subsequent calls."},"bank":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bank acted on (echoed); null for create_account"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Amount in UI token units (echoed)"},"submit":{"type":"string","enum":["sequential","bundle"],"description":"How to submit: \"sequential\" = sign and send in array order, waiting for each to confirm; \"bundle\" = ALL transactions must be signed with the returned blockhash and submitted together as ONE atomic Jito bundle — sending them one by one will fail or leave a half-open position"},"leverage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Target leverage for loop actions; null otherwise"},"legs":{"anyOf":[{"type":"object","properties":{"deposit":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false},"borrow":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false}},"required":["deposit","borrow"],"additionalProperties":false},{"type":"null"}],"description":"Per-leg sizing for flash-loan actions (loop / close_position); null otherwise"},"swap":{"anyOf":[{"type":"object","properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregator that won the route, e.g. \"JUPITER\" or \"TITAN\""},"in_amount_ui":{"type":"number","description":"Swap input in UI units of the input token"},"out_amount_ui":{"type":"number","description":"Quoted swap output (UI units)"},"min_out_amount_ui":{"type":"number","description":"Guaranteed minimum output after slippage — the deposit is sized to this"},"price_impact_pct":{"anyOf":[{"type":"number"},{"type":"null"}]},"slippage_bps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["provider","in_amount_ui","out_amount_ui","min_out_amount_ui","price_impact_pct","slippage_bps"],"additionalProperties":false},{"type":"null"}],"description":"Swap route inside the flash loan; null when no swap"},"bridge_mint":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when the loop had to route through a bridge token (two-hop); null otherwise"},"transactions":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string","description":"UNSIGNED base64-encoded Solana v0 transaction — sign with the authority wallet and submit"},"type":{"type":"string","description":"Machine tag for this transaction's role, e.g. \"CRANK\", \"DEPOSIT\""},"label":{"type":"string","description":"Human-readable label"}},"required":["base64","type","label"],"additionalProperties":false},"description":"Sign and submit per `submit`: in array order (sequential) or as one atomic bundle"},"action_tx_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Index of the main action tx; earlier entries are oracle cranks that must land first"},"blockhash":{"type":"object","properties":{"value":{"type":"string"},"last_valid_block_height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Transactions expire past this block height (~60s) — rebuild if expired"}},"required":["value","last_valid_block_height"],"additionalProperties":false},"simulation":{"type":"object","properties":{"success":{"type":"boolean","const":true,"description":"Builds are returned only when the preview simulation succeeded"},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false,"description":"The account's health AFTER this action lands"},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking risk warnings — surface these to the user before signing"}},"required":["success","post_health","warnings"],"additionalProperties":false}},"required":["action","authority","account","bank","symbol","amount_ui","submit","leverage","legs","swap","bridge_mint","transactions","action_tx_index","blockhash","simulation"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/borrow":{"post":{"operationId":"buildBorrowTx","summary":"Build a borrow (guardrail-capped)","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"authority":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"The signing wallet (base58)"},"account":{"description":"Marginfi account; required if the wallet owns several","type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Bank address from p0_get_banks / GET /v1/banks"},"amount":{"type":"number","exclusiveMinimum":0,"description":"Amount in UI token units (1.5 = 1.5 tokens)"}},"required":["authority","bank","amount"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"action":{"type":"string"},"authority":{"type":"string","description":"The wallet that must SIGN and submit (echoed)"},"account":{"type":"string","description":"The marginfi account acted on (or to be created). SAVE THIS for subsequent calls."},"bank":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bank acted on (echoed); null for create_account"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Amount in UI token units (echoed)"},"submit":{"type":"string","enum":["sequential","bundle"],"description":"How to submit: \"sequential\" = sign and send in array order, waiting for each to confirm; \"bundle\" = ALL transactions must be signed with the returned blockhash and submitted together as ONE atomic Jito bundle — sending them one by one will fail or leave a half-open position"},"leverage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Target leverage for loop actions; null otherwise"},"legs":{"anyOf":[{"type":"object","properties":{"deposit":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false},"borrow":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false}},"required":["deposit","borrow"],"additionalProperties":false},{"type":"null"}],"description":"Per-leg sizing for flash-loan actions (loop / close_position); null otherwise"},"swap":{"anyOf":[{"type":"object","properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregator that won the route, e.g. \"JUPITER\" or \"TITAN\""},"in_amount_ui":{"type":"number","description":"Swap input in UI units of the input token"},"out_amount_ui":{"type":"number","description":"Quoted swap output (UI units)"},"min_out_amount_ui":{"type":"number","description":"Guaranteed minimum output after slippage — the deposit is sized to this"},"price_impact_pct":{"anyOf":[{"type":"number"},{"type":"null"}]},"slippage_bps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["provider","in_amount_ui","out_amount_ui","min_out_amount_ui","price_impact_pct","slippage_bps"],"additionalProperties":false},{"type":"null"}],"description":"Swap route inside the flash loan; null when no swap"},"bridge_mint":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when the loop had to route through a bridge token (two-hop); null otherwise"},"transactions":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string","description":"UNSIGNED base64-encoded Solana v0 transaction — sign with the authority wallet and submit"},"type":{"type":"string","description":"Machine tag for this transaction's role, e.g. \"CRANK\", \"DEPOSIT\""},"label":{"type":"string","description":"Human-readable label"}},"required":["base64","type","label"],"additionalProperties":false},"description":"Sign and submit per `submit`: in array order (sequential) or as one atomic bundle"},"action_tx_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Index of the main action tx; earlier entries are oracle cranks that must land first"},"blockhash":{"type":"object","properties":{"value":{"type":"string"},"last_valid_block_height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Transactions expire past this block height (~60s) — rebuild if expired"}},"required":["value","last_valid_block_height"],"additionalProperties":false},"simulation":{"type":"object","properties":{"success":{"type":"boolean","const":true,"description":"Builds are returned only when the preview simulation succeeded"},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false,"description":"The account's health AFTER this action lands"},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking risk warnings — surface these to the user before signing"}},"required":["success","post_health","warnings"],"additionalProperties":false}},"required":["action","authority","account","bank","symbol","amount_ui","submit","leverage","legs","swap","bridge_mint","transactions","action_tx_index","blockhash","simulation"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/withdraw":{"post":{"operationId":"buildWithdrawTx","summary":"Build a withdraw","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"authority":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"account":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"amount":{"description":"Required unless withdraw_all is true","type":"number","exclusiveMinimum":0},"withdraw_all":{"description":"Withdraw the entire position","type":"boolean"}},"required":["authority","bank"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"action":{"type":"string"},"authority":{"type":"string","description":"The wallet that must SIGN and submit (echoed)"},"account":{"type":"string","description":"The marginfi account acted on (or to be created). SAVE THIS for subsequent calls."},"bank":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bank acted on (echoed); null for create_account"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Amount in UI token units (echoed)"},"submit":{"type":"string","enum":["sequential","bundle"],"description":"How to submit: \"sequential\" = sign and send in array order, waiting for each to confirm; \"bundle\" = ALL transactions must be signed with the returned blockhash and submitted together as ONE atomic Jito bundle — sending them one by one will fail or leave a half-open position"},"leverage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Target leverage for loop actions; null otherwise"},"legs":{"anyOf":[{"type":"object","properties":{"deposit":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false},"borrow":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false}},"required":["deposit","borrow"],"additionalProperties":false},{"type":"null"}],"description":"Per-leg sizing for flash-loan actions (loop / close_position); null otherwise"},"swap":{"anyOf":[{"type":"object","properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregator that won the route, e.g. \"JUPITER\" or \"TITAN\""},"in_amount_ui":{"type":"number","description":"Swap input in UI units of the input token"},"out_amount_ui":{"type":"number","description":"Quoted swap output (UI units)"},"min_out_amount_ui":{"type":"number","description":"Guaranteed minimum output after slippage — the deposit is sized to this"},"price_impact_pct":{"anyOf":[{"type":"number"},{"type":"null"}]},"slippage_bps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["provider","in_amount_ui","out_amount_ui","min_out_amount_ui","price_impact_pct","slippage_bps"],"additionalProperties":false},{"type":"null"}],"description":"Swap route inside the flash loan; null when no swap"},"bridge_mint":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when the loop had to route through a bridge token (two-hop); null otherwise"},"transactions":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string","description":"UNSIGNED base64-encoded Solana v0 transaction — sign with the authority wallet and submit"},"type":{"type":"string","description":"Machine tag for this transaction's role, e.g. \"CRANK\", \"DEPOSIT\""},"label":{"type":"string","description":"Human-readable label"}},"required":["base64","type","label"],"additionalProperties":false},"description":"Sign and submit per `submit`: in array order (sequential) or as one atomic bundle"},"action_tx_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Index of the main action tx; earlier entries are oracle cranks that must land first"},"blockhash":{"type":"object","properties":{"value":{"type":"string"},"last_valid_block_height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Transactions expire past this block height (~60s) — rebuild if expired"}},"required":["value","last_valid_block_height"],"additionalProperties":false},"simulation":{"type":"object","properties":{"success":{"type":"boolean","const":true,"description":"Builds are returned only when the preview simulation succeeded"},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false,"description":"The account's health AFTER this action lands"},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking risk warnings — surface these to the user before signing"}},"required":["success","post_health","warnings"],"additionalProperties":false}},"required":["action","authority","account","bank","symbol","amount_ui","submit","leverage","legs","swap","bridge_mint","transactions","action_tx_index","blockhash","simulation"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/repay":{"post":{"operationId":"buildRepayTx","summary":"Build a repay","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"authority":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"account":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"amount":{"description":"Required unless repay_all is true","type":"number","exclusiveMinimum":0},"repay_all":{"description":"Repay the entire debt (with a small buffer)","type":"boolean"}},"required":["authority","bank"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"action":{"type":"string"},"authority":{"type":"string","description":"The wallet that must SIGN and submit (echoed)"},"account":{"type":"string","description":"The marginfi account acted on (or to be created). SAVE THIS for subsequent calls."},"bank":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bank acted on (echoed); null for create_account"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Amount in UI token units (echoed)"},"submit":{"type":"string","enum":["sequential","bundle"],"description":"How to submit: \"sequential\" = sign and send in array order, waiting for each to confirm; \"bundle\" = ALL transactions must be signed with the returned blockhash and submitted together as ONE atomic Jito bundle — sending them one by one will fail or leave a half-open position"},"leverage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Target leverage for loop actions; null otherwise"},"legs":{"anyOf":[{"type":"object","properties":{"deposit":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false},"borrow":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false}},"required":["deposit","borrow"],"additionalProperties":false},{"type":"null"}],"description":"Per-leg sizing for flash-loan actions (loop / close_position); null otherwise"},"swap":{"anyOf":[{"type":"object","properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregator that won the route, e.g. \"JUPITER\" or \"TITAN\""},"in_amount_ui":{"type":"number","description":"Swap input in UI units of the input token"},"out_amount_ui":{"type":"number","description":"Quoted swap output (UI units)"},"min_out_amount_ui":{"type":"number","description":"Guaranteed minimum output after slippage — the deposit is sized to this"},"price_impact_pct":{"anyOf":[{"type":"number"},{"type":"null"}]},"slippage_bps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["provider","in_amount_ui","out_amount_ui","min_out_amount_ui","price_impact_pct","slippage_bps"],"additionalProperties":false},{"type":"null"}],"description":"Swap route inside the flash loan; null when no swap"},"bridge_mint":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when the loop had to route through a bridge token (two-hop); null otherwise"},"transactions":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string","description":"UNSIGNED base64-encoded Solana v0 transaction — sign with the authority wallet and submit"},"type":{"type":"string","description":"Machine tag for this transaction's role, e.g. \"CRANK\", \"DEPOSIT\""},"label":{"type":"string","description":"Human-readable label"}},"required":["base64","type","label"],"additionalProperties":false},"description":"Sign and submit per `submit`: in array order (sequential) or as one atomic bundle"},"action_tx_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Index of the main action tx; earlier entries are oracle cranks that must land first"},"blockhash":{"type":"object","properties":{"value":{"type":"string"},"last_valid_block_height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Transactions expire past this block height (~60s) — rebuild if expired"}},"required":["value","last_valid_block_height"],"additionalProperties":false},"simulation":{"type":"object","properties":{"success":{"type":"boolean","const":true,"description":"Builds are returned only when the preview simulation succeeded"},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false,"description":"The account's health AFTER this action lands"},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking risk warnings — surface these to the user before signing"}},"required":["success","post_health","warnings"],"additionalProperties":false}},"required":["action","authority","account","bank","symbol","amount_ui","submit","leverage","legs","swap","bridge_mint","transactions","action_tx_index","blockhash","simulation"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/loop":{"post":{"operationId":"buildLoopTx","summary":"Build a leveraged loop (open a strategy): borrow -> swap -> deposit in one flash loan","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","parameters":[{"name":"x-jupiter-api-key","in":"header","required":false,"schema":{"type":"string"},"description":"Bring-your-own Jupiter API key for this build (overrides the service key). Never put keys in the body."},{"name":"x-titan-api-key","in":"header","required":false,"schema":{"type":"string"},"description":"Bring-your-own Titan API key for this build (overrides the service key)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"authority":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"The signing wallet (base58)"},"account":{"description":"Existing marginfi account to add the position to; omit to auto-resolve","type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"create_new_account":{"description":"Create a fresh, isolated marginfi account for this position (recommended per strategy)","type":"boolean"},"deposit_bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Collateral bank — a strategy's `supply.bank`"},"borrow_bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Debt bank — a strategy's `borrow.bank` (P0 venue only)"},"amount":{"type":"number","exclusiveMinimum":0,"description":"Principal already in the wallet, in deposit-token UI units"},"leverage":{"type":"number","minimum":1,"maximum":100,"description":"Target leverage, e.g. 2 = 2x. Must be <= the strategy's max_leverage"},"slippage_bps":{"description":"Swap slippage tolerance in bps (default 100 = 1%)","type":"integer","minimum":1,"maximum":500}},"required":["authority","deposit_bank","borrow_bank","amount","leverage"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"action":{"type":"string"},"authority":{"type":"string","description":"The wallet that must SIGN and submit (echoed)"},"account":{"type":"string","description":"The marginfi account acted on (or to be created). SAVE THIS for subsequent calls."},"bank":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bank acted on (echoed); null for create_account"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Amount in UI token units (echoed)"},"submit":{"type":"string","enum":["sequential","bundle"],"description":"How to submit: \"sequential\" = sign and send in array order, waiting for each to confirm; \"bundle\" = ALL transactions must be signed with the returned blockhash and submitted together as ONE atomic Jito bundle — sending them one by one will fail or leave a half-open position"},"leverage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Target leverage for loop actions; null otherwise"},"legs":{"anyOf":[{"type":"object","properties":{"deposit":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false},"borrow":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false}},"required":["deposit","borrow"],"additionalProperties":false},{"type":"null"}],"description":"Per-leg sizing for flash-loan actions (loop / close_position); null otherwise"},"swap":{"anyOf":[{"type":"object","properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregator that won the route, e.g. \"JUPITER\" or \"TITAN\""},"in_amount_ui":{"type":"number","description":"Swap input in UI units of the input token"},"out_amount_ui":{"type":"number","description":"Quoted swap output (UI units)"},"min_out_amount_ui":{"type":"number","description":"Guaranteed minimum output after slippage — the deposit is sized to this"},"price_impact_pct":{"anyOf":[{"type":"number"},{"type":"null"}]},"slippage_bps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["provider","in_amount_ui","out_amount_ui","min_out_amount_ui","price_impact_pct","slippage_bps"],"additionalProperties":false},{"type":"null"}],"description":"Swap route inside the flash loan; null when no swap"},"bridge_mint":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when the loop had to route through a bridge token (two-hop); null otherwise"},"transactions":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string","description":"UNSIGNED base64-encoded Solana v0 transaction — sign with the authority wallet and submit"},"type":{"type":"string","description":"Machine tag for this transaction's role, e.g. \"CRANK\", \"DEPOSIT\""},"label":{"type":"string","description":"Human-readable label"}},"required":["base64","type","label"],"additionalProperties":false},"description":"Sign and submit per `submit`: in array order (sequential) or as one atomic bundle"},"action_tx_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Index of the main action tx; earlier entries are oracle cranks that must land first"},"blockhash":{"type":"object","properties":{"value":{"type":"string"},"last_valid_block_height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Transactions expire past this block height (~60s) — rebuild if expired"}},"required":["value","last_valid_block_height"],"additionalProperties":false},"simulation":{"type":"object","properties":{"success":{"type":"boolean","const":true,"description":"Builds are returned only when the preview simulation succeeded"},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false,"description":"The account's health AFTER this action lands"},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking risk warnings — surface these to the user before signing"}},"required":["success","post_health","warnings"],"additionalProperties":false}},"required":["action","authority","account","bank","symbol","amount_ui","submit","leverage","legs","swap","bridge_mint","transactions","action_tx_index","blockhash","simulation"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/close-position":{"post":{"operationId":"buildClosePositionTx","summary":"Unwind a loop: withdraw collateral -> swap -> repay debt in one flash loan","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","parameters":[{"name":"x-jupiter-api-key","in":"header","required":false,"schema":{"type":"string"},"description":"Bring-your-own Jupiter API key for this build (overrides the service key). Never put keys in the body."},{"name":"x-titan-api-key","in":"header","required":false,"schema":{"type":"string"},"description":"Bring-your-own Titan API key for this build (overrides the service key)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"authority":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"account":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$"},"deposit_bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Collateral bank to withdraw from (the loop's deposit_bank)"},"borrow_bank":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Debt bank to repay (the loop's borrow_bank)"},"amount":{"description":"Debt to repay in borrow-token UI units; required unless repay_all","type":"number","exclusiveMinimum":0},"repay_all":{"description":"Repay the entire debt","type":"boolean"},"slippage_bps":{"description":"Swap slippage tolerance in bps (default 100 = 1%)","type":"integer","minimum":1,"maximum":500}},"required":["authority","deposit_bank","borrow_bank"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"action":{"type":"string"},"authority":{"type":"string","description":"The wallet that must SIGN and submit (echoed)"},"account":{"type":"string","description":"The marginfi account acted on (or to be created). SAVE THIS for subsequent calls."},"bank":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bank acted on (echoed); null for create_account"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Amount in UI token units (echoed)"},"submit":{"type":"string","enum":["sequential","bundle"],"description":"How to submit: \"sequential\" = sign and send in array order, waiting for each to confirm; \"bundle\" = ALL transactions must be signed with the returned blockhash and submitted together as ONE atomic Jito bundle — sending them one by one will fail or leave a half-open position"},"leverage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Target leverage for loop actions; null otherwise"},"legs":{"anyOf":[{"type":"object","properties":{"deposit":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false},"borrow":{"type":"object","properties":{"bank":{"type":"string"},"symbol":{"anyOf":[{"type":"string"},{"type":"null"}]},"amount_ui":{"type":"number","description":"Amount in UI token units for this leg"}},"required":["bank","symbol","amount_ui"],"additionalProperties":false}},"required":["deposit","borrow"],"additionalProperties":false},{"type":"null"}],"description":"Per-leg sizing for flash-loan actions (loop / close_position); null otherwise"},"swap":{"anyOf":[{"type":"object","properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Aggregator that won the route, e.g. \"JUPITER\" or \"TITAN\""},"in_amount_ui":{"type":"number","description":"Swap input in UI units of the input token"},"out_amount_ui":{"type":"number","description":"Quoted swap output (UI units)"},"min_out_amount_ui":{"type":"number","description":"Guaranteed minimum output after slippage — the deposit is sized to this"},"price_impact_pct":{"anyOf":[{"type":"number"},{"type":"null"}]},"slippage_bps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["provider","in_amount_ui","out_amount_ui","min_out_amount_ui","price_impact_pct","slippage_bps"],"additionalProperties":false},{"type":"null"}],"description":"Swap route inside the flash loan; null when no swap"},"bridge_mint":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when the loop had to route through a bridge token (two-hop); null otherwise"},"transactions":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string","description":"UNSIGNED base64-encoded Solana v0 transaction — sign with the authority wallet and submit"},"type":{"type":"string","description":"Machine tag for this transaction's role, e.g. \"CRANK\", \"DEPOSIT\""},"label":{"type":"string","description":"Human-readable label"}},"required":["base64","type","label"],"additionalProperties":false},"description":"Sign and submit per `submit`: in array order (sequential) or as one atomic bundle"},"action_tx_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Index of the main action tx; earlier entries are oracle cranks that must land first"},"blockhash":{"type":"object","properties":{"value":{"type":"string"},"last_valid_block_height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Transactions expire past this block height (~60s) — rebuild if expired"}},"required":["value","last_valid_block_height"],"additionalProperties":false},"simulation":{"type":"object","properties":{"success":{"type":"boolean","const":true,"description":"Builds are returned only when the preview simulation succeeded"},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false,"description":"The account's health AFTER this action lands"},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking risk warnings — surface these to the user before signing"}},"required":["success","post_health","warnings"],"additionalProperties":false}},"required":["action","authority","account","bank","symbol","amount_ui","submit","leverage","legs","swap","bridge_mint","transactions","action_tx_index","blockhash","simulation"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}},"/v1/tx/simulate":{"post":{"operationId":"simulateTxs","summary":"Simulate a transaction bundle, returning post-action health","description":"Returns UNSIGNED base64 v0 transactions — sign with the authority wallet and submit in array order. transactions[action_tx_index] is the main action; earlier entries are oracle cranks. The blockhash expires in ~60s; rebuild if expired. simulation.post_health is the account's health after the action. `submit` tells you how: \"sequential\" = one at a time in order; \"bundle\" = ALL transactions signed with the returned blockhash and submitted together as ONE atomic Jito bundle (loop / close-position may require this).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"transactions":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","minLength":1},"description":"Base64-encoded transactions to simulate as an atomic bundle, in order"},"account":{"type":"string","pattern":"^[1-9A-HJ-NP-Za-km-z]{32,44}$","description":"Marginfi account whose post-action health to compute"}},"required":["transactions","account"],"additionalProperties":false}}}},"responses":{"200":{"description":"Unsigned transaction envelope","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"success":{"type":"boolean","const":true},"post_health":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","moderate","warning","critical"],"description":"healthy >0.5, moderate 0.1-0.5, warning 0.01-0.1, critical <=0.01; liquidation occurs at 0"},"health_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"(maint assets - maint liabilities) / maint assets; 1 = no debt, 0 = liquidatable. null when the account has no assets."},"assets_usd_maint":{"type":"string","description":"Maintenance-weighted assets, USD decimal string"},"liabilities_usd_maint":{"type":"string"},"assets_usd_initial":{"type":"string","description":"Initial-weighted assets (governs new borrows)"},"liabilities_usd_initial":{"type":"string"},"free_collateral_usd":{"type":"string","description":"Initial-weighted borrowing power remaining, USD decimal string"}},"required":["status","health_factor","assets_usd_maint","liabilities_usd_maint","assets_usd_initial","liabilities_usd_initial","free_collateral_usd"],"additionalProperties":false},"warnings":{"type":"array","items":{"type":"string"}}},"required":["success","post_health","warnings"],"additionalProperties":false}}}},"400":{"description":"Invalid input (INVALID_ADDRESS, BANK_NOT_FOUND, ...)","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"string","description":"Prescriptive message: what broke and how to fix it"},"code":{"type":"string","enum":["INVALID_ADDRESS","BANK_NOT_FOUND","ACCOUNT_NOT_FOUND","ACCOUNT_AMBIGUOUS","NOT_FOUND","INSUFFICIENT_COLLATERAL","BORROW_LIMIT_EXCEEDED","LEVERAGE_EXCEEDED","SWAP_ROUTE_UNAVAILABLE","TX_TOO_LARGE","BRIDGE_CONFLICT","ORACLE_CRANK_FAILED","SIMULATION_FAILED","UPSTREAM_ERROR","RATE_LIMITED","INTERNAL_ERROR"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["error","code"],"additionalProperties":false}}}},"422":{"description":"Preview simulation or oracle crank failed — transactions withheld"},"429":{"description":"Rate limited; Retry-After header is set"},"502":{"description":"Upstream (monitor/app/RPC) unavailable"}}}}}}