> ## 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.

# Market data

> Your live Buy and Sell rates per symbol, with freshness and trading flags.

Market data is the live rate board as **your account** sees it: the Buy rate you buy at and the Sell rate you sell at, for every active symbol. If your account has special pricing, these are your prices, the same ones the Bullionwale app shows you. Test and production return the same live prices.

| Call | Endpoint | Scope |
| - | - | - |
| [List rates](#read-the-rates) | `GET /rates` | `rates:read` |
| [One rate](#read-one-rate) | `GET /rates/{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/rates` | `/api/trading/test/v1/rates/{symbol_code}` |
| Production | `/api/trading/v1/rates` | `/api/trading/v1/rates/{symbol_code}` |

## The rate object

| Field | Type | Meaning |
| - | - | - |
| `symbol_code` | string | The symbol, for example `GOLD_TRADE_999`. Send it as `symbol_code` in an order. |
| `display_name` | string or null | The symbol's name on the board. |
| `metal` | string | `gold` or `silver`. |
| `unit` | string | What the price is quoted per: `10 gram` for the gold symbols, `kg` for silver. |
| `quantity_unit` | string | The measure an order's `quantity` is in: `g` or `kg`. |
| `buy` | string or null | Your Buy rate in rupees per `unit`, 2 decimals. `null` when the symbol has no buy price right now. |
| `sell` | string or null | Your Sell rate in rupees per `unit`, 2 decimals. `null` when the symbol has no sell price right now. |
| `updated_at` | string or null | When this rate was last published (ISO 8601 with its offset). |
| `is_trading` | boolean | The symbol accepts orders right now: its trading switch is on, trading is not halted and its price is not frozen. |
| `frozen` | boolean | The price has not moved for a while, so trading on it is paused until it moves (orders are refused with `400 symbol_frozen`). |
| `stale` | boolean | The rate cannot be traded on: the live feed has not confirmed it in the last few seconds, or the symbol is unpriced. An order would be refused with `503 stale_rate` or `400 unpriced`. |

A price is per `unit`, a quantity is in `quantity_unit`. A gold rate per `10 gram` and an order of `10` grams is worth one rate, not ten: see [Units and pricing](/units-and-pricing). Parse every amount as a decimal, not a float.

## Read the rates

```bash curl theme={null}
curl -s https://api.bullionwale.com/api/trading/test/v1/rates \
  -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"]}

rates = requests.get(f"{BASE}/rates", headers=HEADERS, timeout=10).json()
for r in rates["items"]:
    print(r["symbol_code"], r["buy"], r["sell"], r["stale"])
```

```json 200 OK theme={null}
{
  "items": [
    {"symbol_code": "GOLD_TRADE_999", "display_name": "Gold 999", "metal": "gold",
     "unit": "10 gram", "quantity_unit": "g", "buy": "141250.00", "sell": "141100.00",
     "updated_at": "2026-10-21T09:31:05.120000+00:00", "is_trading": true,
     "frozen": false, "stale": false},
    {"symbol_code": "SILVER_999", "display_name": "Silver 999", "metal": "silver",
     "unit": "kg", "quantity_unit": "kg", "buy": "171000.00", "sell": "170500.00",
     "updated_at": "2026-10-21T09:31:05.120000+00:00", "is_trading": true,
     "frozen": false, "stale": false}
  ],
  "total": 2
}
```

* The list holds every **active** symbol that has a published rate, sorted by `symbol_code`. `total` counts them all.
* It takes `limit` (1 to 200, default 50) and `offset`, like `GET /orders`. The board is short, so one call normally returns it whole.

## Read one rate

```bash curl theme={null}
curl -s https://api.bullionwale.com/api/trading/test/v1/rates/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"]}

r = requests.get(f"{BASE}/rates/GOLD_TRADE_999", headers=HEADERS, timeout=10)
print(r.status_code, r.json())
```

```json 200 OK theme={null}
{
  "symbol_code": "GOLD_TRADE_999",
  "display_name": "Gold 999",
  "metal": "gold",
  "unit": "10 gram",
  "quantity_unit": "g",
  "buy": "141250.00",
  "sell": "141100.00",
  "updated_at": "2026-10-21T09:31:05.120000+00:00",
  "is_trading": true,
  "frozen": false,
  "stale": false
}
```

A symbol that does not exist or is not active answers `404 unknown_symbol`. An active symbol whose rate is not published yet answers `503 rates_not_ready`: retry shortly.

## Using a rate to place an order

The rate tells you what an order would cost **now**; it does not reserve that price. Prices move every few seconds, and the order is priced again when it is placed.

1. Check that `is_trading` is `true` and `stale` is `false`, and that the side you want (`buy` for a buy, `sell` for a sell) is not `null`.
2. Work out the value: for 25 g of `GOLD_TRADE_999` at a Buy rate of `141250.00` per 10 g, the order is worth 141,250.00 × (25 ÷ 10) = **₹353,125.00**.
3. Send the rate you showed as `expected_price` in `POST /orders`. If the live price has moved beyond Bullionwale's tolerance from it, the order is refused with `409 price_moved` instead of being booked at a price you did not expect (see [Orders](/api-reference/orders/overview#place-an-order)).

The flags are a guide; the order check is the authority. An order can still be refused for a reason that appeared after you read the rate.

## Test and production

Rates are not account data, so both environments return the **same live prices**, priced for your account. A test order is priced from this same board.

## Polling

The board is republished every few seconds. Polling more often than about once a second gains nothing and uses your read budget (300 per minute per key by default; see [Rate limits](/rate-limits)). To follow trading halts and the official close as well, use [Market status](/api-reference/market/overview).

## Errors

| Code | Status | Meaning |
| - | - | - |
| `unknown_symbol` | 404 | `GET /rates/{symbol_code}`: no such active symbol. |
| `rates_not_ready` | 503 | `GET /rates/{symbol_code}`: the symbol's rate is not published yet. Retry shortly. |
| `pricing_unavailable` | 503 | Your account's prices could not be computed 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.