Order Books
Create Order Book
Open a trading venue for an imported ERC-3643 security
POST
/
orderbooks
/
external-securities
/
api
/
order-books
curl -X POST "https://api.trusset.org/orderbooks/external-securities/api/order-books" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"tokenAddress": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"name": "Helvetia Growth Fund",
"symbol": "HELG",
"underlyingIdentifier": "CH0012032048",
"settlementOperator": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
"tickSize": "10000",
"minOrderSize": "1000000",
"makerFeeBps": 0,
"takerFeeBps": 10,
"allowSharedLiquidity": true
}'
const payload = {
tokenAddress,
quoteTokenAddress,
name: 'Helvetia Growth Fund',
symbol: 'HELG',
underlyingIdentifier: 'CH0012032048',
settlementOperator: await operator.getAddress(),
tickSize: '10000',
minOrderSize: '1000000'
};
let res = await fetch(
'https://api.trusset.org/orderbooks/external-securities/api/order-books',
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
}
);
let body = await res.json();
if (!body.success && body.error.code === 'CUSTODY_SETUP_REQUIRED') {
const custodySetupTxs: Record<string, string> = {};
for (const step of body.error.setup.steps) {
const tx = await wallet.sendTransaction({ to: step.to, data: step.data });
await tx.wait();
custodySetupTxs[step.key] = tx.hash;
}
res = await fetch(
'https://api.trusset.org/orderbooks/external-securities/api/order-books',
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ ...payload, custodySetupTxs })
}
);
body = await res.json();
}
{
"success": true,
"data": {
"id": "clx_ob_extsec_001",
"instanceId": "inst_abc123",
"tokenAddress": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"name": "Helvetia Growth Fund",
"symbol": "HELG",
"status": "ACTIVE",
"tokenType": "EXTERNAL_SECURITY",
"settlementMode": "ON_CHAIN",
"custodyContract": "0x489aee4ae9546081d55848f157e03192e826988c",
"settlementOperator": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
"underlyingIdentifier": "CH0012032048",
"baseDecimals": 18,
"quoteDecimals": 6,
"minOrderSize": "1000000",
"maxOrderSize": null,
"tickSize": "10000",
"makerFeeBps": 0,
"takerFeeBps": 10,
"mmMakerRebateBps": null,
"allowImport": false,
"allowSharedLiquidity": true,
"tradingMode": "CONTINUOUS",
"priceRefEnabled": false,
"priceRefMode": "MANUAL",
"priceRefEnforcement": "EVERY_TRADE",
"priceRefSpreadBps": null,
"createdAt": "2025-06-15T12:00:00.000Z"
}
}
{
"success": false,
"data": null,
"error": {
"code": "CUSTODY_SETUP_REQUIRED",
"message": "This external securities order book needs 3 on-chain transactions signed before it can be created. Sign the returned transactions with the indicated wallet and submit the request again with their transaction hashes in custodySetupTxs.",
"setup": {
"action": "SIGN_TRANSACTIONS",
"custodyContract": "0x489aee4ae9546081d55848f157e03192e826988c",
"confirmWith": { "field": "custodySetupTxs", "keyedBy": "key" },
"steps": [
{
"key": "agentRole",
"to": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"data": "0x...",
"functionName": "addAgent",
"description": "Grant the T-REX agent role on 0x51f2... to the custody contract 0x489a...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
},
{
"key": "quoteAsset",
"to": "0x489aee4ae9546081d55848f157e03192e826988c",
"data": "0x...",
"functionName": "setQuoteAsset",
"description": "Authorize 0x98ad... as a settlement asset for 0x51f2...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
},
{
"key": "operator",
"to": "0x489aee4ae9546081d55848f157e03192e826988c",
"data": "0x...",
"functionName": "setOperator",
"description": "Authorize 0x5ad8... as a settlement operator for 0x51f2...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
}
]
}
}
}
{
"success": false,
"data": null,
"error": {
"code": "ISIN_MISMATCH",
"message": "This security is already registered on the custody contract under \"CH0012032048\". Use that identifier, or ask the token issuer to update it on chain."
}
}
Creates an order book for one imported security token quoted in one settlement asset. Three properties are fixed by this venue and cannot be overridden: settlement is always on-chain, the token type is always an external security, and the trading mode is always continuous.
The book cannot be created until the four on-chain prerequisites hold. See Custody setup.
One instance may hold a single open book per pair. If an
ACTIVE or PAUSED book already quotes this pair, the request returns ORDER_BOOK_EXISTS.
Body Parameters
string
required
The ERC-3643 security token. Must be imported into your instance and readable on chain.
string
required
Settlement asset the security is quoted in. Must be authorized for this security on the custody contract, which is one of the four setup steps. Must differ from
tokenAddress.string
required
Display name, 1 to 64 characters.
string
required
Display symbol, 1 to 16 characters.
string
required
Wallet that will sign settlement transactions for this book. It must be authorized on the custody contract for this security, which is the fourth setup step. Naming a wallet you control is what lets settlements be driven through this API.
string
Instrument identifier, 1 to 31 characters, trimmed and upper-cased. An ISIN, a WKN, or an issuer’s own reference.Required when the security is not yet registered on the custody contract, because registration writes this identifier on chain. Optional afterwards, and if supplied it must match what is already registered, otherwise
ISIN_MISMATCH. The stored value always comes from the chain.string
Custody contract to use. Defaults to the address from Get Custody Contract. Any other address is refused with
INVALID_CONFIG.string
default:"0"
Smallest accepted quantity, in order book units.
string
Largest accepted quantity, in order book units.
string
default:"1"
Price increment, in order book units. Enforced when an order is submitted: a price that is not a multiple is refused with
INVALID_PRICE. Prepare Order does not check it, so a payload can be built at an off-tick price and then rejected on submission.integer
default:"0"
Maker fee in basis points, 0 to 1000.
integer
default:"0"
Taker fee in basis points, 0 to 1000.
integer
Fee applied in place of
makerFeeBps when the resting side is a market maker account, −1000 to 1000. A negative value pays the market maker.boolean
default:"false"
Publish the book so other instances on the same network can import it.
boolean
default:"false"
Pool depth with other books quoting the same instrument identifier. See Shared liquidity.
boolean
default:"false"
Enforce a reference price band on incoming orders.
string
default:"MANUAL"
MANUAL, STOCK_FEED or EXTERNAL_FEED.string
HTTPS feed endpoint, up to 2048 characters. Must resolve to a public host.
string
Feed request headers as a JSON string, up to 4096 characters.
string
JSON path to the price, or the ticker symbol in
STOCK_FEED mode.string
default:"EVERY_TRADE"
Refresh interval, from
EVERY_TRADE to 1DAY.integer
Band half-width in basis points, 1 to 10000.
boolean
default:"false"
Refuse orders when the reference is stale.
integer
Staleness window in seconds, 60 to 604800.
integer
Reference move in basis points that pauses the book, 10 to 10000.
object
Hashes of the setup transactions you signed after a
CUSTODY_SETUP_REQUIRED refusal, keyed by the step key. Unknown keys are rejected.What is read from the chain
Both tokens’ decimals are read at creation and recorded on the book, so every later conversion between order book units and on-chain amounts uses the real numbers rather than a default. A token that reports unusable decimals is refused withTOKEN_METADATA_UNAVAILABLE.
If the RPC endpoint for your instance does not answer, the request fails with CHAIN_UNAVAILABLE rather than reporting the prerequisites as unmet. No book is created and nothing is changed.
Response Fields
Returns201 with the created book.
object
Show child attributes
Show child attributes
string
Order book ID. Use this as
orderBookId everywhere else.string
Owning instance.
string
Security token, lower-cased.
string
Settlement asset, lower-cased.
string
Display name.
string
Display symbol.
string
ACTIVE on creation.string
EXTERNAL_SECURITY.string
ON_CHAIN.string
Custody contract the book settles through.
string
Wallet authorized to sign settlements, lower-cased.
string
Instrument identifier as recorded on chain.
integer
Security token decimals read from chain.
integer
Settlement asset decimals read from chain.
string
Minimum quantity.
string
Maximum quantity, or
null.string
Price increment.
integer
Maker fee in basis points.
integer
Taker fee in basis points.
integer
Market maker fee override, or
null.boolean
Whether other instances may import the book.
boolean
Whether the book pools depth.
string
CONTINUOUS.boolean
Whether the band is enforced.
string
Reference source.
string
Refresh interval.
integer
Band half-width, or
null.string
ISO 8601 timestamp.
curl -X POST "https://api.trusset.org/orderbooks/external-securities/api/order-books" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"tokenAddress": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"name": "Helvetia Growth Fund",
"symbol": "HELG",
"underlyingIdentifier": "CH0012032048",
"settlementOperator": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
"tickSize": "10000",
"minOrderSize": "1000000",
"makerFeeBps": 0,
"takerFeeBps": 10,
"allowSharedLiquidity": true
}'
const payload = {
tokenAddress,
quoteTokenAddress,
name: 'Helvetia Growth Fund',
symbol: 'HELG',
underlyingIdentifier: 'CH0012032048',
settlementOperator: await operator.getAddress(),
tickSize: '10000',
minOrderSize: '1000000'
};
let res = await fetch(
'https://api.trusset.org/orderbooks/external-securities/api/order-books',
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
}
);
let body = await res.json();
if (!body.success && body.error.code === 'CUSTODY_SETUP_REQUIRED') {
const custodySetupTxs: Record<string, string> = {};
for (const step of body.error.setup.steps) {
const tx = await wallet.sendTransaction({ to: step.to, data: step.data });
await tx.wait();
custodySetupTxs[step.key] = tx.hash;
}
res = await fetch(
'https://api.trusset.org/orderbooks/external-securities/api/order-books',
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ ...payload, custodySetupTxs })
}
);
body = await res.json();
}
{
"success": true,
"data": {
"id": "clx_ob_extsec_001",
"instanceId": "inst_abc123",
"tokenAddress": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"name": "Helvetia Growth Fund",
"symbol": "HELG",
"status": "ACTIVE",
"tokenType": "EXTERNAL_SECURITY",
"settlementMode": "ON_CHAIN",
"custodyContract": "0x489aee4ae9546081d55848f157e03192e826988c",
"settlementOperator": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
"underlyingIdentifier": "CH0012032048",
"baseDecimals": 18,
"quoteDecimals": 6,
"minOrderSize": "1000000",
"maxOrderSize": null,
"tickSize": "10000",
"makerFeeBps": 0,
"takerFeeBps": 10,
"mmMakerRebateBps": null,
"allowImport": false,
"allowSharedLiquidity": true,
"tradingMode": "CONTINUOUS",
"priceRefEnabled": false,
"priceRefMode": "MANUAL",
"priceRefEnforcement": "EVERY_TRADE",
"priceRefSpreadBps": null,
"createdAt": "2025-06-15T12:00:00.000Z"
}
}
{
"success": false,
"data": null,
"error": {
"code": "CUSTODY_SETUP_REQUIRED",
"message": "This external securities order book needs 3 on-chain transactions signed before it can be created. Sign the returned transactions with the indicated wallet and submit the request again with their transaction hashes in custodySetupTxs.",
"setup": {
"action": "SIGN_TRANSACTIONS",
"custodyContract": "0x489aee4ae9546081d55848f157e03192e826988c",
"confirmWith": { "field": "custodySetupTxs", "keyedBy": "key" },
"steps": [
{
"key": "agentRole",
"to": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"data": "0x...",
"functionName": "addAgent",
"description": "Grant the T-REX agent role on 0x51f2... to the custody contract 0x489a...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
},
{
"key": "quoteAsset",
"to": "0x489aee4ae9546081d55848f157e03192e826988c",
"data": "0x...",
"functionName": "setQuoteAsset",
"description": "Authorize 0x98ad... as a settlement asset for 0x51f2...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
},
{
"key": "operator",
"to": "0x489aee4ae9546081d55848f157e03192e826988c",
"data": "0x...",
"functionName": "setOperator",
"description": "Authorize 0x5ad8... as a settlement operator for 0x51f2...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
}
]
}
}
}
{
"success": false,
"data": null,
"error": {
"code": "ISIN_MISMATCH",
"message": "This security is already registered on the custody contract under \"CH0012032048\". Use that identifier, or ask the token issuer to update it on chain."
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 400 | A field failed schema validation |
INVALID_PAIR | 400 | Base and quote token are the same |
INVALID_CONFIG | 400 | settlementOperator is missing or malformed, a non-custody address was supplied, or a price reference field is invalid |
TOKEN_NO_ISIN | 400 | The security is unregistered and no identifier was supplied, or the registered security has no readable identifier |
ISIN_MISMATCH | 400 | The declared identifier does not match what is registered on chain |
ORDER_BOOK_EXISTS | 409 | An ACTIVE or PAUSED book already quotes this pair |
CUSTODY_SETUP_REQUIRED | 409 | On-chain prerequisites are outstanding. error.setup.steps carries the unsigned transactions |
SECURITY_INACTIVE | 409 | The token issuer has deactivated this security on the custody contract |
INVALID_CUSTODY_CONTRACT | 400 | The address did not answer as the external securities custody contract |
TOKEN_METADATA_UNAVAILABLE | 502 | Token decimals could not be read, or are outside the usable range |
CHAIN_UNAVAILABLE | 502 | The RPC endpoint for your instance did not answer |
CUSTODY_NOT_DEPLOYED | 503 | No custody contract is deployed on your instance’s network |
SERVICE_NOT_ENABLED | 403 | The Trading service is not enabled on this instance |
⌘I
curl -X POST "https://api.trusset.org/orderbooks/external-securities/api/order-books" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"tokenAddress": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"name": "Helvetia Growth Fund",
"symbol": "HELG",
"underlyingIdentifier": "CH0012032048",
"settlementOperator": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
"tickSize": "10000",
"minOrderSize": "1000000",
"makerFeeBps": 0,
"takerFeeBps": 10,
"allowSharedLiquidity": true
}'
const payload = {
tokenAddress,
quoteTokenAddress,
name: 'Helvetia Growth Fund',
symbol: 'HELG',
underlyingIdentifier: 'CH0012032048',
settlementOperator: await operator.getAddress(),
tickSize: '10000',
minOrderSize: '1000000'
};
let res = await fetch(
'https://api.trusset.org/orderbooks/external-securities/api/order-books',
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
}
);
let body = await res.json();
if (!body.success && body.error.code === 'CUSTODY_SETUP_REQUIRED') {
const custodySetupTxs: Record<string, string> = {};
for (const step of body.error.setup.steps) {
const tx = await wallet.sendTransaction({ to: step.to, data: step.data });
await tx.wait();
custodySetupTxs[step.key] = tx.hash;
}
res = await fetch(
'https://api.trusset.org/orderbooks/external-securities/api/order-books',
{
method: 'POST',
headers: {
'X-API-Key': 'trusset_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ ...payload, custodySetupTxs })
}
);
body = await res.json();
}
{
"success": true,
"data": {
"id": "clx_ob_extsec_001",
"instanceId": "inst_abc123",
"tokenAddress": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
"name": "Helvetia Growth Fund",
"symbol": "HELG",
"status": "ACTIVE",
"tokenType": "EXTERNAL_SECURITY",
"settlementMode": "ON_CHAIN",
"custodyContract": "0x489aee4ae9546081d55848f157e03192e826988c",
"settlementOperator": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
"underlyingIdentifier": "CH0012032048",
"baseDecimals": 18,
"quoteDecimals": 6,
"minOrderSize": "1000000",
"maxOrderSize": null,
"tickSize": "10000",
"makerFeeBps": 0,
"takerFeeBps": 10,
"mmMakerRebateBps": null,
"allowImport": false,
"allowSharedLiquidity": true,
"tradingMode": "CONTINUOUS",
"priceRefEnabled": false,
"priceRefMode": "MANUAL",
"priceRefEnforcement": "EVERY_TRADE",
"priceRefSpreadBps": null,
"createdAt": "2025-06-15T12:00:00.000Z"
}
}
{
"success": false,
"data": null,
"error": {
"code": "CUSTODY_SETUP_REQUIRED",
"message": "This external securities order book needs 3 on-chain transactions signed before it can be created. Sign the returned transactions with the indicated wallet and submit the request again with their transaction hashes in custodySetupTxs.",
"setup": {
"action": "SIGN_TRANSACTIONS",
"custodyContract": "0x489aee4ae9546081d55848f157e03192e826988c",
"confirmWith": { "field": "custodySetupTxs", "keyedBy": "key" },
"steps": [
{
"key": "agentRole",
"to": "0x51f2b9d0e77c4a1b83ce6d4a9271e5f3a0c8b912",
"data": "0x...",
"functionName": "addAgent",
"description": "Grant the T-REX agent role on 0x51f2... to the custody contract 0x489a...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
},
{
"key": "quoteAsset",
"to": "0x489aee4ae9546081d55848f157e03192e826988c",
"data": "0x...",
"functionName": "setQuoteAsset",
"description": "Authorize 0x98ad... as a settlement asset for 0x51f2...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
},
{
"key": "operator",
"to": "0x489aee4ae9546081d55848f157e03192e826988c",
"data": "0x...",
"functionName": "setOperator",
"description": "Authorize 0x5ad8... as a settlement operator for 0x51f2...",
"requiredSigner": "0x7712db30a7b4ffd9c445793089118b60e56d752a",
"requiredRole": null
}
]
}
}
}
{
"success": false,
"data": null,
"error": {
"code": "ISIN_MISMATCH",
"message": "This security is already registered on the custody contract under \"CH0012032048\". Use that identifier, or ask the token issuer to update it on chain."
}
}
