Queue
Accept Lender Role
Build the transaction that takes a market lender-of-record role
POST
/
lending-external-securities-v2
/
api
/
markets
/
queued
/
{marketAddress}
/
accept
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/queued/0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b/accept" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"admin": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"issuer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"collateralAgent": "0x8b17e4d90c3a25f6e1d09b7c4a3f52e86d1c0b94",
"saleRecipient": "0x2f6a0d83c5e19b47d2a8c6f1e03b95d74a2c8e16",
"liquidationOperator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"oracleOwner": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"priceSigner": "0x9c4d27e1a5b8f03d6e2c71a49b0f58d3e6a1c2b7",
"realizationMode": "ISSUER_REDEMPTION",
"liquidityCommitment": "250000",
"maxFixedRateBps": 1500,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"assetDataHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90"
}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/queued/${marketAddress}/accept`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const terms = {
admin, issuer, collateralAgent, saleRecipient,
liquidationOperator, oracleOwner, priceSigner,
realizationMode: 'ISSUER_REDEMPTION',
liquidityCommitment: '250000',
assetDataHash: reviewedHash
};
let res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(terms) });
let { data } = await res.json();
if (data.claimFlow) {
const announce = await wallet.sendTransaction(data.transaction);
await announce.wait();
await new Promise((resolve) => setTimeout(resolve, data.claimDelaySeconds * 1000));
res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...terms, claimSalt: data.claimSalt })
});
({ data } = await res.json());
}
const tx = await wallet.sendTransaction(data.transaction);
await tx.wait();
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xf1ad12f5698f58badd8a662acffccb067a2ddb8a",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "acceptCuratorRole",
"marketAddress": "0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b",
"signer": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"identityRegistry": null,
"borrowerRegistry": null,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"borrowAsset": {
"address": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"symbol": "USDC",
"decimals": 6
},
"generation": "TWO_REGISTERS",
"installedRegister": null,
"borrowerProfile": null,
"providerProfile": null,
"requiredFollowUp": null,
"terms": {
"admin": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"issuer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"collateralAgent": "0x8b17e4d90c3a25f6e1d09b7c4a3f52e86d1c0b94",
"saleRecipient": "0x2f6a0d83c5e19b47d2a8c6f1e03b95d74a2c8e16",
"liquidationOperator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"oracleOwner": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"priceSigner": "0x9c4d27e1a5b8f03d6e2c71a49b0f58d3e6a1c2b7",
"identityRegistry": null,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"liquidator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"vault": null,
"liquidityCommitment": "250000000000",
"realizationMode": "ISSUER_REDEMPTION",
"claimSalt": "0x0000000000000000000000000000000000000000000000000000000000000000",
"maxFixedRateBps": 1500,
"assetDataHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90"
},
"assetData": {
"acknowledged": true,
"contentHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90",
"version": 1,
"attestor": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"factorySupport": true,
"note": "This adoption records your approval of asset data version 1 (0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90). The factory refuses the whole adoption if the issuer re-attests before it mines."
},
"handoverNote": "Adoption assigns every regulated role on the market and its router, authorizes the price signer, installs the registers you name, grants the liquidator and connects the vault, and hands the oracle, the rate model and the reserve to the owners you name, all inside this one transaction. Nothing is left for anyone to accept afterwards; the vault's own draw cap is the only step that follows, signed by the vault operator.",
"confirmWith": {
"endpoint": "confirm-accept",
"txHash": true
}
}
}
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xf1ad12f5698f58badd8a662acffccb067a2ddb8a",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "commitCuratorClaim",
"claimFlow": true,
"commitment": "0x3f9e1c7a5b2d8046e1f9a3c7d5b20e8f4a6c1d9b7e3f5a2c8d0b4e6f1a9c3d7e",
"claimSalt": "0x7c2e9a4f1b6d3e8c5a0f7b2d9e4c1a6f3b8d5e0c7a2f9b4d1e6c3a8f5b0d2e7c",
"claimDelaySeconds": 600,
"claimWindowSeconds": 259200,
"marketAddress": "0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b",
"signer": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"description": "Announce the claim on this open market. After 10 minutes, call accept again with the identical terms and this claimSalt to receive the acceptCuratorRole transaction; the announcement lapses after 72 hours.",
"confirmWith": {
"endpoint": "accept",
"retryWith": {
"claimSalt": "0x7c2e9a4f1b6d3e8c5a0f7b2d9e4c1a6f3b8d5e0c7a2f9b4d1e6c3a8f5b0d2e7c"
}
}
}
}
{
"success": false,
"error": {
"code": "ASSET_DATA_ACKNOWLEDGEMENT_REQUIRED",
"message": "The issuer attested asset data for this market (version 1, 0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90). Read the bundle, then name the hash you reviewed as assetDataHash in the adoption terms so the adoption records your approval of that version; pass acknowledgeAssetData: false to adopt without acknowledging any version.",
"details": {
"standing": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90",
"standingVersion": 1
}
}
}
{
"success": false,
"error": {
"code": "CLAIM_PENDING",
"message": "The claim was announced and becomes actionable at 2026-09-26T10:24:00.000Z. Call accept again with the identical terms and claimSalt after that moment."
}
}
Returns the transaction that takes a market’s lender-of-record role. The adopting institution names every party on the market, declares how seized collateral is realized, and approves the asset data version it reviewed. The factory does all of it in one transaction, signed by one of this instance’s verified wallets, and either every part lands or none does. See Lender of record.
Three conditions must hold before anything is built:
A whitelist is checked as on Set Identity Gates: never the borrower register of a
The announcement lapses after
The claim announcement, on the first call of an open-market claim:
Adoption is final: no path returns the market to seeking a lender of record. Every address in the terms receives its role in the same transaction. Check each one before signing. The
saleRecipient is the fixed destination for seized collateral, and rotating it is not available through this API. Even the router admin can only rotate it through an announced, one-hour-delayed flow that is refused while any realization is in flight.- Trusset approved this account to act as a lender of record. Otherwise
403 CURATOR_NOT_APPROVED. - One of this instance’s verified wallets is nominated on the market, or the market is open to claimants beyond its candidates. A claim on an open market takes two calls, see Claim an open market.
- The market still seeks a lender of record.
signer. It becomes the market’s operator wallet: it receives the fixed operator share of repaid interest and is one of the two kinds of depositor the market accepts directly. Rotate Operator Wallet changes it later.
Path Parameters
string
required
Market contract address,
0x followed by 40 hex characters. It must be a market of the v2 lending factory.Body Parameters
Parties
Seven parties are required. Each is a checksum-valid address that is not the zero address. One wallet may hold several of them.string
required
Receives
DEFAULT_ADMIN_ROLE on the market and on its liquidation router, and owns the insurance fund.string
required
Receives
ISSUER_ROLE on the market and owns the interest rate model, so it governs the rate and term offering from here on. It also becomes the wallet that attests the market’s asset data.string
required
Recorded as the pledgee on every collateral lock the market’s adapter makes. It carries no capability on the market, the adapter or the router.
string
required
Where seized collateral goes when it is withdrawn for sale. The collateral token must permit the delivery from the market’s router to this address, or the call is refused with
SALE_RECIPIENT_NOT_ELIGIBLE.string
required
Receives
OPERATOR_ROLE on the market’s liquidation router, which drives settlement. Naming a wallet this instance holds lets settlement run through this API.string
required
Owns the market’s price oracle.
string
required
Authorized as the oracle’s price signer. It is the only one: a market seeking a lender of record has no signer at all.
Realization and commitment
string
required
How seized collateral is turned into money on default:
EXCHANGE_SALE, ISSUER_REDEMPTION or AUCTION.The price source limits the choice. EXCHANGE_SALE is available only on a MARKET-priced market, and AUCTION is refused there because such a market cannot run Dutch auctions. A FIXED market therefore takes ISSUER_REDEMPTION or AUCTION. The declaration puts the path on the record before any loan exists. Beyond these checks at adoption, no contract logic branches on it. The API offers the atomic sale only where EXCHANGE_SALE is declared, see Get Atomic Sale.string
default:"0"
Liquidity the lender of record declares for the market, as a decimal amount of the borrow asset. Parsed at the borrow asset’s decimals. The factory records it and emits it with the adoption. Nothing in the contracts enforces it.
integer
Ceiling on any fixed borrower rate the rate model owner can set later, in basis points. Integer, 1 to 50000. Once recorded it can only move down. Omit it to record no ceiling.On a
FIXED market the ceiling must not be below the rate new loans are stamped with, or the adoption reverts on-chain. The API does not check this before building.Registers and provisioning
string
Borrower register for a market that has none. Only a nominated wallet may bring one. It is ignored when the deployer already installed a register, which stands. A
MARKET-priced market must end up with one, and it must qualify as a professional gate, see Professional borrowers.It must answer isVerified(address), as an ERC-3643 identity registry, an ONCHAINID-based register and the Trusset register all do. Omit it, or send the zero address, to adopt without one where the price source allows.The previous Trusset ID Register, 0xE9114c40934f6fB6BB317935156b731f7A86D006, takes no new identities and is refused with IDENTITY_REGISTRY_RETIRED, here and in providerRegistry. Name the current one, 0xEf244c4Bd4d71Bd9A30EDF6Edef7CCC72642291a. A borrower register the deployer installed is not refused when it is the previous one: the adoption goes through, installedRegister carries retired: true, and the market admin moves the gate afterwards. See The Previous Trusset ID Register.string
A verification profile key of your instance, 1 to 60 letters, digits,
- or _. Its eligibility register is used as identityRegistry. Sent with identityRegistry, both must name the same register, otherwise GATE_PROFILE_CONFLICT.string
The register every vault on the market examines its depositors against. Installed when the market carries none. The deployer’s
proposedProviderRegistry is a suggestion only: this field decides.string
A verification profile key whose eligibility register is used as
providerRegistry, with the same rules as identityRegistryProfile.string
The ID of a whitelist of your instance, 1 to 64 letters, digits,
- or _, used as identityRegistry. Not accepted beside identityRegistryProfile, and refused on a MARKET-priced market. See Whitelists as Gates.string
The ID of a whitelist of your instance, used as
providerRegistry. Not accepted beside providerRegistryProfile.boolean
true confirms that the whitelist named as providerRegistry lists identified wallets only. Required whenever providerRegistry is a whitelist, whether named by ID or by address. confirmWith.body carries it to Confirm Lender Role, which writes it to the audit record of the adoption.string
Wallet granted
LIQUIDATOR_ROLE on the market in the same transaction. It can trigger a seizure and configure nothing. Omitted or zero on a TWO_REGISTERS market, the API names the signing wallet.string
One of this instance’s own vaults, registered on the market as a just-in-time liquidity source with vault liquidity switched on. The vault must settle in the market’s borrow asset and be operated by the signing wallet. The vault’s own draw cap remains the one step left, signed by the vault operator.The vault’s investors must meet the market’s provider gate, under the rules of Register Vault. A vault with its own register needs
providerRegistry to be that register or none (PROVIDER_GATE_MISMATCH). A vault without one needs a providerRegistry, since nothing else would examine its depositors (DEPOSITOR_GATE_REQUIRED). It must be the register the vault adopted from the first market it funded, or, before it adopted one, the provider register of every market it funds (PROVIDER_GATE_MISMATCH).MARKET market (ACCESS_LIST_NOT_ALLOWED), never a register on the earlier single-register implementation (ACCESS_LIST_NOT_ALLOWED), kept for the right side (ACCESS_LIST_PURPOSE_MISMATCH), and as provider register only when your instance keeps it or one of its wallets owns or manages it (ACCESS_LIST_NOT_CONTROLLED) and with attestIdentifiedMembers: true (ACCESS_LIST_ATTESTATION_REQUIRED). Once the role is taken, Confirm Lender Role offers the step that makes the lender of record a manager of each whitelist gate.
providerRegistry, liquidator and vault need the current market implementation. A market on the earlier implementation, reported as SINGLE_REGISTER by Get Queued Market, refuses them with MARKET_UPGRADE_REQUIRED. It also needs a borrower register whatever its price source.
Asset data and open-market claims
string
The hash of the asset data version you reviewed,
0x followed by 64 hex characters. It must equal the issuer’s standing attestation, assetData.attested on Get Queued Market. The adoption then records the approval of exactly that version.boolean
Send
false to adopt without acknowledging any version. It takes effect only when assetDataHash is omitted.string
Salt for an open-market claim,
0x followed by 64 hex characters. Omit it on the first call and the API generates one. Send the returned value, with identical terms, on the second call. A nominee does not need it.Professional borrowers
AMARKET-priced market lends to professional borrowers only. Its borrower register must qualify as a professional gate: at least one verification profile admits wallets to it, and every profile that does, on any instance of the market’s network and environment, is limited to professional clients and in the REGISTER mode. The register deployed for your PROFESSIONAL profile, named with identityRegistryProfile: "PROFESSIONAL", is the simplest path. See Professional borrowers.
How that is enforced depends on who installs the register:
- You bring it, on a market the deployer left without one: a register that does not qualify is refused with
422 PROFESSIONAL_BORROWER_GATE_REQUIRED,details.field: "identityRegistry". - The deployer installed it: it stands, and the adoption is not refused. When it does not qualify, the response carries the warning
BORROWER_GATE_NOT_PROFESSIONALandrequiredFollowUp: { action: "SET_IDENTITY_GATES", reason: "BORROWER_GATE_NOT_PROFESSIONAL" }. Right after taking the role, replace the register through Set Identity Gates. Until then the API opens no loan and adds no liquidity on the market.
503 STATE_UNAVAILABLE and builds nothing.
Fixed price markets
AFIXED market prices its collateral at the price fixed at deployment for its whole life, and the adoption underwrites that value. The response carries it in fixedPrice and warns with FIXED_PRICE_MARK_DOWN_ONLY: after adoption the oracle owner and the price signer you name can only lower the price, within the deviation bound, and the oracle owner also holds the oracle’s upgrade authority. Name an oracle owner your institution controls itself, never the issuer or a borrower. When the asset data version you acknowledge states a different fixed price than the oracle holds, the response warns with FIXED_PRICE_NOT_AS_ATTESTED. The market lends against the oracle value. When the fixed price cannot be read, the call answers 503 ORACLE_STATE_UNREADABLE and builds nothing.
Approve the asset data
A market that carries an issuer attestation cannot be adopted silently. WithoutassetDataHash, the call is refused with 422 ASSET_DATA_ACKNOWLEDGEMENT_REQUIRED, and error.details names the standing hash and version. Read the bundle with Get Asset Data Bundle, then send the hash you read. Send acknowledgeAssetData: false instead only if the adoption should approve no version.
A hash other than the standing attestation is refused with 409 ASSET_DATA_STALE, with details.reviewed, details.standing and details.standingVersion. The issuer can still re-attest after the transaction is built. The factory then refuses the whole adoption on-chain, so a stale approval can never pass.
Claim an open market
When no wallet of this instance is nominated and the market is open, the first call returns acommitCuratorClaim transaction instead of the adoption. It announces a hash of the exact adoption call, so the terms stay private and transaction ordering cannot decide who takes the market. Only the wallet in signer can complete the claim.
1
Announce
Broadcast the returned
commitCuratorClaim transaction. Keep claimSalt.2
Wait
Wait
claimDelaySeconds (10 minutes) from the announcement. Calling earlier returns 409 CLAIM_PENDING with the moment it becomes actionable.3
Complete
Call this endpoint again with identical terms and the same
claimSalt. It returns the acceptCuratorRole transaction. Broadcast it with signer, then confirm it.claimWindowSeconds (72 hours) and its hash stays consumed. A later call returns 409 CLAIM_EXPIRED. Start again without claimSalt to receive a fresh one.
Any change to the terms changes the announced hash, including a newly attested asset data version. The API then answers with a new commitCuratorClaim for the new terms, and the wait starts again.
An open-market claimant is admitted by the borrower register the deployer installed. The API picks the first of this instance’s wallets, up to five, that the register verifies. None verified is 403 CANDIDATE_NOT_VERIFIED. A market with no borrower register cannot be claimed without a nomination (403 NOMINATION_REQUIRED), and a claimant cannot bring its own register.
Response Fields
The adoption transaction:object
Show child attributes
Show child attributes
string
SIGN_TRANSACTION.object
Unsigned transaction,
{ to, data, value, chainId }, addressed to the lending factory.string
acceptCuratorRole.string
Market address, lowercased.
string
The wallet that must sign: the nominated wallet, or on an open-market claim the wallet the register verified.
string
The borrower register the market will carry, or
null for none.string
The same value as
identityRegistry.string
The provider register the terms install, or
null.object
{ address, symbol, decimals } of the market’s settlement asset, or null when it could not be read.string
TWO_REGISTERS or SINGLE_REGISTER.object
The borrower register the deployer installed,
{ address, shape, usable, note }, or null. When it is the previous Trusset ID Register it also carries retired: true and currentRegistry, the current register lowercased, and note says that it takes no new identities.object
{ key, name, entityType, professionalOnly, requirementsHash } of your verification profile whose eligibility register the borrower register is, or null.object
The same for the provider register, or
null.object
The whitelist the borrower register is, as on Get Identity Gates, or
null.object
The whitelist the provider register is, or
null.boolean
Present and
true when the request carried attestIdentifiedMembers: true.object
FIXED markets only. The fixed price as the oracle holds it: priceWei, price, settlementSymbol, updatedAt, fixed, maxDeviationBps, realizationPaths, authority ({ oracleOwner, priceSigner } as named in the terms), note, and, when an asset data version is acknowledged, acknowledgedPriceWei and matchesAcknowledgedPrice. perWholeToken, neverStale, markDownOnly and oracleOwnerCanUpgrade are always true.object
{ action: "SET_IDENTITY_GATES", reason: "BORROWER_GATE_NOT_PROFESSIONAL" } when the deployer’s borrower register must be replaced after adoption, otherwise null. See Professional borrowers.object
The terms as encoded: the seven parties,
identityRegistry, providerRegistry, liquidator, vault, liquidityCommitment in the borrow asset’s smallest unit, realizationMode, claimSalt, maxFixedRateBps and assetDataHash. Absent optional values read null.object
{ acknowledged, contentHash, version, attestor, factorySupport, note }. acknowledged says whether this adoption approves a version.string
What the transaction hands over. On a
TWO_REGISTERS market the oracle, rate model and insurance fund pass to their named owners inside the transaction. On a SINGLE_REGISTER market each named owner must accept ownership afterwards.array
Present only when there is something to say, each
{ code, message }. VAULT_PREDATES_DISTRIBUTOR flags a vault that cannot yet collect the distributor share this market books for it, and also names the vault. BORROWER_GATE_NOT_PROFESSIONAL flags a MARKET market whose installed borrower register does not qualify as a professional gate. Its message says why. FIXED_PRICE_MARK_DOWN_ONLY and FIXED_PRICE_NOT_AS_ATTESTED are explained in Fixed price markets.object
{ endpoint: "confirm-accept", txHash: true }, with body: { attestIdentifiedMembers: true } when the request attested a whitelist. See Confirm Lender Role.object
Show child attributes
Show child attributes
string
SIGN_TRANSACTION.object
Unsigned transaction, addressed to the lending factory.
string
commitCuratorClaim.boolean
Always
true. Branch on it.string
The announced hash of the signer and the exact adoption call.
string
The salt inside the terms. Send it back unchanged on the second call.
integer
Wait before completing, read from the factory.
600.integer
How long the announcement stays usable.
259200.string
Market address, lowercased.
string
The wallet the announcement binds. Only it can complete the claim.
string
The next step in words.
object
{ endpoint: "accept", retryWith: { claimSalt } }. There is nothing to confirm: call this endpoint again.curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/queued/0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b/accept" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"admin": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"issuer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"collateralAgent": "0x8b17e4d90c3a25f6e1d09b7c4a3f52e86d1c0b94",
"saleRecipient": "0x2f6a0d83c5e19b47d2a8c6f1e03b95d74a2c8e16",
"liquidationOperator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"oracleOwner": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"priceSigner": "0x9c4d27e1a5b8f03d6e2c71a49b0f58d3e6a1c2b7",
"realizationMode": "ISSUER_REDEMPTION",
"liquidityCommitment": "250000",
"maxFixedRateBps": 1500,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"assetDataHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90"
}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/queued/${marketAddress}/accept`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const terms = {
admin, issuer, collateralAgent, saleRecipient,
liquidationOperator, oracleOwner, priceSigner,
realizationMode: 'ISSUER_REDEMPTION',
liquidityCommitment: '250000',
assetDataHash: reviewedHash
};
let res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(terms) });
let { data } = await res.json();
if (data.claimFlow) {
const announce = await wallet.sendTransaction(data.transaction);
await announce.wait();
await new Promise((resolve) => setTimeout(resolve, data.claimDelaySeconds * 1000));
res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...terms, claimSalt: data.claimSalt })
});
({ data } = await res.json());
}
const tx = await wallet.sendTransaction(data.transaction);
await tx.wait();
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xf1ad12f5698f58badd8a662acffccb067a2ddb8a",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "acceptCuratorRole",
"marketAddress": "0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b",
"signer": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"identityRegistry": null,
"borrowerRegistry": null,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"borrowAsset": {
"address": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"symbol": "USDC",
"decimals": 6
},
"generation": "TWO_REGISTERS",
"installedRegister": null,
"borrowerProfile": null,
"providerProfile": null,
"requiredFollowUp": null,
"terms": {
"admin": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"issuer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"collateralAgent": "0x8b17e4d90c3a25f6e1d09b7c4a3f52e86d1c0b94",
"saleRecipient": "0x2f6a0d83c5e19b47d2a8c6f1e03b95d74a2c8e16",
"liquidationOperator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"oracleOwner": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"priceSigner": "0x9c4d27e1a5b8f03d6e2c71a49b0f58d3e6a1c2b7",
"identityRegistry": null,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"liquidator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"vault": null,
"liquidityCommitment": "250000000000",
"realizationMode": "ISSUER_REDEMPTION",
"claimSalt": "0x0000000000000000000000000000000000000000000000000000000000000000",
"maxFixedRateBps": 1500,
"assetDataHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90"
},
"assetData": {
"acknowledged": true,
"contentHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90",
"version": 1,
"attestor": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"factorySupport": true,
"note": "This adoption records your approval of asset data version 1 (0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90). The factory refuses the whole adoption if the issuer re-attests before it mines."
},
"handoverNote": "Adoption assigns every regulated role on the market and its router, authorizes the price signer, installs the registers you name, grants the liquidator and connects the vault, and hands the oracle, the rate model and the reserve to the owners you name, all inside this one transaction. Nothing is left for anyone to accept afterwards; the vault's own draw cap is the only step that follows, signed by the vault operator.",
"confirmWith": {
"endpoint": "confirm-accept",
"txHash": true
}
}
}
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xf1ad12f5698f58badd8a662acffccb067a2ddb8a",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "commitCuratorClaim",
"claimFlow": true,
"commitment": "0x3f9e1c7a5b2d8046e1f9a3c7d5b20e8f4a6c1d9b7e3f5a2c8d0b4e6f1a9c3d7e",
"claimSalt": "0x7c2e9a4f1b6d3e8c5a0f7b2d9e4c1a6f3b8d5e0c7a2f9b4d1e6c3a8f5b0d2e7c",
"claimDelaySeconds": 600,
"claimWindowSeconds": 259200,
"marketAddress": "0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b",
"signer": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"description": "Announce the claim on this open market. After 10 minutes, call accept again with the identical terms and this claimSalt to receive the acceptCuratorRole transaction; the announcement lapses after 72 hours.",
"confirmWith": {
"endpoint": "accept",
"retryWith": {
"claimSalt": "0x7c2e9a4f1b6d3e8c5a0f7b2d9e4c1a6f3b8d5e0c7a2f9b4d1e6c3a8f5b0d2e7c"
}
}
}
}
{
"success": false,
"error": {
"code": "ASSET_DATA_ACKNOWLEDGEMENT_REQUIRED",
"message": "The issuer attested asset data for this market (version 1, 0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90). Read the bundle, then name the hash you reviewed as assetDataHash in the adoption terms so the adoption records your approval of that version; pass acknowledgeAssetData: false to adopt without acknowledging any version.",
"details": {
"standing": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90",
"standingVersion": 1
}
}
}
{
"success": false,
"error": {
"code": "CLAIM_PENDING",
"message": "The claim was announced and becomes actionable at 2026-09-26T10:24:00.000Z. Call accept again with the identical terms and claimSalt after that moment."
}
}
Error Codes
A malformed body is refused by its first offending field. The fourINVALID_ codes below carry error.details naming that field.
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | marketAddress, maxFixedRateBps, claimSalt, identityRegistryProfile, providerRegistryProfile, a whitelist ID or attestIdentifiedMembers failed validation |
INVALID_CURATOR_TERMS | 400 | A party address, identityRegistry, providerRegistry, liquidator or vault is missing where required, malformed, the zero address where a party is required, or fails its checksum |
INVALID_REALIZATION_MODE | 400 | realizationMode is missing or not EXCHANGE_SALE, ISSUER_REDEMPTION or AUCTION |
INVALID_LIQUIDITY_COMMITMENT | 400 | liquidityCommitment is not a non-negative decimal, or carries more decimal places than the borrow asset |
INVALID_CONTENT_HASH | 400 | assetDataHash is not a 32-byte hex hash, or acknowledgeAssetData is not a boolean |
GATE_PROFILE_CONFLICT | 400 | identityRegistry or providerRegistry names a different register than the profile sent beside it |
GATE_PROFILE_UNRESOLVED | 400 | A profile key could not be resolved for a reason that carries no code of its own |
GATE_SOURCE_CONFLICT | 400 | One side names both a verification profile and a whitelist, or an address that differs from the whitelist named beside it |
ACCESS_LIST_ATTESTATION_REQUIRED | 400 | providerRegistry is a whitelist and attestIdentifiedMembers is not true |
ACCEPT_FAILED | 400 | The transaction could not be built for a reason that carries no code of its own |
CURATOR_NOT_APPROVED | 403 | Trusset has not approved this account to act as a lender of record |
NOT_NOMINATED | 403 | No verified wallet of this instance is nominated, and the market is not open |
ACCESS_LIST_NOT_CONTROLLED | 403 | providerRegistry is a whitelist another instance curates, and no verified wallet of yours owns or manages it |
NOMINATION_REQUIRED | 403 | A claimant nobody nominated brought a borrower register, or the open market has no borrower register to admit one |
CANDIDATE_NOT_VERIFIED | 403 | None of the wallets checked is verified on the register the open market admits claimants through |
MARKET_NOT_V2 | 404 | The address is not a market of the v2 lending factory this instance deploys to |
MARKET_NOT_DEPLOYED | 404 | No deployment for this market could be read from the lending factory |
PROFILE_NOT_FOUND | 404 | identityRegistryProfile or providerRegistryProfile names no verification profile of this instance |
ACCESS_LIST_NOT_FOUND | 404 | identityRegistryAccessList or providerRegistryAccessList names no whitelist of this instance on this network that is not archived |
VAULT_NOT_FOUND | 404 | vault is not a vault of this instance, or it is archived |
NOT_SEEKING_CURATOR | 409 | The market already has a lender of record. The message names it |
REALIZATION_MODE_UNAVAILABLE | 409 | AUCTION was declared on a MARKET-priced market |
REALIZATION_BASIS_UNAVAILABLE | 409 | EXCHANGE_SALE was declared on a NAV, ORACLE or FIXED market. Declare ISSUER_REDEMPTION or AUCTION |
SIGNER_SET_NOT_CLEAN | 409 | The market’s oracle reports a different number of authorized signers than adoption requires |
MARKET_UPGRADE_REQUIRED | 409 | providerRegistry, liquidator or vault was sent for a market on the earlier implementation |
ACCESS_LIST_NOT_ALLOWED | 409 | A whitelist was named as the borrower register of a MARKET market, or as a register of a market on the earlier single-register implementation. details carries field, reason and address |
ACCESS_LIST_PURPOSE_MISMATCH | 409 | A whitelist is kept for the other side: DEPOSITOR as identityRegistry, or BORROWER as providerRegistry |
ELIGIBILITY_REGISTER_NOT_SET | 409 | The named profile has no eligibility register |
PROVIDER_GATE_MISMATCH | 409 | providerRegistry differs from the register vault admits its depositors against: its own, the one it adopted, or the provider register of a market it funds. Also a vault without a register of its own that funds no market while its shares are still held. The message starts with the vault’s name |
DEPOSITOR_GATE_REQUIRED | 409 | vault has no register of its own and the terms name no provider register |
ASSET_MISMATCH | 409 | vault settles in a different asset than the market |
VAULT_NOT_OPERATORS | 409 | vault is operated by a different wallet than the one signing the adoption |
ASSET_DATA_STALE | 409 | assetDataHash is not the standing attestation. details carries reviewed, standing, standingVersion and attestedAt |
ASSET_DATA_NONE | 409 | assetDataHash was sent but the issuer attested no asset data for this market |
FACTORY_UPGRADE_REQUIRED | 409 | assetDataHash was sent but the factory records no asset data attestation |
CLAIM_PENDING | 409 | The open-market claim was announced less than claimDelaySeconds ago. The message names the moment it becomes actionable |
CLAIM_EXPIRED | 409 | The announcement lapsed. Start again without claimSalt |
WALLET_NOT_CONFIGURED | 412 | This instance has no verified wallet |
IDENTITY_REGISTRY_REQUIRED | 422 | The market ends up without a borrower register where one is required: a MARKET-priced market, or a market on the earlier implementation |
PROFESSIONAL_BORROWER_GATE_REQUIRED | 422 | On a MARKET market without an installed register, the borrower register in the terms does not qualify as a professional gate. details carries field and priceSource |
IDENTITY_REGISTRY_INCOMPATIBLE | 422 | A register named in the terms does not answer isVerified(address) in a shape the market reads |
IDENTITY_REGISTRY_RETIRED | 422 | identityRegistry or providerRegistry in the terms is the previous Trusset ID Register, which takes no new identities. details carries field, registry and currentRegistry. Name the current register |
SALE_RECIPIENT_NOT_ELIGIBLE | 422 | The collateral token refuses delivery from the market’s router to saleRecipient. The message names the blocked party and the remedy |
ORACLE_FEED_UNUSABLE | 422 | On an ORACLE market, the feed cannot answer a price inside the staleness window right now |
ASSET_DATA_ACKNOWLEDGEMENT_REQUIRED | 422 | The market carries an attestation and neither assetDataHash nor acknowledgeAssetData: false was sent. details carries standing and standingVersion |
MARKET_VERIFICATION_UNAVAILABLE | 503 | The address could not be checked against the v2 factory. Retry shortly |
ORACLE_STATE_UNREADABLE | 503 | The market’s oracle could not be read to check its signer set, or on a FIXED market its fixed price. Retry shortly |
ACCESS_LIST_UNREADABLE | 503 | Whether a named address is a whitelist, or whether your wallets own or manage it, could not be read. Retry shortly |
ACCESS_LISTS_NOT_CONFIGURED | 503 | A whitelist ID was sent on a network where the whitelist factory is not deployed |
IDENTITY_REGISTRY_UNREADABLE | 503 | The market’s borrower register, or a register named in the terms, could not be reached. Retry shortly |
MARKET_IMPLEMENTATION_UNREADABLE | 503 | The market implementation could not be read. Retry shortly |
MARKET_STATE_UNAVAILABLE | 503 | The register of vault, the register it adopted, its share supply, or the markets it funds and their provider registers could not be read. Retry shortly |
STATE_UNAVAILABLE | 503 | On a MARKET market, the verification profiles behind the borrower register could not be read. Retry shortly |
FACTORY_READ_FAILED | 503 | The factory could not be read for the market, its asset data record or the claim record. Retry shortly |
⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/queued/0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b/accept" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"admin": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"issuer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"collateralAgent": "0x8b17e4d90c3a25f6e1d09b7c4a3f52e86d1c0b94",
"saleRecipient": "0x2f6a0d83c5e19b47d2a8c6f1e03b95d74a2c8e16",
"liquidationOperator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"oracleOwner": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"priceSigner": "0x9c4d27e1a5b8f03d6e2c71a49b0f58d3e6a1c2b7",
"realizationMode": "ISSUER_REDEMPTION",
"liquidityCommitment": "250000",
"maxFixedRateBps": 1500,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"assetDataHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90"
}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/queued/${marketAddress}/accept`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const terms = {
admin, issuer, collateralAgent, saleRecipient,
liquidationOperator, oracleOwner, priceSigner,
realizationMode: 'ISSUER_REDEMPTION',
liquidityCommitment: '250000',
assetDataHash: reviewedHash
};
let res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(terms) });
let { data } = await res.json();
if (data.claimFlow) {
const announce = await wallet.sendTransaction(data.transaction);
await announce.wait();
await new Promise((resolve) => setTimeout(resolve, data.claimDelaySeconds * 1000));
res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...terms, claimSalt: data.claimSalt })
});
({ data } = await res.json());
}
const tx = await wallet.sendTransaction(data.transaction);
await tx.wait();
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xf1ad12f5698f58badd8a662acffccb067a2ddb8a",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "acceptCuratorRole",
"marketAddress": "0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b",
"signer": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"identityRegistry": null,
"borrowerRegistry": null,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"borrowAsset": {
"address": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"symbol": "USDC",
"decimals": 6
},
"generation": "TWO_REGISTERS",
"installedRegister": null,
"borrowerProfile": null,
"providerProfile": null,
"requiredFollowUp": null,
"terms": {
"admin": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"issuer": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"collateralAgent": "0x8b17e4d90c3a25f6e1d09b7c4a3f52e86d1c0b94",
"saleRecipient": "0x2f6a0d83c5e19b47d2a8c6f1e03b95d74a2c8e16",
"liquidationOperator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"oracleOwner": "0x5a3c9e71b0d24f86a1c7e5039b2d84f6c1a0e7d3",
"priceSigner": "0x9c4d27e1a5b8f03d6e2c71a49b0f58d3e6a1c2b7",
"identityRegistry": null,
"providerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"liquidator": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"vault": null,
"liquidityCommitment": "250000000000",
"realizationMode": "ISSUER_REDEMPTION",
"claimSalt": "0x0000000000000000000000000000000000000000000000000000000000000000",
"maxFixedRateBps": 1500,
"assetDataHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90"
},
"assetData": {
"acknowledged": true,
"contentHash": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90",
"version": 1,
"attestor": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"factorySupport": true,
"note": "This adoption records your approval of asset data version 1 (0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90). The factory refuses the whole adoption if the issuer re-attests before it mines."
},
"handoverNote": "Adoption assigns every regulated role on the market and its router, authorizes the price signer, installs the registers you name, grants the liquidator and connects the vault, and hands the oracle, the rate model and the reserve to the owners you name, all inside this one transaction. Nothing is left for anyone to accept afterwards; the vault's own draw cap is the only step that follows, signed by the vault operator.",
"confirmWith": {
"endpoint": "confirm-accept",
"txHash": true
}
}
}
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0xf1ad12f5698f58badd8a662acffccb067a2ddb8a",
"data": "0x...",
"value": "0",
"chainId": 11155111
},
"functionName": "commitCuratorClaim",
"claimFlow": true,
"commitment": "0x3f9e1c7a5b2d8046e1f9a3c7d5b20e8f4a6c1d9b7e3f5a2c8d0b4e6f1a9c3d7e",
"claimSalt": "0x7c2e9a4f1b6d3e8c5a0f7b2d9e4c1a6f3b8d5e0c7a2f9b4d1e6c3a8f5b0d2e7c",
"claimDelaySeconds": 600,
"claimWindowSeconds": 259200,
"marketAddress": "0x1c74f9a2b0e63d581a47c02f9b8de3517a604c2b",
"signer": "0x4e91a7c05d3b62f18a0c94e7db2358f1c60a4e93",
"description": "Announce the claim on this open market. After 10 minutes, call accept again with the identical terms and this claimSalt to receive the acceptCuratorRole transaction; the announcement lapses after 72 hours.",
"confirmWith": {
"endpoint": "accept",
"retryWith": {
"claimSalt": "0x7c2e9a4f1b6d3e8c5a0f7b2d9e4c1a6f3b8d5e0c7a2f9b4d1e6c3a8f5b0d2e7c"
}
}
}
}
{
"success": false,
"error": {
"code": "ASSET_DATA_ACKNOWLEDGEMENT_REQUIRED",
"message": "The issuer attested asset data for this market (version 1, 0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90). Read the bundle, then name the hash you reviewed as assetDataHash in the adoption terms so the adoption records your approval of that version; pass acknowledgeAssetData: false to adopt without acknowledging any version.",
"details": {
"standing": "0xa93f4d51d67f4f88cb447fd06bccff45483fb5a9f04fa67dd1c8cdcd1127ae90",
"standingVersion": 1
}
}
}
{
"success": false,
"error": {
"code": "CLAIM_PENDING",
"message": "The claim was announced and becomes actionable at 2026-09-26T10:24:00.000Z. Call accept again with the identical terms and claimSalt after that moment."
}
}
