Deposits & Redemptions
Redeem
Redemption calldata with a fill quote
POST
/
lending-external-securities-v2
/
api
/
vaults
/
{vaultId}
/
redeem
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/vaults/cmssh8t2u0003cghxkx1w1fwd/redeem" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"shares": "500", "holderAddress": "0x6a6cba16dad34f7ea7ecbcdbf050f8146b942d6b"}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/vaults/${vaultId}/redeem`,
{
method: 'POST',
headers: { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' },
body: JSON.stringify({ shares: '500', holderAddress: await signer.getAddress() })
}
);
const { data } = await res.json();
if (data.priceWarning) console.warn(data.priceWarning);
if (data.willFillFully === false) {
console.log(`Partial fill: about ${data.expectedPayout} paid, the rest stays in shares`);
}
const tx = await signer.sendTransaction(data.transaction);
await tx.wait();
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x4d0cfe39a3431b145d1a1393d901a36d459a1b13",
"data": "0xdb006a75...",
"value": "0",
"chainId": 11155111
},
"functionName": "redeem",
"note": "When market utilization blocks part of the value, the redemption fills partially: unpaid shares stay in the wallet.",
"maxPayableNow": "87500.0",
"willFillFully": true,
"expectedPayout": "506.25",
"assetsFullyReadable": true,
"priceWarning": null,
"confirmWith": { "endpoint": "confirm-tx", "txHash": true, "txType": "REDEEM" }
}
}
{
"success": false,
"data": null,
"error": {
"code": "NOTHING_REDEEMABLE",
"message": "The vault can pay nothing right now: no funds sit idle and every allocated market is fully lent out, so redeem() would revert without burning any shares. Retry once borrowers repay or the operator frees liquidity."
}
}
Builds the transaction that redeems vault shares for the vault’s asset at the current share price. The holder signs one transaction, with no approval step, because the vault burns its own shares. The payout goes to the signing wallet.
Redemptions cannot be paused, and on the current vault implementation no register examines them. What bounds them is liquidity: idle funds pay first, and beyond that the vault draws on its market positions as far as each market’s free liquidity allows. An instance that sees an unpublished vault as a distributor of record can redeem from it too.
Path Parameters
string
required
Vault ID.
Body Parameters
string
required
Shares to redeem as a decimal string, parsed at the vault’s
assetDecimals. Digits with an optional fraction, greater than zero.string
required
The wallet that will sign.
redeem burns the caller’s own shares, so the amount cannot be checked against a balance until the wallet is named. Omitting it, or sending something other than a 0x address, returns HOLDER_REQUIRED.Before the holder signs
When market utilization blocks part of the value, the redemption fills partially. The holder is paid what liquidity allows and the unpaid shares stay in the wallet.willFillFully and expectedPayout say so before the signature. The amount recorded on confirmation comes from the Redeemed event, meaning the assets actually paid, not the shares requested. Compare the two to detect a partial fill.
A redemption is quoted from totals read without their completeness flag, on purpose. An exit is the one thing a market that has gone dark must never be able to block. When
priceWarning is set, the shares still burn, at a price that understates the vault, and the difference stays with the holders who wait. Nothing blocks the redemption. Show the warning and let the holder decide.Response Fields
object
Show child attributes
Show child attributes
string
SIGN_TRANSACTION.object
to, data, value ("0") and chainId for the redeem call.string
redeem.string
The most the vault could pay any redemption at this moment, in its asset. The same figure as
redeemableNow on Get Vault. null when the chain read failed.boolean
Whether this redemption is expected to pay out in full.
false means a partial fill, null means it could not be established.string
What this redemption is expected to pay: the full value when
willFillFully is true, otherwise maxPayableNow. null when it could not be established.string
The partial-fill position in words, sized to this redemption when a partial fill is expected. Show it near your redeem control.
boolean
false when a market the vault funds would not answer, so the share price this redemption is quoted at leaves that position out. null when the chain read failed.string
Set when
assetsFullyReadable is false, stating that the quoted price understates the vault by an unknown amount. null otherwise.object
Report the hash to Confirm Transaction with
txType: "REDEEM".curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/vaults/cmssh8t2u0003cghxkx1w1fwd/redeem" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"shares": "500", "holderAddress": "0x6a6cba16dad34f7ea7ecbcdbf050f8146b942d6b"}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/vaults/${vaultId}/redeem`,
{
method: 'POST',
headers: { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' },
body: JSON.stringify({ shares: '500', holderAddress: await signer.getAddress() })
}
);
const { data } = await res.json();
if (data.priceWarning) console.warn(data.priceWarning);
if (data.willFillFully === false) {
console.log(`Partial fill: about ${data.expectedPayout} paid, the rest stays in shares`);
}
const tx = await signer.sendTransaction(data.transaction);
await tx.wait();
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x4d0cfe39a3431b145d1a1393d901a36d459a1b13",
"data": "0xdb006a75...",
"value": "0",
"chainId": 11155111
},
"functionName": "redeem",
"note": "When market utilization blocks part of the value, the redemption fills partially: unpaid shares stay in the wallet.",
"maxPayableNow": "87500.0",
"willFillFully": true,
"expectedPayout": "506.25",
"assetsFullyReadable": true,
"priceWarning": null,
"confirmWith": { "endpoint": "confirm-tx", "txHash": true, "txType": "REDEEM" }
}
}
{
"success": false,
"data": null,
"error": {
"code": "NOTHING_REDEEMABLE",
"message": "The vault can pay nothing right now: no funds sit idle and every allocated market is fully lent out, so redeem() would revert without burning any shares. Retry once borrowers repay or the operator frees liquidity."
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | shares is missing, not a positive decimal string, finer than the asset’s decimals, or too large. error.details names the field |
HOLDER_REQUIRED | 400 | holderAddress was omitted or is not an address |
REDEEMER_NOT_VERIFIED | 403 | The wallet is not verified on the vault’s identity register, on a vault whose earlier implementation still gates redemptions on it |
VAULT_NOT_FOUND | 404 | No such vault, or it is not visible to your instance |
VAULT_NOT_DEPLOYED | 409 | The vault has no on-chain address on record |
INSUFFICIENT_SHARES | 409 | The wallet holds no shares, or fewer than shares |
NOTHING_REDEEMABLE | 409 | The vault can pay nothing right now, or shares values to nothing at the current price. No shares would be burned |
VAULT_STATE_UNAVAILABLE | 503 | Whether your instance is a distributor of record in an unpublished vault could not be read from the chain. Retry shortly |
SERVICE_UNAVAILABLE | 503 | The vault records or your instance’s verified wallets could not be read. Retry shortly |
VAULT_REDEEM_FAILED | 500 | Unexpected failure. Retry, or contact support with the request ID |
⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/vaults/cmssh8t2u0003cghxkx1w1fwd/redeem" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"shares": "500", "holderAddress": "0x6a6cba16dad34f7ea7ecbcdbf050f8146b942d6b"}'
const res = await fetch(
`https://api.trusset.org/lending-external-securities-v2/api/vaults/${vaultId}/redeem`,
{
method: 'POST',
headers: { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' },
body: JSON.stringify({ shares: '500', holderAddress: await signer.getAddress() })
}
);
const { data } = await res.json();
if (data.priceWarning) console.warn(data.priceWarning);
if (data.willFillFully === false) {
console.log(`Partial fill: about ${data.expectedPayout} paid, the rest stays in shares`);
}
const tx = await signer.sendTransaction(data.transaction);
await tx.wait();
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x4d0cfe39a3431b145d1a1393d901a36d459a1b13",
"data": "0xdb006a75...",
"value": "0",
"chainId": 11155111
},
"functionName": "redeem",
"note": "When market utilization blocks part of the value, the redemption fills partially: unpaid shares stay in the wallet.",
"maxPayableNow": "87500.0",
"willFillFully": true,
"expectedPayout": "506.25",
"assetsFullyReadable": true,
"priceWarning": null,
"confirmWith": { "endpoint": "confirm-tx", "txHash": true, "txType": "REDEEM" }
}
}
{
"success": false,
"data": null,
"error": {
"code": "NOTHING_REDEEMABLE",
"message": "The vault can pay nothing right now: no funds sit idle and every allocated market is fully lent out, so redeem() would revert without burning any shares. Retry once borrowers repay or the operator frees liquidity."
}
}
