# Close position (simulate)

Endpoint reference for the 1delta API. Index: https://docs.1delta.io/llms.txt · every endpoint: https://docs.1delta.io/llms-full.txt

---

### POST /v1/actions/loop/close

- operationId: `close-position-simulate`
- docs: https://docs.1delta.io/1delta-api/close-position-simulate/
- markdown: https://docs.1delta.io/1delta-api/close-position-simulate.md
- tags: Loop (Actions)

Close position (simulate)

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.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `route` | query | "auto" \| "bundler3" \| "native" \| "composer" \| "proxy" | no | Which 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** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `balanceData` | object | yes | Aggregated balance data for a sub-account. |
| `balanceData.deposits` | number | no | Total deposits in USD |
| `balanceData.debt` | number | no | Total debt in USD |
| `balanceData.adjustedDebt` | number | no | Debt adjusted for borrow factors |
| `balanceData.collateral` | number | no | Collateral value in USD |
| `balanceData.collateralAllActive` | number | no | Collateral if all assets were enabled |
| `balanceData.borrowDiscountedCollateral` | number | no | Collateral discounted by borrow factors |
| `balanceData.borrowDiscountedCollateralAllActive` | number | no | Discounted collateral if all enabled |
| `balanceData.nav` | number | no | Net asset value (deposits - debt) |
| `balanceData.deposits24h` | number | no | Deposits 24h ago (for change calculation) |
| `balanceData.debt24h` | number | no | Debt 24h ago |
| `balanceData.nav24h` | number | no | NAV 24h ago |
| `balanceData.rewards` | object[] | no | Pending reward token claims. Each entry represents a single reward program. |
| `balanceData.rewards[].asset` | string | no | Reward token contract address |
| `balanceData.rewards[].totalRewards` | number | no | Total accumulated rewards (token units) |
| `balanceData.rewards[].claimableRewards` | number | no | Immediately claimable rewards (token units) |
| `aprData` | object | yes | APR breakdown for a sub-account. |
| `aprData.apr` | number | no | Net APR (deposit - borrow) |
| `aprData.depositApr` | number | no | Weighted deposit APR |
| `aprData.borrowApr` | number | no | Weighted borrow APR |
| `aprData.rewardApr` | number | no | Total reward APR |
| `aprData.rewardDepositApr` | number | no | Reward APR on deposits |
| `aprData.rewardBorrowApr` | number | no | Reward APR on borrows |
| `aprData.intrinsicApr` | number | no | Intrinsic yield APR (e.g., stETH staking) |
| `aprData.intrinsicDepositApr` | number | no | Intrinsic yield APR portion from deposits |
| `aprData.intrinsicBorrowApr` | number | no | Intrinsic yield APR portion from borrows |
| `aprData.rewards` | object | no | Per-reward-token APR breakdown. Keys are reward token addresses. |
| `modeId` | string | no | Mode/config key from `userConfig.selectedMode` (defaults to "0") |
| `positions` | object[] | no | Current 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[].marketUid` | string | yes | Unique market identifier (format: `{lender}:{chainId}:{address}`) |
| `positions[].depositsUSD` | number | yes | Deposit amount in USD |
| `positions[].debtUSD` | number | yes | Variable debt in USD |
| `positions[].debtStableUSD` | number | yes | Stable debt in USD |
| `positions[].collateralEnabled` | boolean | yes | Whether this asset is enabled as collateral |

**Example request body**

```json
{
  "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": {}
  },
  "modeId": "0",
  "positions": [
    {
      "marketUid": "AAVE_V3:1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
      "depositsUSD": 5000,
      "debtUSD": 2000,
      "debtStableUSD": 0,
      "collateralEnabled": true
    }
  ]
}
```

**Response `200`** — Quote or full build with simulation

| Field | Type | Description |
| --- | --- | --- |
| `success` | true |  |
| `data` | object | Quotes and simulation results |
| `data.lender` | string | Protocol identifier. See the `LenderId` schema. |
| `data.quotes` | object[] | Candidate routes, best output first. Execute exactly one. |
| `data.quotes[].deltas` | object |  |
| `data.quotes[].deltas.aggregator` | string | Aggregator source |
| `data.quotes[].deltas.tradeInput` | number | Trade input amount |
| `data.quotes[].deltas.tradeOutput` | number | Trade output amount |
| `data.quotes[].deltas.deltas` | object | Balance deltas |
| `data.quotes[].rateImpact` | object[] | Projected interest-rate impact per market for THIS quote (its own trade amounts). Omitted if IRM data is unavailable. |
| `data.quotes[].rateImpact[].marketUid` | string | Market identifier (format: `lender:chainId:address`) |
| `data.quotes[].rateImpact[].utilization` | object | A current/projected pair for a single rate metric. |
| `data.quotes[].rateImpact[].utilization.current` | number | Current value |
| `data.quotes[].rateImpact[].utilization.projected` | number | Projected value after the action |
| `data.quotes[].rateImpact[].borrowRate` | object | A current/projected pair for a single rate metric. |
| `data.quotes[].rateImpact[].borrowRate.current` | number | Current value |
| `data.quotes[].rateImpact[].borrowRate.projected` | number | Projected value after the action |
| `data.quotes[].rateImpact[].depositRate` | object | A current/projected pair for a single rate metric. |
| `data.quotes[].rateImpact[].depositRate.current` | number | Current value |
| `data.quotes[].rateImpact[].depositRate.projected` | number | Projected value after the action |
| `data.rateImpact` | object[] | Projected interest-rate impact per market. Single-market actions produce 1 entry; loop actions produce 2. Null if IRM data is unavailable. |
| `data.rateImpact[].marketUid` | string | Market identifier (format: `lender:chainId:address`) |
| `data.rateImpact[].utilization` | object | A current/projected pair for a single rate metric. |
| `data.rateImpact[].utilization.current` | number | Current value |
| `data.rateImpact[].utilization.projected` | number | Projected value after the action |
| `data.rateImpact[].borrowRate` | object | A current/projected pair for a single rate metric. |
| `data.rateImpact[].borrowRate.current` | number | Current value |
| `data.rateImpact[].borrowRate.projected` | number | Projected value after the action |
| `data.rateImpact[].depositRate` | object | A current/projected pair for a single rate metric. |
| `data.rateImpact[].depositRate.current` | number | Current value |
| `data.rateImpact[].depositRate.projected` | number | Projected value after the action |
| `data.simulation` | object | Projected post-trade metrics, or null if simulation failed |
| `data.simulation.pre` | object | Portfolio state before the trade. |
| `data.simulation.pre.healthFactor` | number | Health factor before the trade (null-safe: capped at 1e18 when no debt) |
| `data.simulation.pre.borrowCapacity` | number | Borrow capacity (USD) before the trade |
| `data.simulation.post` | object | Projected portfolio state after the trade. |
| `data.simulation.post.healthFactor` | number | Projected health factor after the trade |
| `data.simulation.post.borrowCapacity` | number | Projected borrow capacity (USD) after the trade |
| `data.simulation.post.balanceData` | object | Aggregated balance data for a sub-account. |
| `data.simulation.post.balanceData.deposits` | number | Total deposits in USD |
| `data.simulation.post.balanceData.debt` | number | Total debt in USD |
| `data.simulation.post.balanceData.adjustedDebt` | number | Debt adjusted for borrow factors |
| `data.simulation.post.balanceData.collateral` | number | Collateral value in USD |
| `data.simulation.post.balanceData.collateralAllActive` | number | Collateral if all assets were enabled |
| `data.simulation.post.balanceData.borrowDiscountedCollateral` | number | Collateral discounted by borrow factors |
| `data.simulation.post.balanceData.borrowDiscountedCollateralAllActive` | number | Discounted collateral if all enabled |
| `data.simulation.post.balanceData.nav` | number | Net asset value (deposits - debt) |
| `data.simulation.post.balanceData.deposits24h` | number | Deposits 24h ago (for change calculation) |
| `data.simulation.post.balanceData.debt24h` | number | Debt 24h ago |
| `data.simulation.post.balanceData.nav24h` | number | NAV 24h ago |
| `data.simulation.post.balanceData.rewards` | object[] | Pending reward token claims. Each entry represents a single reward program. |
| `data.simulation.post.aprData` | object | APR breakdown for a sub-account. |
| `data.simulation.post.aprData.apr` | number | Net APR (deposit - borrow) |
| `data.simulation.post.aprData.depositApr` | number | Weighted deposit APR |
| `data.simulation.post.aprData.borrowApr` | number | Weighted borrow APR |
| `data.simulation.post.aprData.rewardApr` | number | Total reward APR |
| `data.simulation.post.aprData.rewardDepositApr` | number | Reward APR on deposits |
| `data.simulation.post.aprData.rewardBorrowApr` | number | Reward APR on borrows |
| `data.simulation.post.aprData.intrinsicApr` | number | Intrinsic yield APR (e.g., stETH staking) |
| `data.simulation.post.aprData.intrinsicDepositApr` | number | Intrinsic yield APR portion from deposits |
| `data.simulation.post.aprData.intrinsicBorrowApr` | number | Intrinsic yield APR portion from borrows |
| `data.simulation.post.aprData.rewards` | object | Per-reward-token APR breakdown. Keys are reward token addresses. |
| `data.simulationError` | string | Error message if simulation failed |
| `data.quotes[].tx` | object | An EVM transaction ready to sign and broadcast. Send `to`, `data` and `value` as-is; do not re-encode them. |
| `data.quotes[].tx.to` | string | Target contract address |
| `data.quotes[].tx.data` | string | Encoded calldata |
| `data.quotes[].tx.value` | string | ETH value to send with the transaction |
| `data.quotes[].tx.description` | string | Human-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"). |
| `data.permissionTxns` | object[] | Approvals needed for this specific quote. Most integrators should use the deduplicated envelope-level `actions.permissions` instead. |
| `data.permissionTxns[].to` | string | Target contract address |
| `data.permissionTxns[].data` | string | Encoded calldata |
| `data.permissionTxns[].value` | string | ETH value |
| `data.permissionTxns[].description` | string | Human-readable description of the approval (e.g. "Approve borrow for AAVE_V3", "Approve ERC20") |
| `data.permissionTxns[].spender` | string | ERC-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` | object | Transaction calldata and approvals. Null for quote-only responses (no account provided). |
| `actions.transactions` | object[] | 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[].to` | string | Target contract address |
| `actions.transactions[].data` | string | Encoded calldata |
| `actions.transactions[].value` | string | ETH value to send with the transaction |
| `actions.transactions[].description` | string | Human-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.alternatives` | object[] | 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[].to` | string | Target contract address |
| `actions.alternatives[].data` | string | Encoded calldata |
| `actions.alternatives[].value` | string | ETH value to send with the transaction |
| `actions.alternatives[].description` | string | Human-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.permissions` | object[] | 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[].to` | string | Target contract address |
| `actions.permissions[].data` | string | Encoded calldata |
| `actions.permissions[].value` | string | ETH value |
| `actions.permissions[].description` | string | Human-readable description of the approval (e.g. "Approve borrow for AAVE_V3", "Approve ERC20") |
| `actions.permissions[].spender` | string | ERC-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. |

**Example response**

```json
{
  "success": true,
  "data": {
    "lender": "AAVE_V3",
    "quotes": [
      {
        "deltas": {
          "aggregator": "string",
          "tradeInput": 1,
          "tradeOutput": 1,
          "deltas": {}
        },
        "rateImpact": [
          {
            "marketUid": "AAVE_V3:8453:0x4200000000000000000000000000000000000006",
            "utilization": {
              "current": 1,
              "projected": 1
            },
            "borrowRate": {
              "current": 1,
              "projected": 1
            },
            "depositRate": {
              "current": 1,
              "projected": 1
            }
          }
        ]
      }
    ],
    "rateImpact": [
      {
        "marketUid": "AAVE_V3:8453:0x4200000000000000000000000000000000000006",
        "utilization": {
          "current": 1,
          "projected": 1
        },
        "borrowRate": {
          "current": 1,
          "projected": 1
        },
        "depositRate": {
          "current": 1,
          "projected": 1
        }
      }
    ],
    "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"
      }
    ]
  }
}
```

**Response `400`** — Validation error

**Response `429`** — Rate limited. Unauthenticated callers share a per-IP budget; send an `x-api-key` header to lift it. Retry with exponential backoff.

**Response `500`** — Unexpected server error. Safe to retry with backoff.

**Response `502`** — An upstream data source or protocol origin failed (`error.code` is `ORIGIN_FAILED`). `error.details` carries the per-origin status. This is also what a missing or malformed required parameter currently returns, rather than a 400.
