Risk and Access
Set Identity Gates
Install, replace or clear the borrower and provider registers of a market
POST
/
lending-external-securities-v2
/
api
/
markets
/
{marketId}
/
identity-gates
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/{marketId}/identity-gates" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"borrowerProfile": "PROFESSIONAL"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/${marketId}/identity-gates`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ borrowerProfile: 'PROFESSIONAL' })
});
const { data } = await res.json();
const tx = await adminWallet.sendTransaction({
to: data.transaction.to,
data: data.transaction.data,
chainId: data.chainId
});
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...data.confirmWith.body, txHash: tx.hash })
});
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x..."
},
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"functionName": "setIdentityGates",
"requiredRole": "DEFAULT_ADMIN_ROLE",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"unchanged": false,
"description": "Set borrower register 0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90 and provider register 0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37 (every registered vault examines its depositors against it) on this market; every entry is a live read against the register at call time (requires DEFAULT_ADMIN_ROLE)",
"requiredSigner": null,
"heldByThisInstance": true,
"signerAddress": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"note": null,
"confirmWith": {
"endpoint": "POST /lending-external-securities-v2/api/markets/clx4k1m7a0000m8tq2b5c9d1e/identity-gates",
"field": "txHash",
"body": {
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"txHash": null
}
},
"chainId": 11155111,
"value": "0"
}
}
{
"success": true,
"data": {
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b",
"signedBy": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"previousBorrowerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"previousProviderRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"previousReadable": true,
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"gates": {
"marketAddress": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"generation": "TWO_REGISTERS",
"adjustable": true,
"pendingCurator": false,
"priceSource": "NAV",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"operatorOnlyLiquidity": true,
"borrowerGateRequired": false,
"providerGateRequired": false,
"vaultOnlyLiquidity": true,
"providerGateReadBy": "VAULTS",
"borrower": {
"address": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"shape": "bool",
"usable": true
},
"provider": {
"address": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"shape": "tuple",
"usable": true
},
"upgradeRequired": false,
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"borrowerProfileElsewhere": null,
"providerProfileElsewhere": null,
"borrowerGateCompliant": true,
"borrowerGateProblem": null
}
}
}
{
"success": false,
"error": {
"code": "IDENTITY_REGISTRY_REQUIRED",
"message": "This market prices its collateral from a live market price, which carries the free-hand realization path under § 1259 BGB, and that path is only available against professional borrowers. A borrower register has to stay installed on it.",
"details": { "field": "borrowerRegistry" }
}
}
{
"success": false,
"error": {
"code": "PROFESSIONAL_BORROWER_GATE_REQUIRED",
"message": "This market prices its collateral from a live market price, which carries the free-hand realization path under § 1259 BGB and is only available against professional borrowers. The borrower register 0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21 admits wallets for the Retail profile, which is not limited to professional clients. Choose the register of a profile limited to professional clients as the borrower gate.",
"details": { "field": "borrowerRegistry", "priceSource": "MARKET" }
}
}
{
"success": false,
"error": {
"code": "ACCESS_LIST_ATTESTATION_REQUIRED",
"message": "A whitelist admits every wallet it lists without examining an identity, so it can gate liquidity providers or vault depositors only once you confirm that it lists identified wallets only. Send attestIdentifiedMembers: true with the request to confirm it.",
"details": { "field": "providerRegistry" }
}
}
{
"success": false,
"error": {
"code": "MARKET_UPGRADE_REQUIRED",
"message": "This market runs an earlier implementation that examines borrowers and providers against one register and offers no way to change it. Move the market onto the current implementation first (the admin signs POST /markets/:id/upgrade), then choose its registers here."
}
}
{
"success": false,
"error": {
"code": "IDENTITY_REGISTRY_RETIRED",
"message": "0xe9114c40934f6fb6bb317935156b731f7a86d006 is the previous Trusset ID Register, which takes no new identities, so a gate on it refuses every customer verified since the register moved. Name the current Trusset ID Register (0xef244c4bd4d71bd9a30edf6edef7ccc72642291a) instead, or another register.",
"details": {
"field": "providerRegistry",
"registry": "0xe9114c40934f6fb6bb317935156b731f7a86d006",
"currentRegistry": "0xef244c4bd4d71bd9a30edf6edef7ccc72642291a"
}
}
}
Builds the
Once a whitelist gates the market, its lender of record can maintain it only as a manager of the list. Get Identity Gates offers that step in
Or send only the side that reads the previous register. The other rules on this page still apply: the borrower side of a
The four signer fields are absent when the role lookup itself fails.
The confirmed response:
Confirming records an
Confirming with
setIdentityGates transaction that installs, replaces or clears the market’s borrower register and provider register in one call. The wallet holding DEFAULT_ADMIN_ROLE on the market signs it. The same POST with txHash verifies the mined transaction and records it.
The borrower register gates openLoan and borrowMore on the market. The provider register is read by every registered vault before it admits a depositor, because the market itself takes direct deposits only from the operator wallet and registered vaults. Get Identity Gates describes both doors in full.
A change applies from the next open, draw, vault deposit or share transfer. Existing loans and vault holdings are not examined again, and repaying, closing and redeeming are never gated.
Choose What Each Side Gets
Each field is read on its own:- Omitted: the market keeps the register it has now.
- An address: that register is installed.
null, an empty string or the zero address: the register is cleared, and the side is left without one.
borrowerRegistry therefore changes the borrower side and leaves the provider side as it is.
Instead of an address, a side can name one of your verification profiles in borrowerProfile or providerProfile. The profile’s eligibility register is then installed, so the side admits exactly the wallets admitted under that profile. An address sent beside a profile must name the same register, or the request is refused with GATE_PROFILE_CONFLICT. A profile without an eligibility register is refused with ELIGIBILITY_REGISTER_NOT_SET.
A side can also name one of your whitelists by its ID in borrowerAccessList or providerAccessList. See Whitelists as Gates. A side takes a profile or a whitelist, not both: sending both is refused with GATE_SOURCE_CONFLICT, and so is an address beside a whitelist that names a different contract.
Whitelists as Gates
A whitelist admits exactly the wallets its owner and managers listed, and examines no identity. Create and maintain one with the whitelist routes. Only a whitelist your instance keeps and has not archived can be named by its ID. Any other is refused with404 ACCESS_LIST_NOT_FOUND, details.field naming the field you sent. A whitelist of another instance can still be installed by its address.
- Borrower side. A whitelist cannot be the borrower gate of a
MARKETmarket, which lends to professional borrowers only and needs a professional gate. That is refused with409 ACCESS_LIST_NOT_ALLOWED,details.reason: MARKET_PRICE_BORROWER_GATE. - Purpose. A whitelist kept for depositors (
purpose: DEPOSITOR) cannot become the borrower register, and one kept for borrowers (BORROWER) cannot become the provider register. That is refused with409 ACCESS_LIST_PURPOSE_MISMATCH. A list kept forANYfits both. The owner changes the purpose with Update Whitelist. - Provider side. A whitelist gates the market’s liquidity providers only on the attestation of whoever curates its members. A list your instance neither keeps nor controls through a verified wallet that owns or manages it is refused with
403 ACCESS_LIST_NOT_CONTROLLED. Every request that installs a whitelist as the provider register must sendattestIdentifiedMembers: true, which confirms that the list holds identified wallets only, or it is refused with400 ACCESS_LIST_ATTESTATION_REQUIRED. The first attestation of a list by your instance is written to the audit log asLENDING_ACCESS_LIST_ATTESTED.
503 ACCESS_LIST_UNREADABLE and decides nothing.
The confirm call runs the provider-side checks again on a whitelist the transaction installed, and records nothing when one fails. The transaction has already changed the market on chain by then. Send
attestIdentifiedMembers: true on the confirm call as well: confirmWith.body carries it when the build was attested.accessListSteps.
Professional Borrowers
AMARKET-priced market carries the free-hand realization path under § 1259 BGB, which is open against professional borrowers only. Its borrower register must therefore admit professional clients and nobody else. The API judges that from the verification profiles bound to the register as their eligibility register, read across every instance on the market’s network and environment, not only yours. The register qualifies when:
- At least one such profile admits wallets to it. A profile bound in the
EXTERNALmode admits nobody through Trusset, so it is not counted. - Every profile that admits wallets to it is limited to professional clients (
professionalOnly: true): thePROFESSIONALorELIGIBLE_COUNTERPARTYpreset, or a custom profile limited to professional clients. - Every one of those profiles is in the
REGISTERmode, so its own instance signs each admission. A register bound as an instance register does not qualify.
PROFESSIONAL profile, named with borrowerProfile: "PROFESSIONAL", is the direct way to a qualifying gate.
Any change that would leave a MARKET market with a borrower register that does not qualify is refused with PROFESSIONAL_BORROWER_GATE_REQUIRED, details.field: "borrowerRegistry". That includes a change to the provider side alone while the borrower register does not qualify, so fix the borrower side first, or in the same call.
Until the borrower register qualifies, the API prepares nothing that lends on the market or moves liquidity into it. Open Loan, Borrow More, Add Liquidity and the register action of Register Vault refuse with the same code, and so do vault allocations, draw caps and rebalances for the market in the Issuer Portal. Get Identity Gates reports the state as borrowerGateCompliant. When the profiles behind the register cannot be read, those calls answer 503 STATE_UNAVAILABLE and decide nothing.
This rule is enforced by the API, not by the market contract. The contract only asks the borrower register whether a wallet is verified, so a transaction built and signed outside this API is not refused on this ground.
Vaults Registered on the Market
On a current market every registered vault examines its depositors against the provider register, so a new provider register must fit the vaults already registered:- A vault with its own register needs the provider register to be that same register, or none.
- A vault without a register of its own takes its depositor gate from the provider registers of the markets it funds, and keeps the first one for good. Once a provider register is installed, it can be neither replaced nor cleared while such a vault is registered.
PROVIDER_GATE_MISMATCH, and details.conflicts lists each vault as { vault, register }, with register null for a vault without one. Set the provider register to the vaults’ register, or deregister those vaults first with Register Vault.
Registers That Must Stay
AMARKET-priced market must keep a borrower register. The API refuses to clear it with IDENTITY_REGISTRY_REQUIRED, and the contract would revert the same change.
On a current market the provider register can be cleared, since the market takes no third-party deposit that it would guard. A vault without a register of its own registered on the market still blocks the change, see Vaults Registered on the Market. On an older market whose pool is open to third-party providers, the API refuses to clear the provider register with IDENTITY_REGISTRY_REQUIRED. details.field names the side in both cases.
A market on the earlier single-register implementation examines both sides through one register and cannot change it. It is refused with MARKET_UPGRADE_REQUIRED until the admin moves it onto the current implementation with Upgrade Market.
The Previous Trusset ID Register
The Trusset ID Register on Sepolia moved to0xEf244c4Bd4d71Bd9A30EDF6Edef7CCC72642291a on 10 October 2026. The previous register, 0xE9114c40934f6fB6BB317935156b731f7A86D006, takes no new identities. A gate that still reads it admits the wallets verified on it before the move and refuses every customer verified since 10 October 2026. Get Identity Gates marks such a side with retired: true.
Until the side moves, a wallet that register does not admit is refused with 409 IDENTITY_GATE_RETIRED, and the refusal names the move to the current register. Open Loan, Borrow More, Add Liquidity and Deposit to Vault return it.
Install the current register on both sides:
{
"borrowerRegistry": "0xEf244c4Bd4d71Bd9A30EDF6Edef7CCC72642291a",
"providerRegistry": "0xEf244c4Bd4d71Bd9A30EDF6Edef7CCC72642291a"
}
MARKET market must qualify as a professional gate, and a new provider register must fit the vaults registered on the market.
Naming the previous register as a new gate, on a side the request changes, is refused with 422 IDENTITY_REGISTRY_RETIRED. details carries field, registry and currentRegistry. A side the transaction leaves on the previous register is not refused, for example when only the other side changes. The calldata response then carries one warnings entry per such side, { code: "RETIRED_REGISTRY_KEPT", field, registry, message }.
A vault keeps its register for life. A vault registered on the market whose own register is the previous Trusset ID Register needs the provider register to be that register or none, so moving the provider side to the current register is refused with
PROVIDER_GATE_MISMATCH while that vault is registered.Checks Before the Calldata
Every register named is probed first. One that cannot be reached is refused withIDENTITY_REGISTRY_UNREADABLE, and one that does not answer isVerified(address) with IDENTITY_REGISTRY_INCOMPATIBLE, because as a gate it would refuse every party. ERC-3643 identity registries, ONCHAINID-based registers and the Trusset register all answer.
A request that would leave both registers as they are is refused with IDENTITY_GATES_UNCHANGED rather than answered with a transaction that only costs gas. There is no unchanged: true response on this endpoint.
Path Parameters
string
required
Body Parameters
string
The borrower register to install, or
null, "" or the zero address to clear it. Omit it to keep the current one. An address must be 0x followed by 40 hex characters, all-lowercase or with a valid EIP-55 checksum.string
The provider register to install, or
null, "" or the zero address to clear it. Omit it to keep the current one. Same address rules as borrowerRegistry.string
A verification profile key of your instance, 1 to 60 letters, digits,
- or _. Installs that profile’s eligibility register as the borrower register.string
A verification profile key whose eligibility register is installed as the provider register.
string
The ID of a whitelist of your instance, 1 to 64 letters, digits,
- or _, installed as the borrower register. Not accepted beside borrowerProfile.string
The ID of a whitelist of your instance, installed as the provider register. Not accepted beside
providerProfile.boolean
true confirms that the whitelist installed as the provider register lists identified wallets only. Required whenever the provider register changes to a whitelist, whether named by ID or by address. Send it on the confirm call too.string
Hash of the mined transaction, as a 0x-prefixed 64-character hex string. Send it to confirm; the registers are then read from the transaction’s
IdentityGatesUpdated event, so the other fields are not needed, apart from attestIdentifiedMembers for a whitelist provider gate. Omit it to receive the calldata.Response Fields
The calldata response:object
Show child attributes
Show child attributes
string
SIGN_TRANSACTION.object
{ to, data }, the setIdentityGates call on the market. The chainId and value to sign with sit on data itself, not inside this object.string
The market address, repeated from
transaction.string
The calldata, repeated from
transaction.integer
The chain to sign on.
string
Always
0.string
setIdentityGates.string
The borrower register the transaction installs, lowercased, or
null for none.string
The provider register the transaction installs, lowercased, or
null for none.object
{ key, name, entityType, professionalOnly, requirementsHash } of the profile whose eligibility register becomes the borrower register, or null when it belongs to no profile of your instance.object
The same for the provider register, or
null.object
The whitelist that becomes the borrower register, as on Get Identity Gates, or
null.object
The whitelist that becomes the provider register, or
null.boolean
true when the request carried attestIdentifiedMembers: true. Absent otherwise.boolean
Always
false, since a request that changes nothing is refused.string
What the transaction sets, in words.
string
DEFAULT_ADMIN_ROLE.string
Always
null on this endpoint.boolean
Whether a wallet registered on this instance holds
DEFAULT_ADMIN_ROLE on the market. null when the check could not be read.string
The instance wallet that holds the role, or
null.string
Why no instance wallet can sign, or why that is unknown.
null when an instance wallet holds the role.object
{ endpoint, field, body }: the POST to send back with the transaction hash in txHash. body carries the two registers, and attestIdentifiedMembers: true when the build was attested.array
Present only when the transaction leaves a side on the previous Trusset ID Register. One entry per side:
code (RETIRED_REGISTRY_KEPT), field (borrowerRegistry or providerRegistry), registry, lowercased, and message. See The Previous Trusset ID Register.object
Show child attributes
Show child attributes
string
The verified transaction hash.
string
The wallet that sent it.
string
The borrower register the transaction set, lowercased, or
null for none. Read from its IdentityGatesUpdated event, or from the call when the receipt carries none.string
The provider register the transaction set, or
null.string
The borrower register at the block before the transaction, or
null for none. Also null when that block could not be read, see previousReadable.string
The provider register at the block before the transaction, or
null.boolean
Whether the registers before the transaction could be read.
object
The profile behind the new borrower register, or
null.object
The profile behind the new provider register, or
null.object
The whitelist the new borrower register is, or
null.object
The whitelist the new provider register is, or
null.boolean
Present when the transaction installed a whitelist as the provider register:
true once your instance has attested it.object
The full Get Identity Gates answer after the change,
borrowerProfileElsewhere and providerProfileElsewhere included, or null when it could not be read. It carries no accessListSteps.IDENTITY_GATES_SET transaction on the market, visible through List Transactions, once per transaction hash, with the registers before and after the change.
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/{marketId}/identity-gates" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"borrowerProfile": "PROFESSIONAL"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/${marketId}/identity-gates`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ borrowerProfile: 'PROFESSIONAL' })
});
const { data } = await res.json();
const tx = await adminWallet.sendTransaction({
to: data.transaction.to,
data: data.transaction.data,
chainId: data.chainId
});
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...data.confirmWith.body, txHash: tx.hash })
});
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x..."
},
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"functionName": "setIdentityGates",
"requiredRole": "DEFAULT_ADMIN_ROLE",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"unchanged": false,
"description": "Set borrower register 0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90 and provider register 0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37 (every registered vault examines its depositors against it) on this market; every entry is a live read against the register at call time (requires DEFAULT_ADMIN_ROLE)",
"requiredSigner": null,
"heldByThisInstance": true,
"signerAddress": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"note": null,
"confirmWith": {
"endpoint": "POST /lending-external-securities-v2/api/markets/clx4k1m7a0000m8tq2b5c9d1e/identity-gates",
"field": "txHash",
"body": {
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"txHash": null
}
},
"chainId": 11155111,
"value": "0"
}
}
{
"success": true,
"data": {
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b",
"signedBy": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"previousBorrowerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"previousProviderRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"previousReadable": true,
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"gates": {
"marketAddress": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"generation": "TWO_REGISTERS",
"adjustable": true,
"pendingCurator": false,
"priceSource": "NAV",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"operatorOnlyLiquidity": true,
"borrowerGateRequired": false,
"providerGateRequired": false,
"vaultOnlyLiquidity": true,
"providerGateReadBy": "VAULTS",
"borrower": {
"address": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"shape": "bool",
"usable": true
},
"provider": {
"address": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"shape": "tuple",
"usable": true
},
"upgradeRequired": false,
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"borrowerProfileElsewhere": null,
"providerProfileElsewhere": null,
"borrowerGateCompliant": true,
"borrowerGateProblem": null
}
}
}
{
"success": false,
"error": {
"code": "IDENTITY_REGISTRY_REQUIRED",
"message": "This market prices its collateral from a live market price, which carries the free-hand realization path under § 1259 BGB, and that path is only available against professional borrowers. A borrower register has to stay installed on it.",
"details": { "field": "borrowerRegistry" }
}
}
{
"success": false,
"error": {
"code": "PROFESSIONAL_BORROWER_GATE_REQUIRED",
"message": "This market prices its collateral from a live market price, which carries the free-hand realization path under § 1259 BGB and is only available against professional borrowers. The borrower register 0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21 admits wallets for the Retail profile, which is not limited to professional clients. Choose the register of a profile limited to professional clients as the borrower gate.",
"details": { "field": "borrowerRegistry", "priceSource": "MARKET" }
}
}
{
"success": false,
"error": {
"code": "ACCESS_LIST_ATTESTATION_REQUIRED",
"message": "A whitelist admits every wallet it lists without examining an identity, so it can gate liquidity providers or vault depositors only once you confirm that it lists identified wallets only. Send attestIdentifiedMembers: true with the request to confirm it.",
"details": { "field": "providerRegistry" }
}
}
{
"success": false,
"error": {
"code": "MARKET_UPGRADE_REQUIRED",
"message": "This market runs an earlier implementation that examines borrowers and providers against one register and offers no way to change it. Move the market onto the current implementation first (the admin signs POST /markets/:id/upgrade), then choose its registers here."
}
}
{
"success": false,
"error": {
"code": "IDENTITY_REGISTRY_RETIRED",
"message": "0xe9114c40934f6fb6bb317935156b731f7a86d006 is the previous Trusset ID Register, which takes no new identities, so a gate on it refuses every customer verified since the register moved. Name the current Trusset ID Register (0xef244c4bd4d71bd9a30edf6edef7ccc72642291a) instead, or another register.",
"details": {
"field": "providerRegistry",
"registry": "0xe9114c40934f6fb6bb317935156b731f7a86d006",
"currentRegistry": "0xef244c4bd4d71bd9a30edf6edef7ccc72642291a"
}
}
}
Error Codes
Refusals from the checks above carrydetails as an object: field for the side concerned, registry on IDENTITY_REGISTRY_INCOMPATIBLE, priceSource on PROFESSIONAL_BORROWER_GATE_REQUIRED, and conflicts on PROVIDER_GATE_MISMATCH. IDENTITY_GATES_UNCHANGED carries the two registers the market already has. The whitelist codes are explained in Whitelists as Gates.
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | A register is not 0x followed by 40 hex characters, fails its EIP-55 checksum, a profile key is not 1 to 60 letters, digits, - or _, a whitelist ID is not 1 to 64 of them, or txHash is malformed |
NO_MARKET_ADDRESS | 400 | The market has no on-chain address recorded |
GATE_PROFILE_CONFLICT | 400 | A register address names a different register than the profile sent for the same side |
GATE_PROFILE_UNRESOLVED | 400 | A profile key could not be resolved for a reason that carries no code of its own |
IDENTITY_GATES_FAILED | 400 | The change could not be prepared or confirmed and no more specific code applied |
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 | The provider register would become a whitelist and attestIdentifiedMembers is not true. On the confirm call, also when your instance never attested the list. Send it and retry |
ACCESS_LIST_NOT_CONTROLLED | 403 | The provider register would become a whitelist that another instance curates: neither its owner nor any of its managers is a verified wallet of your instance. Install a whitelist you own or manage, or a register |
MISSING_MARKET_ID | 400 | marketId is longer than 100 characters |
MARKET_NOT_FOUND | 404 | No market with this ID on your instance |
PROFILE_NOT_FOUND | 404 | borrowerProfile or providerProfile names no verification profile of your instance |
ACCESS_LIST_NOT_FOUND | 404 | borrowerAccessList or providerAccessList names no whitelist of your instance on this network that is not archived. details carries field and accessListId |
MARKET_PENDING_CURATOR | 409 | The market has no lender of record yet, so nobody holds the admin role that sets its registers. Skipped when confirming with txHash |
MARKET_UPGRADE_REQUIRED | 409 | The market runs the earlier single-register implementation |
ELIGIBILITY_REGISTER_NOT_SET | 409 | The named profile has no eligibility register |
IDENTITY_REGISTRY_REQUIRED | 409 | The request would clear a register the market must keep |
PROFESSIONAL_BORROWER_GATE_REQUIRED | 409 | A MARKET market would be left with a borrower register that does not qualify as a professional gate. See Professional borrowers |
PROVIDER_GATE_MISMATCH | 409 | The new provider register does not fit a vault registered on the market. details.conflicts lists them |
ACCESS_LIST_NOT_ALLOWED | 409 | The borrower register of a MARKET market would be a whitelist. details carries field, reason (MARKET_PRICE_BORROWER_GATE) and address. Choose the register of a profile limited to professional clients |
ACCESS_LIST_PURPOSE_MISMATCH | 409 | The whitelist is kept for the other side: DEPOSITOR on the borrower side or BORROWER on the provider side. details carries field, purpose, gate and address. Change the list’s purpose or choose another list |
IDENTITY_GATES_UNCHANGED | 409 | The request would leave both registers as they are |
IDENTITY_REGISTRY_INCOMPATIBLE | 422 | A named register does not answer isVerified(address) |
IDENTITY_REGISTRY_RETIRED | 422 | A side the request changes would be gated on the previous Trusset ID Register, which takes no new identities. details carries field, registry and currentRegistry. Name the current register. See The Previous Trusset ID Register |
IDENTITY_GATES_UNREADABLE | 503 | The market’s current registers could not be read. Retry |
IDENTITY_REGISTRY_UNREADABLE | 503 | A named register could not be reached to be checked. Retry |
MARKET_STATE_UNAVAILABLE | 503 | The vaults registered on the market, or one of their registers, could not be read. Retry |
ACCESS_LIST_UNREADABLE | 503 | Whether a named address is a whitelist, or whether a wallet of your instance owns or manages it, could not be read. Nothing was decided. Retry |
ACCESS_LISTS_NOT_CONFIGURED | 503 | A whitelist ID was sent on a network where the whitelist factory is not deployed |
STATE_UNAVAILABLE | 503 | The verification profiles behind the borrower register could not be read. Retry |
txHash can also return any transaction verification error, with the status listed there.⌘I
curl -X POST "https://api.trusset.org/lending-external-securities-v2/api/markets/{marketId}/identity-gates" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{"borrowerProfile": "PROFESSIONAL"}'
const url = `https://api.trusset.org/lending-external-securities-v2/api/markets/${marketId}/identity-gates`;
const headers = {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
};
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ borrowerProfile: 'PROFESSIONAL' })
});
const { data } = await res.json();
const tx = await adminWallet.sendTransaction({
to: data.transaction.to,
data: data.transaction.data,
chainId: data.chainId
});
await tx.wait();
await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...data.confirmWith.body, txHash: tx.hash })
});
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": {
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x..."
},
"to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"data": "0x...",
"functionName": "setIdentityGates",
"requiredRole": "DEFAULT_ADMIN_ROLE",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"unchanged": false,
"description": "Set borrower register 0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90 and provider register 0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37 (every registered vault examines its depositors against it) on this market; every entry is a live read against the register at call time (requires DEFAULT_ADMIN_ROLE)",
"requiredSigner": null,
"heldByThisInstance": true,
"signerAddress": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"note": null,
"confirmWith": {
"endpoint": "POST /lending-external-securities-v2/api/markets/clx4k1m7a0000m8tq2b5c9d1e/identity-gates",
"field": "txHash",
"body": {
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"txHash": null
}
},
"chainId": 11155111,
"value": "0"
}
}
{
"success": true,
"data": {
"txHash": "0x9f2c41d8b7e05a3164c2870fbd935e1a4c7802db6135ea9048f7c21b5d3ea41b",
"signedBy": "0x1234f9a07c6b53d81e2a4f70c9b385d6014a7e52",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"previousBorrowerRegistry": "0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21",
"previousProviderRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"previousReadable": true,
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"gates": {
"marketAddress": "0x70a0e25c7b768b87e658348b3b577678a173e038",
"generation": "TWO_REGISTERS",
"adjustable": true,
"pendingCurator": false,
"priceSource": "NAV",
"borrowerRegistry": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"providerRegistry": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"operatorOnlyLiquidity": true,
"borrowerGateRequired": false,
"providerGateRequired": false,
"vaultOnlyLiquidity": true,
"providerGateReadBy": "VAULTS",
"borrower": {
"address": "0x4f2a9c81d06e3b75a1c8e24d9b07f56e3a1d8c90",
"shape": "bool",
"usable": true
},
"provider": {
"address": "0x7d31e6b09a4c25f8e1b73d0a6c94e2f58b1a0c37",
"shape": "tuple",
"usable": true
},
"upgradeRequired": false,
"borrowerProfile": {
"key": "PROFESSIONAL",
"name": "Professional",
"entityType": "INDIVIDUAL",
"professionalOnly": true,
"requirementsHash": "0x8919ea37bac1f44ea0e8a37529be970cb49e9779ebd4c4e98490cfd754e9d390"
},
"providerProfile": null,
"borrowerAccessList": null,
"providerAccessList": null,
"borrowerProfileElsewhere": null,
"providerProfileElsewhere": null,
"borrowerGateCompliant": true,
"borrowerGateProblem": null
}
}
}
{
"success": false,
"error": {
"code": "IDENTITY_REGISTRY_REQUIRED",
"message": "This market prices its collateral from a live market price, which carries the free-hand realization path under § 1259 BGB, and that path is only available against professional borrowers. A borrower register has to stay installed on it.",
"details": { "field": "borrowerRegistry" }
}
}
{
"success": false,
"error": {
"code": "PROFESSIONAL_BORROWER_GATE_REQUIRED",
"message": "This market prices its collateral from a live market price, which carries the free-hand realization path under § 1259 BGB and is only available against professional borrowers. The borrower register 0x9e3c8a15f4d70b2681c5a3f9027d4be8115c7d21 admits wallets for the Retail profile, which is not limited to professional clients. Choose the register of a profile limited to professional clients as the borrower gate.",
"details": { "field": "borrowerRegistry", "priceSource": "MARKET" }
}
}
{
"success": false,
"error": {
"code": "ACCESS_LIST_ATTESTATION_REQUIRED",
"message": "A whitelist admits every wallet it lists without examining an identity, so it can gate liquidity providers or vault depositors only once you confirm that it lists identified wallets only. Send attestIdentifiedMembers: true with the request to confirm it.",
"details": { "field": "providerRegistry" }
}
}
{
"success": false,
"error": {
"code": "MARKET_UPGRADE_REQUIRED",
"message": "This market runs an earlier implementation that examines borrowers and providers against one register and offers no way to change it. Move the market onto the current implementation first (the admin signs POST /markets/:id/upgrade), then choose its registers here."
}
}
{
"success": false,
"error": {
"code": "IDENTITY_REGISTRY_RETIRED",
"message": "0xe9114c40934f6fb6bb317935156b731f7a86d006 is the previous Trusset ID Register, which takes no new identities, so a gate on it refuses every customer verified since the register moved. Name the current Trusset ID Register (0xef244c4bd4d71bd9a30edf6edef7ccc72642291a) instead, or another register.",
"details": {
"field": "providerRegistry",
"registry": "0xe9114c40934f6fb6bb317935156b731f7a86d006",
"currentRegistry": "0xef244c4bd4d71bd9a30edf6edef7ccc72642291a"
}
}
}
