Skip to main content
POST
Liquidates a loan on either of two triggers. A loan qualifies when its health factor is below 1.0, and it qualifies when its term has run past its effective due date plus grace, whatever its health. A market that makes open-ended loans has only the first trigger. Where the seized collateral goes depends on the market’s useDutchAuction setting. With Dutch auctions disabled, collateral is seized and transferred to the market’s liquidation router, and a pending liquidation is created on the market and on the router. The response carries the router’s liquidationId, collateralSeized and debtRepaid, and settlement becomes a manual operator workflow. On a market whose router runs the atomic sale, the seized collateral is sold to the sale recipient at its standing bid in the same transaction, and the record settles at once. See Atomic sale. With Dutch auctions enabled, the collateral goes to the market’s auction venue and a Dutch auction opens. The market records its pending liquidation at the seizure, but the router holds nothing. The response carries auctionId, and liquidationId is the market’s own record ID rather than a router ID. The router takes part only if the auction expires with collateral unsold and Settle Expired Auction hands the remainder to it. A market priced from a live market price cannot enable Dutch auctions, and none can run before an auction venue is wired. A market whose lender of record declared AUCTION as its realization path is refused with 409 AUCTION_PATH_NOT_ENABLED while Dutch auctions are off, because the seizure would go to the router for a direct sale instead. Wire the venue with Wire Auction Module and turn on useDutchAuction with Update Market Config first. readiness.auctionPathMissing reports this state.
The signing wallet must hold LIQUIDATOR_ROLE on the market. Role state is reported in readiness but never blocks the calldata. You sign in your own environment, so the wallet this API knows about is not necessarily the one that will call. A wallet without the role has its transaction reverted on-chain rather than rejected here. Pass signerAddress to have readiness answer for the wallet you intend to use.

Path Parameters

string
required
The market’s record ID, as id on List Markets, not its contract address. See Market IDs. At most 100 characters.
integer
required
On-chain loan ID. Must be a positive integer.

Body Parameters

object
EIP-712 signed price built with Sign Price and signed by the oracle’s authorized signer. The contract applies it atomically with the liquidation, before it reads the price. Omit it to price against the stored oracle value. Before building, the API checks the quote against the oracle: it must verify against an authorized signer, be dated after the stored price, and stay inside the oracle’s deviation band. Otherwise the call is refused with INVALID_SIGNED_PRICE, SIGNED_PRICE_OUTDATED or PRICE_DEVIATION_TOO_LARGE. An accepted quote lifts the PRICE_STALE refusal, since the liquidation then runs on the quoted price. Without one, push a fresh price with Sync Oracle Price first. A market that prices from an external feed refuses a signed price with EXTERNAL_FEED_ACTIVE, and a market with a fixed price with FIXED_PRICE_ACTIVE.
string
Wallet you intend to liquidate with. Used to resolve readiness against that address rather than against your instance’s primary verified wallet. It does not appear in the transaction. On a collateral token whose ERC-1400 granularity() is above one base unit it is required: the exact liquidation is simulated from it before the calldata is returned, and without it the call is refused with COLLATERAL_GRANULARITY_UNCHECKED. When the granularity or the simulation cannot be read, the calldata is returned and the contract decides. Anything that is not a valid address is ignored.
string
Hash of the transaction you broadcast for this operation. Send it to confirm the transaction and record the result. Omit it to receive the calldata. A value that is not 0x followed by 64 hex characters is refused with 400 VALIDATION_ERROR and nothing is built or recorded. null or an empty string counts as omitted.

Response Fields

Without txHash the response is the unsigned liquidate call, alongside a readiness object describing every gate the contract passes through.
object

Atomic sale

A market priced from a live market price (MARKET) whose lender of record declared EXCHANGE_SALE can run its router in atomic mode, switched on with Set Atomic Mode. A liquidation there sells the seized collateral to the sale recipient at its standing bid inside the liquidation transaction, and the record settles in the same block: status: SETTLED, realization: ATOMIC. If the sale recipient cannot buy, the whole liquidation reverts and the loan stays liquidatable. The calldata is refused before anything is signed:
  • 409 ATOMIC_SALE_UNAVAILABLE when the router runs atomic mode on a market where the atomic sale is not offered: not MARKET-priced, or not declared EXCHANGE_SALE. details carries loanId, priceSource, realizationMode and reasonCode. The router administrator switches the router back to two-step first, then the loan is liquidated the two-step way.
  • 409 ATOMIC_BUYER_UNAVAILABLE when the sale recipient cannot buy. On the market’s state, details carries reasonCode, saleRecipient and routerAddress. Without a signedPrice, the loan itself is checked too. For this loan, details adds loanId, expectedPayment ({ amount, raw }) and collateralAmount (in base units), and reasonCode can also be INTAKE_CLOSED: the market reports that the router would not take this sale although every buyer fact readable here passes. The sale recipient can post or renew its bid with Set Sale Bid, or the router administrator can switch to two-step.
  • 409 LIQUIDATION_NOT_READY when, on that same loan check, the collateral token refuses delivery of the loan’s seized collateral to the router.
A confirm that sees an atomic sale it cannot read back answers 503 ROUTER_UNREADABLE and records nothing, so the liquidation is never booked as two-step by mistake. Retry the confirm.

What One Call Realizes

On the health trigger a liquidation does not close the whole loan. The debt one call can discharge is capped by closeFactor, and the collateral seized for it is marked up by liquidationPenalty at the current price. A deeply underwater loan therefore needs several liquidations to clear. When the collateral runs out before the debt does, all of it is seized. The remaining debt is then written off at once, against the insurance fund first and the pool second. On the term trigger the whole debt is realized in one call, marked up by the loan’s term penalty instead of the liquidation penalty. The seizure takes only the collateral that requires, and the rest goes back to the borrower in the same transaction. Collateral that falls short is taken whole and the remaining debt is written off the same way. On the auction path the venue takes closeFactor of the collateral against the same share of the debt, or all of it when the collateral is worth less than that debt. A term realization routed to an auction sizes its slice at the auction’s floor price rather than at the oracle price. There is no auto-sell for external securities. Once collateral reaches the router in two-step mode it stays there until an operator sells it and settles the proceeds. See Settle Liquidation. The atomic sale above sells to the sale recipient’s standing bid inside the liquidation, and only where the router administrator switched it on. An auction sells only to verified bidders who take the price the venue quotes through Bid on Auction.

Error Codes

Refusals from the readiness, loan, atomic and granularity checks carry the full readiness object alongside code and message, so the failing gate can be inspected without a second call. The examples above shorten it, and the calldata example shortens readiness.atomic. The loan-level refusals also carry loan. When the loan itself cannot be read, the calldata is returned and the contract decides. Confirming with txHash can also return any transaction verification error.
A missing LIQUIDATOR_ROLE shows as liquidatorRoleReady: false in readiness rather than as an error. Resolve it through Set Liquidator Role when the market admin drives the grant, or let a connected liquidation bot hold it.