Lifecycle
Every read names a listing’s state instatus.
Collateral modes
Each market runs in one mode, fixed at deployment.FREEZE is the default.
Every lock names the market’s collateral agent as pledgee. In custody mode, when the token refuses to return the asset to the seller on cancellation or liquidation, the adapter keeps it in escrow for the seller. Cancel Listing and Liquidate say so in
assetReturn before you sign. Once the token admits the seller again, the seller takes it back with Claim Escrowed Collateral.
Asset leg
Retention of title holds only while the asset can still reach the buyer. In freeze mode the asset stays in the seller’s wallet, and an agent of the token can release the freeze and move it. In custody mode an agent can move it out of the adapter. Get Listing and Get Loan Status check the asset leg of everyACTIVE and REPAID listing in assetLeg. In freeze mode the check is pooled over all of the seller’s ACTIVE and REPAID listings on the market, because one wallet backs them all.
While the asset cannot be delivered, a repayment that would complete the loan and the asset claim are refused with 409 ASSET_NOT_DELIVERABLE: a payoff would credit the seller the full price while the delivery to the buyer reverts. A partial repayment still builds, with the same warning. A leg that could not be read (checked: false) never refuses anything.
Token-side setup
Each market has its own adapter, deployed with it. Until the asset token accepts that adapter, a freeze market refuses every listing, and a custody listing on a token that gates its holders reverts at the transfer into the adapter. The party that signs this setup is on the token issuer’s side, not necessarily the deployer.- Freeze mode. The token’s owner grants the freeze adapter the agent role with
addAgent(adapter). Only the owner can grant it. The adapter then freezes, unfreezes and force-transfers exactly the listed amount. - Custody mode. The token must admit the custody adapter as a holder. On a token with an ERC-3643 identity register, the token issuer’s KYC operator issues an ONCHAINID for the adapter carrying the claims the register requires, and an agent of the register registers the adapter under it. On a Trusset ID Register, a KYC provider of the register verifies the adapter. On a token with its own contract allow-list, the token’s compliance admin allow-lists the adapter. A token with neither an identity register nor an allow-list, and no transfer rule that refuses the adapter, needs no step.
Roles
The deployment names the admin, the operator and the collateral agent. Without an operator, the admin holds the operator role as well. Trusset holds no role, key or asset on a market, and neither does the factory. No role can move escrowed payment tokens or the asset to anyone other than the recorded seller, the recorded buyer (or the recipient the buyer names on claim) and the fixed Trusset wallet. There is no emergency withdrawal.
A market can name an identity register. When it does, the seller must be verified on it to list and the buyer to purchase. The operator changes or removes it with Set Identity Register. A register that is retired or does not answer
isVerified(address) refuses every seller and buyer, so List Markets and Get Market report it in identityGate with usable: false. Separately, a buyer must be verified on the asset token’s own identity register when the token has one, because the token would otherwise refuse the delivery. A seller holding the agent role on the asset token is refused at listing and at purchase, because an agent can unfreeze and move the tokens it sells.
Interest
A listing takes one of the strategies its market enables. The rate, the premium coefficients and every term are stamped on the listing when it is created. A later configuration change reaches new listings only.FIXEDcharges one annual rate on the outstanding principal. On a market where sellers set the rate (sellerSetsFixedRate: true), the seller names it infixedRateBps, up to the market’smaxFixedRateBps. Otherwise the operator’sfixedRateBpsapplies.DERIVEDcharges the operator’s base rate (baseRateBps) on the outstanding principal, plus a walk-away premium. The premium pays the seller for the buyer’s right to walk away from the sale. It is priced from the listing’s price and downpayment and from the operator’s volatility input (volatilityBps), and stamped on the listing aspremiumAandpremiumB. It accrues with the time since purchase, fastest at the start, and does not fall as principal is repaid.
aprEquivalent. That figure is a simple annualized rate for comparison, not a regulatory effective annual rate.
Due dates, grace and default
The runtime is cut into interest periods counted from the purchase. The interest charged up to the end of each period is due at that end. The last period is shorter when the runtime is not a multiple of the period. The principal is due at maturity. With an interest period equal to the runtime, interest and principal are both due at maturity. Each due date is followed by the listing’s grace period. A payment made by the end of the grace period is on time. One second later, the loan becomes liquidatable if interest charged up to that due date is still unpaid. It also becomes liquidatable one second after maturity plus the grace period while principal is outstanding. Get Loan Status answersisLiquidatable, liquidatableAt and the next amount due.
The interest of a period can be paid in full only once its due date has passed, because a payment before it settles only the interest accrued so far. The window to pay a period on time is therefore its grace period, from the due date to liquidatableAt. With a grace period of 0 that window is one second, and a payment mined one block early leaves a remainder that puts the loan in default. A listing whose interest period is shorter than its runtime therefore needs a grace period of at least one day: Create Listing and Get Quote refuse a shorter one with 400 GRACE_PERIOD_REQUIRED. A single-period listing, whose interest period equals its runtime, may keep a grace period of 0. The same floor applies to the market configuration: maxGracePeriodDays must be at least 1 unless every listing on the market has a single period.
Interest keeps accruing after a missed due date until the seller liquidates. A liquidation takes it out of the escrow, capped at what the escrow holds after the compensation, so the buyer never owes the market more than the escrow.
Coverage rule
A listing is refused unless its downpayment, after the 1.5 percent compensation, covers the interest of one interest period plus the grace period plus one day. A liquidation within a day of the first missed grace period can then pay the compensation and every unit of interest owed out of the escrow. A short interest period and a short grace period keep the required downpayment low. Get Quote returns the check ascoverageWindowInterest, coverageLimit and coverageOk.
Fees
- Trusset interest share. 20 percent, rounded down, of every interest amount the seller receives, and of what the seller takes at liquidation. The rest is credited to the seller. The share is fixed in the market contract.
- Repay fee. Every repayment carries a fee, borne by the payer. It is carved out of the payment: the market keeps the smaller of the market’s repay fee and 0.5 percent of the amount applied, and only the rest goes to interest and principal. The factory stamps the repay fee on the market at deployment, in the payment token’s smallest unit: its default of 1.5 whole units of the payment token, for example 1.5 USDC, or a figure set for that payment token, at most 10 whole units. The market has no setter, so the fee never changes. Get Market returns it as
repayFeeandrepayFeeFormatted, and Build Deployment indeployment.repayFeebefore you sign.
trussetFeesPayable. Anyone can pay it out to the fixed Trusset wallet 0x65FF3a731366472d40CF458332457403168c2BEA with sweepInfrastructureFees() on the market. This API does not build that call.
What each party receives
On completion. The repayment that brings the principal to zero credits the seller the full price: the downpayment plus every principal payment held in escrow. The loan is thenREPAID. The buyer takes delivery with Claim Asset, to its own wallet or to any recipient the token admits. The seller withdraws with Withdraw. In the Sepolia smoke test (a price of 10,000 USDC, 20 percent down, 30 days), the seller withdrew 10,000.8633 USDC: the price plus its share of the 1.079124 USDC interest the buyer paid.
On liquidation. The escrow holds the downpayment plus the principal paid so far. The seller takes the compensation (1.5 percent of the downpayment, rounded up) plus the interest still owed, capped at the escrow. Trusset takes 20 percent of that. The buyer is refunded the rest. The asset is released to the seller: unfrozen in its wallet in freeze mode, returned from the adapter in custody mode. Interest the buyer paid before the default stays with the seller.
For example, take a listing at 10,000 USDC with 20 percent down, 30 days, 7-day interest periods, a 2-day grace period and DERIVED interest at a 4 percent base rate and 12 percent volatility. The buyer pays nothing after the downpayment, and the seller liquidates 10 days after the purchase. The escrow holds 2,000 USDC and 140.139154 USDC of interest is owed. The seller takes the 30 USDC compensation plus that interest, 170.139154 USDC, of which Trusset takes 34.02783 USDC. The seller is credited 136.111324 USDC and the buyer 1,829.860846 USDC. Each withdraws with Withdraw.
Base Path
X-API-Key header. See Authentication. The API takes the instance from the key only. The instance needs the lending service: without it every request answers 403 SERVICE_NOT_ENABLED. Requests draw on the instance’s monthly API credits, booked to the lending service.
Which markets your instance reaches
A market is reached on two kinds of instance on its network:- The deploying instance, which recorded the market with Record Deployment. Its rows carry
access: { "kind": "DEPLOYER" }. - A role holder. Any instance one of whose verified wallets holds
OPERATOR_ROLEorDEFAULT_ADMIN_ROLEon the market. The role is read on chain withhasRoleon every request that names the market, so a role the admin revokes closes the access at once. Its answers carryaccess: { "kind": "ROLE_HOLDER", "wallets": [...] }, naming the wallets and the roles they hold. List Markets lists such a market only when the wallet is the admin or operator named at deployment. A wallet granted a role later reaches the market by its ID on every route.
404 MARKET_NOT_FOUND. When the role check cannot be read, the answer is 503 CHAIN_UNAVAILABLE, never a 404. A role holder does not record the market again: Record Deployment answers it 409 MARKET_RECORDED_ELSEWHERE.
The market ID is the record ID the deploying instance created, the same on every instance that reaches the market, as id on List Markets. It is not the contract address. Sellers and buyers hold no role on a market, so their transactions are built through an instance that reaches it, normally the one that runs the market for the seller.
Response envelope
success is false, data is null, and error carries code, message and, where the page says so, details. Always branch on success rather than on the HTTP status alone. metadata.requestId equals the X-Request-Id response header. Quote it when reporting a problem.
A request refused before it reaches a route answers without data and without metadata.instanceId. That covers an invalid key, a service not enabled on the instance, an exhausted credit allowance, a rate limit and key material in the body. A malformed txHash on Record Deployment reaches the route and answers the standard 400 VALIDATION_ERROR.
Writes
Every write returns unsigned transactions for the wallet holder to sign and broadcast. Nothing is signed or submitted on your behalf, and Trusset holds no key.to, data, value (always "0"), chainId, the functionName it calls, and a label, repeated as description. Broadcast the steps in order, each once the previous one is mined.
fromnames the signer. It is required on every write except Build Token Setup. Without it the answer is400 FROM_REQUIRED, whose message names who signs that transaction, for example “Pass from, the wallet that signs this transaction: the buyer wallet that pays the downpayment. It is needed to check balances and roles and to simulate the transaction before you sign.”, withdetails: [{ field: "from", message }]. Build Deployment answers the same code with its own message and nodetails, after theMARKET_EXISTScheck. The API reads that wallet’s balance and allowance and simulates the main transaction from it. When the contract would revert, the answer is409 TX_WOULD_REVERTand nothing is built. Sign with the wallet you named, because no other wallet was checked.- A wrong signer is named. On the operator builds (Update Configuration, Set Identity Register, Pause Market, Unpause Market) the answer carries
signer: { role: "OPERATOR_ROLE", holders, holdersComplete }: the wallets that hold the role now, and whether the market’s role history was read in full. Cancel Listing and Liquidate carrysigner: { role: "SELLER_OR_OPERATOR_ROLE", seller }. Whenfromis not one of them, theTX_WOULD_REVERTrefusal (AccessControlUnauthorizedAccount,NotSeller, orNotBuyeron Claim Asset) names the role indetails.requiredRoleand its current holders indetails.roleHolders, and the message says which wallet to sign from. - Approvals are exact. An approval step approves exactly the amount the market or the adapter pulls, never an unlimited amount. The one exception is a full payoff, which approves the payoff plus a margin, as below. When the wallet holds a smaller non-zero allowance, a step that resets it to zero comes first. When the allowance already covers the amount, no approval step is returned.
- A closing repayment ends with
approve(0). The payoff approval carries a margin for interest that accrues until the payment is mined. The last step resets what is left of it. It is returned only when the response also approved. confirmStepIndexis the index of the main transaction: after any approval, before a trailing reset. That transaction carries the action. Watch its hash. Deployment is the only write with a confirm endpoint, so for every other write the result is read back once that transaction is mined.- Gas headroom. When the main transaction simulates on its own,
preflightreads{ "simulated": true, "gasEstimate": "..." }and the main step carriesgasLimit, the estimate plus 30 percent. When an approval comes first, the main transaction usually cannot be estimated on its own, because that approval is not mined yet. The API then simulates the approvals and the main call together, in order, fromfrom(eth_simulateV1):- The bundle passes. The main step carries
gasLimit, the gas the bundle used plus 50 percent, andpreflightreads{ "simulated": true, "basis": "approvals-applied", "gasEstimate", "note" }, as in the example above. - The main call reverts in the bundle. The build is refused with
409 TX_WOULD_REVERTand the decoded refusal, as for a single call. - The bundle cannot be simulated, for example on a node without
eth_simulateV1. The response carriespreflight.simulated: falsewith anote, and the main step has nogasLimit. The market’s own checks before the token transfer passed. Estimate the gas once the approval is mined.
- The bundle passes. The main step carries
400 VALIDATION_ERROR with details[].field set to the name of that field (several unknown fields are joined with commas), except instanceId, which is accepted and ignored. A body with a field named for key material, such as privateKey or mnemonic, answers 400 KEY_MATERIAL_REJECTED.
Units
Addresses are0x followed by 40 hex characters. A mixed-case address must pass its EIP-55 checksum, an all-lowercase one is accepted, and the zero address is refused. Amounts you send are decimal strings in whole units of the token, for example "10000" for 10,000 USDC, parsed at the token’s decimals. A finer fraction answers VALIDATION_ERROR. Amounts returned are integer strings in the token’s smallest unit. Most carry a ...Formatted twin in whole units. These do not: premiumA, premiumB, baseAccrued, coverageWindowInterest, coverageLimit, totalClaimable, trussetFeesPayable, the interest, principal and fee parts of payoff, deployment.repayFee on Build Deployment, repayFee on the role assignment record, and the assetAmount, lockedAmount, sellerRequired, sellerFrozen and sellerBalance of assetLeg. Asset amounts are in the asset token’s smallest unit, every other amount in the payment token’s. Rates are basis points per year. Terms are sent in days. Listings return their runtime, interest period and grace period in seconds, and every time as unix seconds.
State is read from the chain
The API records a market when its deployment is confirmed and keeps no record of listings, loans or balances. Every other state is read from the chain through Get Listing, Get Loan Status and Get Claimable. A new listing’s ID is theid of the ListingCreated event in the receipt of the listing transaction. IDs count up from 1 on each market, and total on List Listings is the highest one.
Deployment
- Read Get Deployment Options for the factory, the modes, the default configuration, the bounds and the payment tokens of your network.
- Build the deployment with Build Deployment.
frommust be a verified wallet of your instance. Any other wallet answers403 DEPLOYMENT_NOT_INSTANCE_BOUNDbefore any calldata exists. The API checks both tokens, the market identity register when you name one (it must have code, must not be either token or the retired Trusset ID Register, and must answerisVerified(address)), the asset’s freeze surface in freeze mode and the payment token’s decimals, then simulates the deployment fromfrom. - Sign and broadcast the single
deployMarketstep from that wallet. - Record it with Record Deployment and the transaction hash. The API verifies the receipt against the factory and requires the signer to be a verified wallet of your instance. A deployment sent through a Safe, an EIP-7702 account or an ERC-4337 smart account is accepted: the API reads the wrapped call and takes the
MarketDeployedevent of the signing wallet. The answer carries the market record, the role assignment record and the token-side setup. - Complete the token-side setup with Build Token Setup, signed on the token issuer’s side.
- Keep the role assignment record. Get Role Audit rebuilds it from the deployment receipt, checks each role live, and lists today’s role holders and every role, register and implementation change since. Get Role Certificate renders it as a PDF certificate under the same
docRef, on the API key and in the Issuer Portal.
409 MARKET_EXISTS, names the existing market and, in details.repair, the Set Identity Register route that repairs a market deployed with a wrong register. The rule applies when a deployment is built. Record Deployment still records a deployment of the same combination signed from calldata built elsewhere, for example from a saved build. A payment token must use 6 to 18 decimals and debit exactly what it is asked to transfer, so fee-on-transfer tokens are refused on every inbound payment.
Walkthrough
From deployment to completion:- Issuer. Get Deployment Options, then Build Deployment. Sign the step, then Record Deployment with its hash.
- Token owner or register agent. Build Token Setup. Sign the step it returns.
- Seller. Get Quote to size the terms, then Create Listing. Sign the steps, then read the listing ID from the
ListingCreatedevent. - Buyer. List Listings with
status=OPENand Get Listing, then Purchase. Sign the approval and the purchase. The listing readsACTIVE. - Buyer, each period. Get Loan Status for
nextDue. Once the due date has passed and before its grace period ends, Repay the interest due plus the repay fee. - Buyer, at the end. Repay with
amount: "full". Sign the approval, the repayment and the reset. The listing readsREPAID. - Buyer. Claim Asset. The listing reads
COMPLETED. - Seller. Get Claimable, then Withdraw. The seller can withdraw its interest credits at any time during the loan as well.
- Buyer. Misses a due date. After
liquidatableAt, Get Loan Status readsisLiquidatable: true. - Seller or operator. Liquidate. The listing reads
LIQUIDATEDand the asset is back with the seller. On a custody market whose token refuses that return, the adapter holds it in escrow for the seller, and the seller takes it back later with Claim Escrowed Collateral. - Seller and buyer. Each reads Get Claimable and calls Withdraw: the seller for its compensation and interest, the buyer for its refund.
Pausing
The operator can pause a market for new business. A pause also stops liquidation.Errors
409 TX_WOULD_REVERT means the transaction would revert on-chain, so nothing was built. details.error names the decoded contract error and details.args its arguments, and message explains it, as listed under Contract refusals below. A revert with a text reason, typically from a token, has error: "Error" and the message “The transaction would revert: ” followed by the reason. A revert the API cannot decode has error: null. details.action names the operation and details.revertData carries the raw revert data.
Some refusals come from the API’s own reads before any simulation, with the same code and contract error name and without args or revertData: InsufficientDownpaymentCoverage on Create Listing with details.terms, ListingExpired with details.expiresAt, AgentRoleMissing and InsufficientFreeBalance on Purchase, NotBuyer on Claim Asset with details.requiredRole and details.buyer, NotLiquidatable on Liquidate with details.liquidatableAt, and NothingToWithdraw on Withdraw.
503 CHAIN_UNAVAILABLE means the chain could not be read. Nothing was changed or built. Retry shortly.
Contract refusals
Contract refusals
Rate limits
Every request made with an API key counts against a ceiling of 200 requests per minute for that key. Every write on this API, and Get Role Certificate, also draws on a budget of 10 per minute, and every other read on one of 100 per minute. Each budget is counted per API key across every endpoint that carries it, not per endpoint, and the same two budgets also cover the lending, trading and other product endpoints that carry them. A burst of lending writes therefore leaves fewer Seller Financing writes in that minute. On every route that names a market, the budget is counted before the market is resolved, so a request for a market your instance does not reach still draws on it. Exceeding a limit returns429 with code RATE_LIMIT_EXCEEDED and a Retry-After header in seconds. The 200 per minute ceiling reports its state in X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. The two tighter budgets report theirs in RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. See Rate Limits.
Trust boundaries
- The token issuer keeps its powers over the asset. In freeze mode another agent of the token can unfreeze or force-transfer the frozen amount, and a recovery of the seller’s wallet by the issuer strands the lock. The market refuses a seller that is an agent of the token, but cannot refuse an agent role granted after the purchase. In custody mode an agent can force-transfer tokens out of the adapter, and the delivery then reverts. The issuer can also refuse every recipient or revoke the freeze adapter’s agent role.
- Refunds wait for the asset. Cancellation and liquidation return the asset before any money settles. While the freeze adapter lacks its agent role, or the custody adapter holds less than it recorded, they revert and the escrow waits until the token issuer restores the role or the holdings. A custody return the token merely refuses does not block them: the adapter keeps the asset in escrow for the seller.
- Delivery waits for the asset. A payoff credits the seller the full price, while the delivery to the buyer can revert once the asset left the seller’s wallet or the adapter. The API refuses the payoff and the claim while it reads that state (Asset leg), but it cannot stop an agent of the token from moving the asset after the payoff is mined.
- The payment-token issuer can block repayments. A paused stablecoin, or one that starts charging a transfer fee, makes every repayment revert, while liquidation, which moves no payment tokens, stays open. The operator’s only defence is pausing the market, which also stops liquidation.
- The admin can upgrade the market. An upgraded implementation is not bound by these rules. Compare the market’s ERC-1967 implementation slot with
marketImplementation()on the factory. - Configuration and screening apply to new business. A configuration change mined just before a pending listing applies to it, so check the terms stamped on the listing and cancel one you do not accept. A purchase re-checks that the seller holds no agent role on the asset token, but not that the seller is still verified on the market identity register, and anyone can repay a loan. The operator cancels the open listings of a seller who loses verification. A register change through Set Identity Register reaches new listings and purchases only.
