Liquidation Settlement
Withdraw Collateral for Sale
Move seized collateral out of the router to the designated sale recipient
POST
/
lending-external-securities-v2
/
api
/
liquidations
/
withdraw-collateral
/
{liquidationId}
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/withdraw-collateral/14" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"amount": "100", "marketId": "clx_secmarket_001"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/liquidations/withdraw-collateral/${liquidationId}`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ amount: '100', marketId })
});
const { data } = await res.json();
const tx = await wallet.sendTransaction(data.transaction);
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ amount: '100', marketId, txHash: tx.hash })
});
{
"success": true,
"data": {
"success": true,
"liquidationId": "14",
"recipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "withdrawCollateralForSale"
}
}
{
"success": true,
"data": {
"liquidationId": "14",
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b"
}
}
{
"success": false,
"error": {
"code": "RECIPIENT_FIXED",
"message": "Seized collateral can only be sent to the sale recipient designated for this market (0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473). The market admin can rotate it from a quiet router through the sale-recipient rotation flow.",
"txHash": null,
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473"
}
}
{
"success": false,
"error": {
"code": "ROUTER_OPERATOR_ROLE_MISSING",
"message": "Wallet 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 does not hold OPERATOR_ROLE on the liquidation router 0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"txHash": null,
"calldata": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"description": "Grant OPERATOR_ROLE to 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 on the liquidation router (requires router DEFAULT_ADMIN_ROLE)"
},
"saleRecipient": null
}
}
Transfers seized collateral from the liquidation router to the market’s sale recipient, so it can be sold off-platform. This is step one of the manual settlement workflow, signed by a holder of the router’s
A record on a router in two-step mode does not sell itself. The operator withdraws the collateral, arranges the sale through their own channel, and reports the proceeds back with Report Partial Sale or Settle Liquidation. Where the atomic sale is offered, Sell Pending Liquidation sells a whole record to the sale recipient instead, but only before any of its collateral is withdrawn.
Confirming with
OPERATOR_ROLE.
Once collateral leaves the router, the record can only settle with sale proceeds reported against it. If the sale realizes nothing, the router refuses a settlement at zero. The market’s record then waits for the 7 day write-off in Handle Liquidation Timeout. Withdraw only what a sale is arranged for.The destination is not yours to choose. The lender of record fixed the sale recipient when it adopted the market, and the router call carries no recipient at all. The router administrator can rotate it only through an announced change that takes effect after a one-hour delay and is refused while any record on the router is open. This API does not expose that rotation.
Path Parameters
string
required
Liquidation ID on the market’s router, from Get Pending Liquidations or from the Liquidate Loan response.
Body Parameters
string
required
Collateral to withdraw, as a decimal string in collateral token units, at most as many decimals as the collateral token has. Must be greater than zero. An amount above
collateralRemaining is not refused here; the router reverts it. Required on the confirm call too.string
The destination is fixed on the market, so this field cannot choose one. Supply nothing, or supply exactly the market’s
saleRecipient. Any other address is refused with RECIPIENT_FIXED, and the refusal names the recipient the market will accept.string
Names the market whose liquidation you mean. Every market runs its own liquidation router and IDs restart at
1 on each of them, so the same liquidationId can exist on several markets in one instance. Supply this when it does, otherwise the call is refused with AMBIGUOUS_LIQUIDATION_ID and the response lists the candidates. Also accepted as a query parameter. At most 100 characters.string
Hash of the transaction you broadcast for this operation. Send it together with
amount 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.The wallet that signs must hold
OPERATOR_ROLE on the market’s liquidation router. This endpoint checks the role against your instance’s primary verified wallet, since it takes no signer address. If that wallet lacks the role, the calldata is not returned: the response carries ROUTER_OPERATOR_ROLE_MISSING along with the calldata that grants it.Response Fields
object
Show child attributes
Show child attributes
string
Liquidation ID, echoed back.
boolean
Nested inside
data on the calldata response.string
SIGN_TRANSACTION. Returned when txHash is omitted.object
Unsigned transaction,
{ to, data, value, chainId }, targeting the liquidation router. Returned when txHash is omitted.string
withdrawCollateralForSale. Returned when txHash is omitted.string
Address the collateral will reach. Returned when
txHash is omitted.string
The destination fixed for this market, the same address as
recipient. Returned when txHash is omitted.string
Transaction hash. Returned when confirming with
txHash.Withdrawal is repeatable. Take the collateral out in tranches as sales are arranged. Each call reduces
collateralRemaining on the router. The liquidation’s status stays PENDING throughout, so track progress through collateralRemaining rather than status. If the router administrator set a sale rate limit for the collateral token, a tranche above it reverts.If the liquidation ID exists on-chain but has no Trusset record, the endpoint adopts it automatically by scanning your instance’s routers. Liquidations triggered outside this API are therefore still settleable through it.
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/withdraw-collateral/14" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"amount": "100", "marketId": "clx_secmarket_001"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/liquidations/withdraw-collateral/${liquidationId}`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ amount: '100', marketId })
});
const { data } = await res.json();
const tx = await wallet.sendTransaction(data.transaction);
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ amount: '100', marketId, txHash: tx.hash })
});
{
"success": true,
"data": {
"success": true,
"liquidationId": "14",
"recipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "withdrawCollateralForSale"
}
}
{
"success": true,
"data": {
"liquidationId": "14",
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b"
}
}
{
"success": false,
"error": {
"code": "RECIPIENT_FIXED",
"message": "Seized collateral can only be sent to the sale recipient designated for this market (0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473). The market admin can rotate it from a quiet router through the sale-recipient rotation flow.",
"txHash": null,
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473"
}
}
{
"success": false,
"error": {
"code": "ROUTER_OPERATOR_ROLE_MISSING",
"message": "Wallet 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 does not hold OPERATOR_ROLE on the liquidation router 0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"txHash": null,
"calldata": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"description": "Grant OPERATOR_ROLE to 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 on the liquidation router (requires router DEFAULT_ADMIN_ROLE)"
},
"saleRecipient": null
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | amount is not a positive decimal string or has more decimals than the collateral token, recipientAddress is not a valid address, marketId is longer than 100 characters, or txHash is present but malformed |
AMBIGUOUS_LIQUIDATION_ID | 400 | This ID exists on more than one market in your instance. The error carries candidates; resend with marketId |
ALREADY_SETTLED | 400 | The liquidation is settled or written off, here or on the router |
RECIPIENT_FIXED | 400 | recipientAddress is not the market’s designated sale recipient. The error carries saleRecipient |
SALE_RECIPIENT_NOT_SET | 400 | The market has no lender of record yet, so no destination for seized collateral has been designated |
SALE_RECIPIENT_TRANSFER_RESTRICTED | 400 | The collateral token blocks the transfer to the designated recipient. The error carries saleRecipient |
WALLET_NOT_CONFIGURED | 400 | No verified wallet is registered on this instance to resolve the signer against |
ROUTER_OPERATOR_ROLE_MISSING | 400 | Your instance’s primary verified wallet lacks OPERATOR_ROLE. The error carries grant calldata for the router admin |
TX_NOT_VERIFIED | 400 | The confirmed transaction targets a different liquidation |
WITHDRAW_TX_REVERTED | 400 | The withdrawal could not be prepared or recorded, for example because a chain read failed. error.txHash carries the hash when one exists |
ROLE_UNVERIFIABLE | 400 | The role check could not read the router. Nothing was built. Retry shortly |
LIQUIDATION_NOT_FOUND | 404 | No liquidation with that ID on your instance, and none could be adopted from chain |
MARKET_NOT_FOUND | 404 | marketId was supplied but names no market on your instance |
LIQUIDATION_ON_VENUE | 409 | The record’s Dutch auction is still open, so the router holds none of its collateral |
ROUTER_UNRESOLVED | 503 | The market’s liquidation router could not be read. Retry shortly |
ROUTER_UNREADABLE | 503 | The router could not be read to resolve the sale recipient. Nothing was built. Retry shortly |
txHash can also return any transaction verification error. A withdrawal that reverted on-chain is refused there with TX_REVERTED.⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/liquidations/withdraw-collateral/14" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"amount": "100", "marketId": "clx_secmarket_001"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/liquidations/withdraw-collateral/${liquidationId}`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ amount: '100', marketId })
});
const { data } = await res.json();
const tx = await wallet.sendTransaction(data.transaction);
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ amount: '100', marketId, txHash: tx.hash })
});
{
"success": true,
"data": {
"success": true,
"liquidationId": "14",
"recipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473",
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "withdrawCollateralForSale"
}
}
{
"success": true,
"data": {
"liquidationId": "14",
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b"
}
}
{
"success": false,
"error": {
"code": "RECIPIENT_FIXED",
"message": "Seized collateral can only be sent to the sale recipient designated for this market (0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473). The market admin can rotate it from a quiet router through the sale-recipient rotation flow.",
"txHash": null,
"saleRecipient": "0x5a72e0b41d3f8c62079ae4b1d38f0c95261ba473"
}
}
{
"success": false,
"error": {
"code": "ROUTER_OPERATOR_ROLE_MISSING",
"message": "Wallet 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 does not hold OPERATOR_ROLE on the liquidation router 0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"txHash": null,
"calldata": {
"to": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
"data": "0x...",
"description": "Grant OPERATOR_ROLE to 0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52 on the liquidation router (requires router DEFAULT_ADMIN_ROLE)"
},
"saleRecipient": null
}
}
