> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trusset.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Order Book

> Open a trading venue for a commodity token

Creates an order book for one commodity token quoted in one settlement token (stablecoin). Settlement is always on-chain through `CommodityCustody`, and a custody contract is required.

The book cannot be created until the custody contract admits both tokens. See [Custody setup](/endpoints/commodity-trading/introduction#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`; a `CLOSED` book does not block a new one.

## Body Parameters

<ParamField body="tokenAddress" type="string" required>
  Commodity token contract. Lower-cased before storage.
</ParamField>

<ParamField body="quoteTokenAddress" type="string" required>
  Settlement token contract. A well-known USDC address is normalised to your network's USDC. Must differ from `tokenAddress`.
</ParamField>

<ParamField body="name" type="string" required>Display name, 1 to 64 characters.</ParamField>

<ParamField body="symbol" type="string" required>Display symbol, 1 to 16 characters.</ParamField>

<ParamField body="custodyContract" type="string" required>
  The commodity custody contract for your network. It must be the commodity flavour: the stock custody contract is refused with `INVALID_CONFIG`, since it cannot register commodity tokens. Any existing commodity book on your instance carries the right address in its `custodyContract` field.
</ParamField>

<ParamField body="settlementMode" type="string" default="ON_CHAIN">
  Only `ON_CHAIN` is accepted, and it is the default. There is no off-chain mode on this venue.
</ParamField>

<ParamField body="minOrderSize" type="string" default="0">Smallest accepted quantity, in order book units.</ParamField>

<ParamField body="maxOrderSize" type="string">Largest accepted quantity, in order book units. Omit for no ceiling.</ParamField>

<ParamField body="tickSize" type="string" default="1">Price increment, in order book units.</ParamField>

<ParamField body="makerFeeBps" type="integer" default="0">Maker fee in basis points, 0 to 1000.</ParamField>

<ParamField body="takerFeeBps" type="integer" default="0">Taker fee in basis points, 0 to 1000.</ParamField>

<ParamField body="allowImport" type="boolean" default="false">
  Publish the book so other instances on the same network can import it.
</ParamField>

<ParamField body="allowSharedLiquidity" type="boolean" default="false">
  Pool depth with other books in the same fungibility class. Setting this requires a usable reserve attestation for the token; without one the request is refused rather than silently creating an unpooled book. See [Fungibility classes](/endpoints/commodity-trading/introduction#fungibility-classes).
</ParamField>

<ParamField body="priceRefEnabled" type="boolean" default="false">Enforce a reference price band on incoming orders.</ParamField>

<ParamField body="priceRefMode" type="string" default="MANUAL">`MANUAL`, `STOCK_FEED` or `EXTERNAL_FEED`.</ParamField>

<ParamField body="priceRefFeedUrl" type="string">HTTPS feed endpoint, up to 2048 characters. Must resolve to a public host.</ParamField>

<ParamField body="priceRefFeedHeaders" type="string">Feed request headers as a JSON string, up to 4096 characters. `Host`, `Cookie` and `Authorization` are dropped.</ParamField>

<ParamField body="priceRefFeedPath" type="string">JSON path to the price, or the ticker symbol in `STOCK_FEED` mode. Up to 256 characters.</ParamField>

<ParamField body="priceRefEnforcement" type="string" default="EVERY_TRADE">Refresh interval, from `EVERY_TRADE` to `1DAY`.</ParamField>

<ParamField body="priceRefSpreadBps" type="integer">Band half-width in basis points, 1 to 10000. Without it no band is enforced.</ParamField>

<ParamField body="priceRefHaltOnStale" type="boolean" default="false">Refuse orders when the reference is stale.</ParamField>

<ParamField body="priceRefStaleTolerance" type="integer">Staleness window in seconds, 60 to 604800.</ParamField>

<ParamField body="priceRefCircuitBreakerBps" type="integer">Reference move in basis points that pauses the book, 10 to 10000.</ParamField>

<ParamField body="custodySetupTxs" type="object">
  Hashes of the custody transactions you signed after a `CUSTODY_SETUP_REQUIRED` refusal. Unknown keys are rejected.

  <Expandable>
    <ParamField body="baseToken" type="string">Hash of `addSupportedToken` for the commodity token.</ParamField>
    <ParamField body="quoteToken" type="string">Hash of `addSupportedToken` for the settlement token.</ParamField>
  </Expandable>
</ParamField>

## Response Fields

Returns `201` with the created book.

<ResponseField name="data" type="object">
  <Expandable>
    <ResponseField name="id" type="string">Order book ID. Use this as `orderBookId` everywhere else.</ResponseField>
    <ResponseField name="instanceId" type="string">Owning instance.</ResponseField>
    <ResponseField name="tokenAddress" type="string">Commodity token, lower-cased.</ResponseField>
    <ResponseField name="quoteTokenAddress" type="string">Settlement token, lower-cased and normalised.</ResponseField>
    <ResponseField name="name" type="string">Display name.</ResponseField>
    <ResponseField name="symbol" type="string">Display symbol.</ResponseField>
    <ResponseField name="status" type="string">`ACTIVE` on creation.</ResponseField>
    <ResponseField name="tokenType" type="string">`LIGHT_TOKEN`.</ResponseField>
    <ResponseField name="settlementMode" type="string">`ON_CHAIN`.</ResponseField>
    <ResponseField name="custodyContract" type="string">Custody contract the book settles through.</ResponseField>

    <ResponseField name="cfid" type="string">
      Fungibility class derived from the token's reserve attestation, or `null` when pooling was not requested or no attestation was usable.
    </ResponseField>

    <ResponseField name="minOrderSize" type="string">Minimum quantity.</ResponseField>
    <ResponseField name="maxOrderSize" type="string">Maximum quantity, or `null`.</ResponseField>
    <ResponseField name="tickSize" type="string">Price increment.</ResponseField>
    <ResponseField name="makerFeeBps" type="integer">Maker fee in basis points.</ResponseField>
    <ResponseField name="takerFeeBps" type="integer">Taker fee in basis points.</ResponseField>
    <ResponseField name="allowImport" type="boolean">Whether other instances may import the book.</ResponseField>
    <ResponseField name="allowSharedLiquidity" type="boolean">Whether the book pools depth.</ResponseField>
    <ResponseField name="tradingMode" type="string">`CONTINUOUS`.</ResponseField>
    <ResponseField name="underlyingIdentifier" type="string">`null` on this venue.</ResponseField>
    <ResponseField name="baseDecimals" type="integer">`null` on this venue.</ResponseField>
    <ResponseField name="quoteDecimals" type="integer">`null` on this venue.</ResponseField>
    <ResponseField name="priceRefEnabled" type="boolean">Whether the band is enforced.</ResponseField>
    <ResponseField name="priceRefMode" type="string">Reference source.</ResponseField>
    <ResponseField name="priceRefEnforcement" type="string">Refresh interval.</ResponseField>
    <ResponseField name="priceRefSpreadBps" type="integer">Band half-width, or `null`.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 timestamp.</ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.trusset.org/orderbooks/commodities/api/order-books" \
    -H "X-API-Key: trusset_your_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "tokenAddress": "0xd8f3ba9de5b7b83f66d1a7b1ad96c1a64b811ff9",
      "quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
      "name": "Allocated Gold 999.9",
      "symbol": "XAUA",
      "custodyContract": "0xf3dac9cf19da1c95a80de890e200bc86e0c6f2da",
      "tickSize": "10000",
      "minOrderSize": "1000000",
      "makerFeeBps": 2,
      "takerFeeBps": 8,
      "allowSharedLiquidity": true
    }'
  ```

  ```typescript TypeScript theme={null}
  const payload = {
    tokenAddress,
    quoteTokenAddress,
    name: 'Allocated Gold 999.9',
    symbol: 'XAUA',
    custodyContract,
    tickSize: '10000',
    minOrderSize: '1000000',
    allowSharedLiquidity: true
  };

  let body = await fetch(
    'https://api.trusset.org/orderbooks/commodities/api/order-books',
    {
      method: 'POST',
      headers: {
        'X-API-Key': 'trusset_your_key_here',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    }
  ).then(r => r.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 admin.sendTransaction({ to: step.to, data: step.data });
      await tx.wait();
      custodySetupTxs[step.key] = tx.hash;
    }
    // repeat the same POST with custodySetupTxs
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "id": "clx_ob_comm_001",
      "instanceId": "inst_abc123",
      "tokenAddress": "0xd8f3ba9de5b7b83f66d1a7b1ad96c1a64b811ff9",
      "quoteTokenAddress": "0x98ad0ca091552e23c564b41c74282e5343d03e8a",
      "name": "Allocated Gold 999.9",
      "symbol": "XAUA",
      "status": "ACTIVE",
      "tokenType": "LIGHT_TOKEN",
      "settlementMode": "ON_CHAIN",
      "custodyContract": "0xf3dac9cf19da1c95a80de890e200bc86e0c6f2da",
      "cfid": "0x6b1f0d2c8a3e57941b6d0af25c8e3714b90d6f2a41c5e807396ba2d5f10c84e7",
      "minOrderSize": "1000000",
      "maxOrderSize": null,
      "tickSize": "10000",
      "makerFeeBps": 2,
      "takerFeeBps": 8,
      "allowImport": false,
      "allowSharedLiquidity": true,
      "tradingMode": "CONTINUOUS",
      "underlyingIdentifier": null,
      "baseDecimals": null,
      "quoteDecimals": null,
      "priceRefEnabled": false,
      "priceRefMode": "MANUAL",
      "priceRefEnforcement": "EVERY_TRADE",
      "priceRefSpreadBps": null,
      "createdAt": "2025-06-15T12:00:00.000Z"
    }
  }
  ```

  ```json Error - Custody Setup Required theme={null}
  {
    "success": false,
    "data": null,
    "error": {
      "code": "CUSTODY_SETUP_REQUIRED",
      "message": "This on-chain order book needs 2 custody 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": "0xf3dac9cf19da1c95a80de890e200bc86e0c6f2da",
        "confirmWith": { "field": "custodySetupTxs", "keyedBy": "key" },
        "steps": [
          {
            "key": "baseToken",
            "to": "0xf3dac9cf19da1c95a80de890e200bc86e0c6f2da",
            "data": "0x...",
            "functionName": "addSupportedToken",
            "description": "Register 0xd8f3... as a supported commodity custody token",
            "requiredSigner": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
            "requiredRole": null
          },
          {
            "key": "quoteToken",
            "to": "0xf3dac9cf19da1c95a80de890e200bc86e0c6f2da",
            "data": "0x...",
            "functionName": "addSupportedToken",
            "description": "Register 0x98ad... as a supported commodity custody token",
            "requiredSigner": "0x5ad87a0621175206b72d10e4b8577b192e7f40ab",
            "requiredRole": null
          }
        ]
      }
    }
  }
  ```

  ```json Error - No Usable Attestation theme={null}
  {
    "success": false,
    "data": null,
    "error": {
      "code": "ATTESTATION_NOT_FOUND",
      "message": "No reserve attestation exists for this commodity token"
    }
  }
  ```
</ResponseExample>

## 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` | The custody contract is the stock flavour, or a price reference field is invalid                   |
| `INVALID_CUSTODY_CONTRACT`  | `400` | The address does not resolve to a Trusset custody contract on this network                         |
| `ATTESTATION_NOT_FOUND`     | `400` | Pooling was requested but no reserve attestation exists for the token                              |
| `ATTESTATION_INCOMPLETE`    | `400` | The attestation carries no valid fungibility classification                                        |
| `CFID_UNVERIFIED`           | `400` | The attested symbol does not match the token's on-chain symbol, or the class could not be computed |
| `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      |
| `BASE_TOKEN_NOT_SUPPORTED`  | `503` | The custody contract does not admit the commodity token and no setup step could be built           |
| `QUOTE_TOKEN_NOT_SUPPORTED` | `503` | The custody contract does not admit the settlement token and no setup step could be built          |
| `SERVICE_NOT_ENABLED`       | `403` | The Trading service is not enabled on this instance                                                |
