Skip to main content

Close position (simulate)

POST 

/v1/actions/loop/close

Close a leveraged position and simulate post-trade state. 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/loop/close

Parameters

ParameterInTypeRequiredDescription
routequeryauto, bundler3, native, composer, proxynoWhich assembly to use, for lenders that have more than one. Morpho Blue only today.
  • (omitted)auto: prefer the protocol’s own tooling and fall back to the composer for anything it cannot express (a cross-market pair, a margin paid in a foreign asset, an EXACT_OUTPUT close, a chain with no bundler3 or no swap adapter).
  • bundler3 / native — force Morpho’s bundler3. A request it cannot serve becomes an ERROR instead of silently falling back, which is what makes the route testable.
  • composer / proxy — force the 1delta composer.

The default matters: the bundler3 route asks for setAuthorization(GeneralAdapter1), Morpho’s own audited adapter, where the composer route asks for a standing grant on ours. | | marketUidIn | query | string | yes | Market identifier for input side (lender:chainId:address). | | marketUidOut | query | string | yes | Market identifier for output side (lender:chainId:address). | | slippage | query | number | yes | Slippage tolerance (basis points) | | account | query | string | no | Account address. Include to build transaction, omit for quote-only. | | amount | query | string | yes | Amount in wei | | tradeType | query | 0, 1 | no | Trade type (0=EXACT_INPUT, 1=EXACT_OUTPUT) | | irModeOut | query | 0, 1, 2 | no | Interest rate mode for debt | | usePendleMintRedeem | query | boolean | no | Use Pendle mint/redeem | | isAll | query | boolean | no | Repay full debt | | loanId | query | string | no | Lista DAO fixed-term (brokered) debt markets only. Identifies which loan the close repays on the loop's repay leg: the loan's loanId (broker posId) from the user-positions response, or the type(uint128).max sentinel (340282366920938463463374607431768211455) for the flexible/dynamic position. Required when marketUidOut is a brokered market; ignored otherwise. | | accountId | query | string | no | Account ID |

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
dataobjectQuotes and simulation results
data.lenderstringProtocol identifier. See the LenderId schema.
data.quotesobject[]Candidate routes, best output first. Execute exactly one.
data.quotes[].deltasobject
data.quotes[].deltas.aggregatorstringAggregator source
data.quotes[].deltas.tradeInputnumberTrade input amount
data.quotes[].deltas.tradeOutputnumberTrade output amount
data.quotes[].deltas.deltasobjectBalance deltas
data.quotes[].rateImpactobject[]Projected interest-rate impact per market for THIS quote (its own trade amounts). Omitted if IRM data is unavailable.
data.quotes[].rateImpact[].marketUidstringMarket identifier (format: lender:chainId:address)
data.quotes[].rateImpact[].utilizationobjectA current/projected pair for a single rate metric.
data.quotes[].rateImpact[].borrowRateobjectA current/projected pair for a single rate metric.
data.quotes[].rateImpact[].depositRateobjectA current/projected pair for a single rate metric.
data.rateImpactobject[]Projected interest-rate impact per market. Single-market actions produce 1 entry; loop actions produce 2. Null if IRM data is unavailable.
data.rateImpact[].marketUidstringMarket identifier (format: lender:chainId:address)
data.rateImpact[].utilizationobjectA current/projected pair for a single rate metric.
data.rateImpact[].utilization.currentnumberCurrent value
data.rateImpact[].utilization.projectednumberProjected value after the action
data.rateImpact[].borrowRateobjectA current/projected pair for a single rate metric.
data.rateImpact[].borrowRate.currentnumberCurrent value
data.rateImpact[].borrowRate.projectednumberProjected value after the action
data.rateImpact[].depositRateobjectA current/projected pair for a single rate metric.
data.rateImpact[].depositRate.currentnumberCurrent value
data.rateImpact[].depositRate.projectednumberProjected value after the action
data.simulationobjectProjected post-trade metrics, or null if simulation failed
data.simulation.preobjectPortfolio state before the trade.
data.simulation.pre.healthFactornumberHealth factor before the trade (null-safe: capped at 1e18 when no debt)
data.simulation.pre.borrowCapacitynumberBorrow capacity (USD) before the trade
data.simulation.postobjectProjected portfolio state after the trade.
data.simulation.post.healthFactornumberProjected health factor after the trade
data.simulation.post.borrowCapacitynumberProjected borrow capacity (USD) after the trade
data.simulation.post.balanceDataobjectAggregated balance data for a sub-account.
data.simulation.post.aprDataobjectAPR breakdown for a sub-account.
data.simulationErrorstringError message if simulation failed
data.lenderstringProtocol identifier. See the LenderId schema.
data.quotesobject[]Candidate routes, best output first. Execute exactly one.
data.quotes[].deltasobject
data.quotes[].deltas.aggregatorstringAggregator source
data.quotes[].deltas.tradeInputnumberTrade input amount

Example response

{
"success": true,
"data": {
"lender": "AAVE_V3",
"quotes": [
{
"deltas": {
"aggregator": "string",
"tradeInput": 1.0,
"tradeOutput": 1.0,
"deltas": {}
},
"rateImpact": [
{
"marketUid": "AAVE_V3:8453:0x4200000000000000000000000000000000000006",
"utilization": {
"current": 1.0,
"projected": 1.0
},
"borrowRate": {
"current": 1.0,
"projected": 1.0
},
"depositRate": {
"current": 1.0,
"projected": 1.0
}
}
]
}
],
"rateImpact": [
{
"marketUid": "AAVE_V3:8453:0x4200000000000000000000000000000000000006",
"utilization": {
"current": 1.0,
"projected": 1.0
},
"borrowRate": {
"current": 1.0,
"projected": 1.0
},
"depositRate": {
"current": 1.0,
"projected": 1.0
}
}
],
"simulation": {
"pre": {
"healthFactor": 1.85,
"borrowCapacity": 3000
},
"post": {
"healthFactor": 2.1,
"borrowCapacity": 3500,
"balanceData": {
"deposits": 10000.5,
"debt": 5000.25,
"adjustedDebt": 5500,
"collateral": 9000,
"collateralAllActive": 10000.5,
"borrowDiscountedCollateral": 8000,
"borrowDiscountedCollateralAllActive": 9000,
"nav": 5000.25,
"deposits24h": 9800,
"debt24h": 4900,
"nav24h": 4900,
"rewards": [
{
"asset": "0xc00e94Cb662C3520282E6f5717214004A7f26888",
"totalRewards": 12.5,
"claimableRewards": 12.5
}
]
},
"aprData": {
"apr": 2.5,
"depositApr": 3.5,
"borrowApr": 5.2,
"rewardApr": 1.2,
"rewardDepositApr": 0.8,
"rewardBorrowApr": 0.4,
"intrinsicApr": 0,
"intrinsicDepositApr": 0,
"intrinsicBorrowApr": 0,
"rewards": {}
}
}
},
"simulationError": "string"
},
"actions": {
"transactions": [
{
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"alternatives": [
{
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"permissions": [
{
"to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
]
}
}

Request

Responses

Quote or full build with simulation