---
title: "Prepare an Aave position unwind"
method: POST
path: "/positions/{address}/unwind"
tags: ["Utilities"]
---

# Prepare an Aave position unwind

`POST /positions/{address}/unwind`

Returns an **unsigned** `Pool.withdraw` transaction that exits an Aave position straight to the project's deposit address, so the existing deposit pipeline ingests the proceeds. Nothing is executed: the holding EOA owns the aTokens, so only it can authorise the withdraw, and the service holds no key on this path. The amount is capped server-side against Aave's full withdraw validation and is refused outright if the proceeds would fall foul of the project's deposit policy — that check happens here because this is the last point before an irreversible signature.

## Path parameters

- `address` string, required — The EOA holding the position. It signs and sends the returned transaction.

## Headers

- `x-api-key` string, required — API key for authentication
- `x-api-version` string — API version identifier (e.g. "2026-04.amazon"). Optional today, will become required in a future release.

## Request body

- PrepareUnwindRequestBody
  - `account` string, required — The registered deposit account the proceeds go to. The recipient is resolved from this server-side; it is never taken from the request directly.
  - `market` string, required — The Aave market's Pool address, as returned in a position's `market.address`. Required rather than inferred, because a chain can host several markets.
  - `chainId` integer, required
  - `asset` string, required — The supplied underlying token to withdraw
  - `amount` string — Base units to withdraw. Omit for the largest amount currently permitted. An amount above that maximum is rejected rather than silently reduced.

## Response `200`

Unsigned withdraw transaction

- PrepareUnwindResponse
  - `transaction` object, required — Unsigned transaction for the holding EOA to sign and send. The backend never executes it — the EOA holds the aTokens, so only it can authorise the withdraw.
    - `to` string, required
    - `data` string, required
    - `value` string, required
    - `chainId` number, required
  - `amount` string, required — Base units the transaction will withdraw
  - `isFullExit` boolean, required — True when the whole position is being withdrawn, in which case the calldata uses the max-uint sentinel so interest accrued before the transaction lands is swept too.
  - `recipient` string, required — The deposit address the proceeds are sent to, resolved from the registered account. Echoed so it is auditable.
  - `constraints` string[], required — Why the amount is below the supplied balance, if it is. Empty for an unconstrained full exit.

## Other responses

- `400` — Invalid request, unauthorized, no such position, an amount above the withdrawable maximum, or proceeds the deposit policy would reject
- `403` — API key lacks the required deposits scope, or the account belongs to another project

---

[API](https://skmtc.net/rhinestonewtf/apis/deposit-service-api.md) · [All operations](https://skmtc.net/rhinestonewtf/apis/deposit-service-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/rhinestonewtf/deposit-service-api/revisions/c9aa3f252e4f/schema)
