Skip to main content

Deposit and borrow (simulate)

POST 

/v1/actions/lending/deposit-and-borrow

Deposit and borrow with post-trade simulation. Same parameters as GET. Optionally send a JSON body with current portfolio state (balanceData, aprData, positions) to receive projected post-trade metrics in the simulation field — if omitted, the API fetches balances on-chain automatically. Use the data returned by the user-positions endpoint directly — always include positions for accurate health-factor and borrow-capacity projections.

Plain-text reference — POST /v1/actions/lending/deposit-and-borrow

Parameters

ParameterInTypeRequiredDescription
marketUidquerystringyesThe COLLATERAL (supply) market, lender:chainId:address.
debtMarketUidquerystringyesThe DEBT (borrow) market — same lender and chain (Exactly: any two Exactly markets, it is cross-margin).
collateralAmountquerystringyesRaw amount supplied (alias amount). With a foreign payAsset, the amount of that asset swapped into the collateral.
borrowAmountquerystringyesRaw amount borrowed.
payAssetquerystringnoCurrency the collateral is paid in. Default: the collateral underlying; native (zero address) wraps where the lender supports it; another token adds an aggregator swap (needs slippage) where supported, else 400 UNSUPPORTED.
receiveAssetquerystringnoDelivery currency of the borrow: the debt underlying (default) or native (unwrap of a wrapped-native debt). Any other token is 400 UNSUPPORTED.
operatorquerystringyesThe position owner and caller (signer).
receiverquerystringnoRecipient of the tokens paid out (the borrow, or the withdrawn collateral). Default: operator.
accountIdquerystringnoSub-account / position id (Euler sub-account, Morpho-style position, NFT id, Liquity trove id, …). Aliases: nftId, and troveId on withdraw-and-repay.
borrowModequerystringnoAave rate mode of the debt (alias lendingMode). Default 2 = VARIABLE on Aave-type lenders.
slippagequerystringnoBasis points. Required when a payAsset / receiveAsset conversion adds an aggregator swap.
simulatequerybooleannoWhen true, the API fetches the operator's on-chain balances and returns projected post-trade metrics in the simulation field. The projection is always of the operator's account: with a custom receiver it does not show the receiver's position. Default: false.
modeIdquerystringnoAave V3 only: the e-mode category the borrow capacity was computed against. When it differs from the account's, a setUserEMode pre-step is prepended (a user transaction — it cannot be composed on behalf).
debtTermIdquerystringnoFixed-term debt: Exactly maturity / Lista broker term id (alias termId). collateralTermId is the supply-side equivalent.
interestRatequerystringnoLiquity family / River trove open: the user-set interest rate. With maxUpfrontFee, maxFeePercentage, ownerIndex.
bandsquerystringnoLlamaLend: the number of soft-liquidation bands (4–50). Fixed for the life of the loan; omitted → the market default.
liqLtvquerystringnoTwyne: the liquidation LTV (1e4 scale) of a position DEPLOYED by this open; ignored when a position exists.
bidRatequerystringnoTerm auction: the sealed bid rate (alias rate), with optional termNonce / termSeed seal inputs.
collateralAsset1querystringnoTwo-token (DEX-LP) sides, e.g. Fluid smart vaults: the second token of the collateral, with collateralAmount1; debtAsset1 / debtAmount1 for the debt side; collateralMinShares / debtMaxShares bound the share math. Absent = single-sided.

Request body

