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

# Symbols

> The symbols you can trade: units, the sizes you may order and which sides are offered.

A symbol is one product on the board, such as `GOLD_TRADE_999`. The symbols entity tells your program what it may send in `POST /orders` **before** it sends it: the measure of `quantity`, the sizes your account may order and whether a buy or a sell is offered to you. It carries no price; prices are on [Market data](/api-reference/rates/overview). Test and production return the same answer.

| Call | Endpoint | Scope |
| - | - | - |
| [List symbols](#read-the-symbols) | `GET /symbols` | `rates:read` |
| [One symbol](#read-one-symbol) | `GET /symbols/{symbol_code}` | `rates:read` |

Each path sits under the test base path `/api/trading/test/v1` or the production base path `/api/trading/v1`:

| Environment | List | One symbol |
| - | - | - |
| Test | `/api/trading/test/v1/symbols` | `/api/trading/test/v1/symbols/{symbol_code}` |
| Production | `/api/trading/v1/symbols` | `/api/trading/v1/symbols/{symbol_code}` |

## The symbol object

| Field | Type | Meaning |
| - | - | - |
| `symbol_code` | string | The code you send as `symbol_code` in an order. |
| `display_name` | string | The symbol's name on the board. |
| `description` | string or null | The line shown under the name on the board. |
| `metal` | string | `gold` or `silver`. |
| `unit` | string | What the price is quoted per, for example `10 gram` or `kg`. |
| `quantity_unit` | string | The measure an order's `quantity` is in: `g` or `kg`. |
| `quantity_rule` | object or null | The sizes you may order (below). `null` when no size rule is published for the symbol: any positive quantity within your weight allocation. |
| `is_trading` | boolean | The symbol's trading switch. |
| `buy_enabled` | boolean | A market buy is offered to you: buying is offered, your account may trade and the symbol is trading. |
| `sell_enabled` | boolean | The same, for a market sell. |

`quantity_rule`, when present:

| Field | Type | Meaning |
| - | - | - |
| `min` | string or null | The smallest quantity, in `quantity_unit`. `null` = no minimum. |
| `max` | string or null | The largest quantity, in `quantity_unit`. `null` = no maximum. |
| `step` | string or null | Quantities must be a multiple of this. `null` = any. |
| `label` | string | The rule in words, as the app shows it. |

`quantity_unit` follows the symbol's **unit**, not its metal: a symbol quoted per `10 gram` is ordered in grams, even when its metal is silver. Always read it rather than assuming silver means kilograms.

## Read the symbols

```bash curl theme={null}
curl -s https://api.bullionwale.com/api/trading/test/v1/symbols \
  -H "X-API-Key: $BULLIONWALE_API_KEY"
```

```python Python theme={null}
import os
import requests

BASE = "https://api.bullionwale.com/api/trading/test/v1"
HEADERS = {"X-API-Key": os.environ["BULLIONWALE_API_KEY"]}

for s in requests.get(f"{BASE}/symbols", headers=HEADERS, timeout=10).json()["items"]:
    print(s["symbol_code"], s["quantity_unit"], s["quantity_rule"])
```

```json 200 OK theme={null}
{
  "items": [
    {"symbol_code": "GOLD_TRADE_999", "display_name": "Gold 999", "description": null,
     "metal": "gold", "unit": "10 gram", "quantity_unit": "g",
     "quantity_rule": {"min": "10", "max": "3000", "step": "10",
                       "label": "between 10 and 3000 gm in multiples of 10"},
     "is_trading": true, "buy_enabled": true, "sell_enabled": true},
    {"symbol_code": "SILVER_999", "display_name": "Silver 999", "description": null,
     "metal": "silver", "unit": "kg", "quantity_unit": "kg", "quantity_rule": null,
     "is_trading": true, "buy_enabled": true, "sell_enabled": true}
  ],
  "total": 2
}
```

The list holds every **active** symbol, sorted by `symbol_code`. It takes `limit` (1 to 200, default 50) and `offset`, like `GET /orders`.

## Read one symbol

```bash curl theme={null}
curl -s https://api.bullionwale.com/api/trading/test/v1/symbols/GOLD_TRADE_999 \
  -H "X-API-Key: $BULLIONWALE_API_KEY"
```

```python Python theme={null}
import os
import requests

BASE = "https://api.bullionwale.com/api/trading/test/v1"
HEADERS = {"X-API-Key": os.environ["BULLIONWALE_API_KEY"]}

s = requests.get(f"{BASE}/symbols/GOLD_TRADE_999", headers=HEADERS, timeout=10).json()
print(s["quantity_unit"], s["quantity_rule"], s["buy_enabled"], s["sell_enabled"])
```

```json 200 OK theme={null}
{
  "symbol_code": "GOLD_TRADE_999",
  "display_name": "Gold 999",
  "description": null,
  "metal": "gold",
  "unit": "10 gram",
  "quantity_unit": "g",
  "quantity_rule": {"min": "10", "max": "3000", "step": "10",
                    "label": "between 10 and 3000 gm in multiples of 10"},
  "is_trading": true,
  "buy_enabled": true,
  "sell_enabled": true
}
```

A symbol that does not exist or is not active answers `404 unknown_symbol`.

## Checking an order before you send it

With the symbol and `quantity_rule` in hand, your program can catch most size mistakes locally:

```python theme={null}
from decimal import Decimal


def size_ok(quantity: Decimal, rule: dict | None) -> bool:
    if rule is None:
        return quantity > 0
    if rule["min"] is not None and quantity < Decimal(rule["min"]):
        return False
    if rule["max"] is not None and quantity > Decimal(rule["max"]):
        return False
    if rule["step"] is not None and quantity % Decimal(rule["step"]) != 0:
        return False
    return True


rule = {"min": "10", "max": "3000", "step": "10", "label": "between 10 and 3000 gm in multiples of 10"}
assert size_ok(Decimal("50"), rule) and not size_ok(Decimal("55"), rule)
```

Then check the side: send a buy only when `buy_enabled` is `true`, a sell only when `sell_enabled` is `true`. This list is a guide; the order check is the authority. An order outside the rule is refused with `400 quantity_rule` (the symbol's own rule) or `400 group_quantity_rule` (your account's trading terms), and a side that is not offered with `403 side_not_offered`. Live conditions are not here: trading halts and frozen prices are on [Market data](/api-reference/rates/overview) and [Market status](/api-reference/market/overview), and your remaining weight on [Trading limits](/api-reference/limits/overview).

## Test and production

Symbols are not account money, so both environments return the **same answer**, with the sizes and sides that apply to your account. A test order is checked against the same rules.

## Errors

| Code | Status | Meaning |
| - | - | - |
| `unknown_symbol` | 404 | `GET /symbols/{symbol_code}`: no such active symbol. |
| `pricing_unavailable` | 503 | Your account's trading terms could not be loaded right now. Retry shortly. |
| `insufficient_scope` | 403 | The key does not have `rates:read`. |
| `rate_limited` | 429 | The key's read budget is used up. Wait `Retry-After` seconds. |

Every code is in the [Error reference](/api-reference/error-reference).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.