FieldTypeRequiredDescription
balanceDataobjectyesAggregated balance data for a sub-account.
balanceData.depositsnumbernoTotal deposits in USD
balanceData.debtnumbernoTotal debt in USD
balanceData.adjustedDebtnumbernoDebt adjusted for borrow factors
balanceData.collateralnumbernoCollateral value in USD
balanceData.collateralAllActivenumbernoCollateral if all assets were enabled
balanceData.borrowDiscountedCollateralnumbernoCollateral discounted by borrow factors
balanceData.borrowDiscountedCollateralAllActivenumbernoDiscounted collateral if all enabled
balanceData.navnumbernoNet asset value (deposits - debt)
balanceData.deposits24hnumbernoDeposits 24h ago (for change calculation)
balanceData.debt24hnumbernoDebt 24h ago
balanceData.nav24hnumbernoNAV 24h ago
balanceData.rewardsobject[]noPending reward token claims. Each entry represents a single reward program.
balanceData.rewards[].assetstringnoReward token contract address
balanceData.rewards[].totalRewardsnumbernoTotal accumulated rewards (token units)
balanceData.rewards[].claimableRewardsnumbernoImmediately claimable rewards (token units)
aprDataobjectyesAPR breakdown for a sub-account.
aprData.aprnumbernoNet APR (deposit - borrow)
aprData.depositAprnumbernoWeighted deposit APR
aprData.borrowAprnumbernoWeighted borrow APR
aprData.rewardAprnumbernoTotal reward APR
aprData.rewardDepositAprnumbernoReward APR on deposits
aprData.rewardBorrowAprnumbernoReward APR on borrows
aprData.intrinsicAprnumbernoIntrinsic yield APR (e.g., stETH staking)
aprData.intrinsicDepositAprnumbernoIntrinsic yield APR portion from deposits
aprData.intrinsicBorrowAprnumbernoIntrinsic yield APR portion from borrows
aprData.rewardsobjectnoPer-reward-token APR breakdown. Keys are reward token addresses.
modeIdstringnoMode/config key from userConfig.selectedMode (defaults to "0")
positionsobject[]noCurrent lending positions from the matching sub-account's positions array. The full LendingPosition objects returned by user-positions are accepted — only the fields in SimulationPosition are used. Always include this for accurate health-factor and borrow-capacity projections.
positions[].marketUidstringyesUnique market identifier (format: {lender}:{chainId}:{address})
positions[].depositsUSDnumberyesDeposit amount in USD
positions[].debtUSDnumberyesVariable debt in USD
positions[].debtStableUSDnumberyesStable debt in USD
positions[].collateralEnabledbooleanyesWhether this asset is enabled as collateral

Response 200

FieldTypeDescription
successTrue
dataobjectSimulation results including projected health factor and borrow capacity
actionsobjectTransaction calldata and approvals. Null for quote-only responses (no account provided).
actions.transactionsobject[]Pre-trade setup transactions (e.g. e-mode switch, collateral enable). Execute these before the main swap. Empty when no setup is needed.
actions.transactions[].chainTypeevmWhich VM executes this step. ABSENT means evm, which is the only value any endpoint returns today — every EVM response is unchanged. A non-EVM chain would return a different shape (a serialized, PERISHABLE transaction rather than to/data/value) carrying its own chainType, so a client that wants to stay forward-compatible should branch on this field rather than assume to is present.
actions.transactions[].tostringTarget contract address
actions.transactions[].datastringEncoded calldata
actions.transactions[].valuestringETH value to send with the transaction
actions.transactions[].descriptionstringHuman-readable label. For alternatives, this is the aggregator name (e.g. "Paraswap"). For transactions, describes the setup action (e.g. "Switch e-mode to 1").
actions.alternativesobject[]DEX aggregator swap transactions sorted by best output (descending). Each entry's description is the aggregator name. The client should pick one to execute. Present on loop action endpoints.
actions.alternatives[].chainTypeevmWhich VM executes this step. ABSENT means evm, which is the only value any endpoint returns today — every EVM response is unchanged. A non-EVM chain would return a different shape (a serialized, PERISHABLE transaction rather than to/data/value) carrying its own chainType, so a client that wants to stay forward-compatible should branch on this field rather than assume to is present.
actions.alternatives[].tostringTarget contract address
actions.alternatives[].datastringEncoded calldata
actions.alternatives[].valuestringETH value to send with the transaction
actions.alternatives[].descriptionstringHuman-readable label. For alternatives, this is the aggregator name (e.g. "Paraswap"). For transactions, describes the setup action (e.g. "Switch e-mode to 1").
actions.permissionsobject[]Approval/delegation transactions that must execute before both transactions and alternatives. Includes ERC20 allowances (targeting the composer contract) and lender borrow/withdrawal delegations (targeting the lending protocol contract directly). Filtered against on-chain state so only missing approvals are returned. Null when no approvals are needed.
actions.permissions[].tostringTarget contract address
actions.permissions[].datastringEncoded calldata
actions.permissions[].valuestringETH value
actions.permissions[].descriptionstringHuman-readable description of the approval (e.g. "Approve borrow for AAVE_V3", "Approve ERC20")
actions.permissions[].spenderstringERC-20 approve spender (x-chain permissions). Match it against the selected quote's approvalTarget — several bridges can share one spender, so do not match by description.
actions.permissions[].typeERC20, LenderWhat kind of grant this is. A signatures[] offer names the type it replaces via its replaces field.
actions.signaturesobject[]EIP-712 payloads the user can sign INSTEAD of sending the corresponding permissions entry. Only present when the caller opted in with permit=auto|required and a permit path exists. Sign with eth_signTypedData_v4, then POST the same endpoint with {permits: [{permitId, signature}]} (plus builds where the response issued buildIds) — the permit executes inside the main transaction.
actions.signatures[].permitIdstringOpaque, self-describing handle for this permit. Round-trip it verbatim: POST {permits: [{permitId, signature}]} back to the same endpoint.
actions.signatures[].kinderc2612, dai, permit2, aaveCredit, morphoAuth, cometAuthPermit flavour
actions.signatures[].typedDataobjectReady for eth_signTypedData_v4 (domain, types incl. EIP712Domain, primaryType, message). All numeric fields are decimal strings.
actions.signatures[].replacesstringWhich permissions entry this signature replaces (ERC20 | Lender)
actions.signatures[].spenderstringWho the signature authorises. Match against the permission / quote (approvalTarget) it replaces — on multi-spender responses (x-chain) only routes whose approvalTarget equals this spender are covered by the signature.
actions.signatures[].descriptionstringHuman-readable label for this entry.
actions.signatures[].unscopedbooleanTrue when the grant is NOT amount-scoped (full position control until revoked) — surface this to the user.
actions.signatures[].deadlinestringUnix seconds after which the signature is worthless (default: 30 minutes).
actions.signsobject[]Messages that MUST be signed before anything can be sent (unlike signatures, which are optional permit offers). When non-empty, transactions and alternatives are EMPTY: sign typedData with eth_signTypedData_v4 (or, for format: personal_sign, message with personal_sign), then call submit with the signature under submit.signatureField, and execute what that answers. permissions may still be present and can be sent before or after signing. Produced by Inverse FiRM loops (/loop/leverage, /loop/close), Morpho Midnight make, Term order-sign and the Lista leg of /rewards/claim.
actions.signs[].purposeauthorize-action, publish-order, authenticateauthorize-action: the signature authorises an on-chain action and submit answers its transaction (Inverse ALE loops). publish-order: the signature makes an off-chain order and submit publishes it (Midnight make, Term order-sign). authenticate: the signature is a LOGIN to a third-party API that serves the data the transaction needs (Lista reward proofs); it authorises nothing on-chain.
actions.signs[].formateip712, personal_signeip712: sign typedData with eth_signTypedData_v4. personal_sign: sign the UTF-8 message with personal_sign.
actions.signs[].typedDataobjectformat: eip712 only. Ready for eth_signTypedData_v4. All numeric fields are decimal strings.
actions.signs[].messagestringformat: personal_sign only. The exact text to sign; send it back verbatim (it is part of submit.params).
actions.signs[].signerstringThe address that must sign. The server recovers the signer and refuses any other.
actions.signs[].deadlinestringUnix seconds after which the signature is worthless.
actions.signs[].spenderstringWho the signature authorises.
actions.signs[].descriptionstringHuman-readable label for this entry.

Example response

{
"success": true,
"data": {},
"actions": {
"transactions": [
{
"chainType": "evm",
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"alternatives": [
{
"chainType": "evm",
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"permissions": [
{
"to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"type": "ERC20"
}
],
"signatures": [
{
"permitId": "string",
"kind": "erc2612",
"typedData": {},
"replaces": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"description": "string",
"unscoped": true,
"deadline": "string"
}
],
"signs": [
{
"purpose": "authorize-action",
"format": "eip712",
"typedData": {},
"message": "string",
"signer": "string",
"deadline": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"description": "string",
"submit": {
"method": "GET",
"endpoint": "string",
"params": {},
"body": {},
"signatureField": "string"
}
}
],
"permitSkipped": [
{
"replaces": "string",
"reason": "string"
}
]
}
}

Request​

Responses​

Transaction(s) with post-trade simulation