# Instruments and symbols

URL: https://docs.fxapis.com/instruments

> Name a market once — XAUUSD, US30, BTCUSD — and trade each account's own broker symbol for it. List any connected broker's symbols, contract specifications…



The same market has a different name at almost every broker. Gold is `XAUUSD` at one, `XAUUSD.a` at another, `XAUUSDm` or `GOLD` at a third. The Dow is `US30`, `DJ30`, `WS30` or `US30.cash`. If your members trade at different brokers, or on different account types at one broker, a signal cannot name the broker's symbol.

So fxapis separates the two:

* An **instrument** is a market named once, from a fixed list: `XAUUSD`, `EURUSD`, `US30`, `BTCUSD`, and so on.
* A **symbol** is what one broker calls it, exactly as an order must send it.

Name an instrument in a signal and in each order, and fxapis trades every account's own symbol for it.

## The instruments [#the-instruments]

```bash
curl -sS "https://api.fxapis.com/v1/instruments" -H "Authorization: Bearer $FXAPIS_KEY"
```

```json
{
  "data": [
    { "instrument": "EURUSD", "name": "Euro vs US Dollar", "category": "forex" },
    { "instrument": "XAUUSD", "name": "Gold vs US Dollar", "category": "metals" },
    { "instrument": "US30", "name": "Dow Jones Industrial Average", "category": "indices" },
    { "instrument": "USOIL", "name": "WTI Crude Oil", "category": "energies" },
    { "instrument": "BTCUSD", "name": "Bitcoin vs US Dollar", "category": "crypto" }
  ]
}
```

The list covers the forex majors, crosses and common exotics, metals, the main stock indices, oil and gas, and the main cryptocurrencies. Filter with `?category=forex|metals|indices|energies|crypto`. It needs no account and no broker, so it is the list to build a signal editor from.

## Trading an instrument [#trading-an-instrument]

Send `instrument` instead of `symbol`. Everything else is unchanged:

```bash
curl -sS -X POST "https://api.fxapis.com/v1/accounts/$ACCOUNT_ID/orders/market" \
  -H "Authorization: Bearer $FXAPIS_KEY" \
  -H "Idempotency-Key: signal_9931:member_4821" \
  -H "Content-Type: application/json" \
  -d '{ "instrument": "XAUUSD", "side": "buy", "volume": "0.05", "stopLoss": "2338.50", "takeProfit": "2371.00" }'
```

The order records both names: `symbol` is what was traded at this account's broker, and `instrument` is what you asked for.

```json
{ "data": { "id": "…", "symbol": "XAUUSD.a", "instrument": "XAUUSD", "state": "filled", "filledPrice": "2351.20" } }
```

The translation never reaches the broker and adds no time to the order. It is decided from a list fxapis already holds, and it is refused, before anything is sent, when it cannot be made safely:

| Code                     | Status | Meaning                                                                                                                                         |
| ------------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `INSTRUMENT_NOT_OFFERED` | 422    | This account's broker does not offer the instrument, or this account cannot trade it.                                                           |
| `INSTRUMENT_AMBIGUOUS`   | 422    | The broker has more than one plausible symbol (for example a cash index and a future). `details` lists them; send the one you mean as `symbol`. |
| `UNKNOWN_INSTRUMENT`     | 400    | Not an instrument on the list. Send a broker `symbol` instead.                                                                                  |
| `SYMBOLS_NOT_SYNCED`     | 409    | The account has never been online, so its broker's symbols are not known yet. Bring it online once.                                             |

`symbol` still works exactly as before; send one or the other, not both. Pending orders take `instrument` the same way.

## How a symbol is chosen [#how-a-symbol-is-chosen]

When an account comes online, fxapis reads every symbol its broker offers it, with each symbol's contract specification, and maps the instruments onto them:

* **The instrument's own name wins.** A broker that has `XAUUSD` is traded as `XAUUSD`, even if it also has `XAUUSD.r`.
* **Otherwise, a name brokers use for it**, with the broker's suffix removed: `XAUUSD.a`, `XAUUSDm`, `GOLD`, `US30.cash`, `DJ30`.
* **The contract has to agree.** Where a market has one standard contract (100 ounces of gold per lot, 100,000 units of a currency pair), a symbol with a different contract size is never chosen, however good its name. Gold quoted per gram is never taken for gold per ounce.
* **Two plausible symbols are not guessed between.** The instrument is marked `ambiguous` with both candidates, and an order naming it is refused until you name one.
* **A symbol the account cannot trade** (disabled, or close-only) is never chosen.

See the result for any account:

```bash
curl -sS "https://api.fxapis.com/v1/accounts/$ACCOUNT_ID/instruments" -H "Authorization: Bearer $FXAPIS_KEY"
```

```json
{
  "data": [
    { "instrument": "XAUUSD", "status": "mapped", "symbol": "XAUUSD.a", "reason": "its name once the broker's suffix is removed, contract size agrees", "candidates": [] },
    { "instrument": "US30", "status": "ambiguous", "symbol": null, "candidates": [
      { "symbol": "US30.cash", "confidence": 0.95, "reason": "its name once the broker's suffix is removed" },
      { "symbol": "US30.fut", "confidence": 0.95, "reason": "its name once the broker's suffix is removed" }
    ] },
    { "instrument": "BTCUSD", "status": "missing", "symbol": null, "candidates": [] }
  ],
  "meta": { "syncedAt": "2026-10-03T00:42:48Z", "server": "VantageInternational-Live 11", "symbolCount": 812 }
}
```

This is worth calling when a member connects: tell them straight away which of your instruments their account can follow.

## A broker's symbols [#a-brokers-symbols]

```bash
curl -sS "https://api.fxapis.com/v1/accounts/$ACCOUNT_ID/symbols?search=gold" -H "Authorization: Bearer $FXAPIS_KEY"
```

```json
{
  "data": [
    {
      "name": "XAUUSD.a",
      "description": "Gold vs US Dollar",
      "path": "Metals\\XAUUSD.a",
      "digits": 2,
      "contractSize": 100,
      "volumeMin": 0.01,
      "volumeMax": 50,
      "volumeStep": 0.01,
      "tradable": true,
      "currencyBase": "XAU",
      "currencyProfit": "USD",
      "currencyMargin": "USD"
    }
  ],
  "meta": { "syncedAt": "2026-10-03T00:42:48Z", "server": "VantageInternational-Live 11", "symbolCount": 812 },
  "page": { "hasMore": false, "nextCursor": null }
}
```

Every symbol the broker offers this account, as read when the account was last online, so it answers while the account is offline. Query parameters:

| Parameter         |                                                                              |
| ----------------- | ---------------------------------------------------------------------------- |
| `search`          | Only symbols whose name or description contains this.                        |
| `tradable`        | `true` for symbols this account can open positions in; `false` for the rest. |
| `limit`, `cursor` | Up to 1,000 a page; pass `nextCursor` as `cursor` for the next.              |

`volumeMin`, `volumeStep` and `volumeMax` are what a member's lot size must respect at that broker. `contractSize` is what one lot is.

## Market hours [#market-hours]

Each broker sets its own hours for each symbol: when forex opens on Sunday evening, when gold takes its daily break, whether crypto trades at the weekend. fxapis reads them from the member's broker — MetaTrader's `SymbolInfoSessionTrade`, for every symbol — so a signal screen can show the member's real hours instead of a guess.

```bash
curl -sS "https://api.fxapis.com/v1/accounts/$ACCOUNT_ID/sessions?instrument=XAUUSD" -H "Authorization: Bearer $FXAPIS_KEY"
```

```json
{
  "data": {
    "symbol": "XAUUSD",
    "instrument": "XAUUSD",
    "server": "VantageMarkets-Demo",
    "utcOffsetSeconds": 10800,
    "sessionsSyncedAt": "2026-10-03T02:41:10Z",
    "openNow": false,
    "nextOpen": "2026-10-04T22:01:00Z",
    "nextClose": null,
    "trade": {
      "server": [
        { "day": "monday", "open": "01:01", "close": "23:58" },
        { "day": "tuesday", "open": "01:01", "close": "23:58" }
      ],
      "utc": [
        { "day": "sunday", "open": "22:01", "close": "24:00" },
        { "day": "monday", "open": "00:00", "close": "20:58" }
      ]
    },
    "quote": { "server": [], "utc": [] }
  }
}
```

* Name an `instrument` (this account's symbol for it is used) or the broker's `symbol`.
* `trade` is when orders can be placed; `quote` is when prices are quoted. Each is given in the broker's **server time** — as its platform shows them — and in **UTC**.
* `utcOffsetSeconds` is the broker's clock minus UTC, measured from the terminal when the hours were read; many brokers change it with daylight saving, and the daily refresh follows.
* `openNow`, `nextOpen` and `nextClose` are worked out at the moment you ask. A market open all week (most crypto) has neither a next open nor a next close.
* `close: "24:00"` is the end of the day. A market open across midnight shows as two windows.

`GET /v1/accounts/{id}/symbols` also carries each symbol's `sessions`, in server time, with `meta.utcOffsetSeconds`.

The hours are the broker's *configured* schedule. A holiday the broker does not load into it is not here, and on such a day an order is refused with `ORDER_REJECTED` (`Market closed`) — nothing is opened. They are read a minute or so after the account first comes online, then daily; until then the endpoint answers **409** `SESSIONS_NOT_SYNCED`.

## When the list is read [#when-the-list-is-read]

* When an account comes online, if fxapis has no list for it, the list is from another server name, or it is a day old.
* When you ask: `POST /v1/accounts/{id}/symbols/sync` reads it again now. The account has to be online (`ready`). Most integrations never need this.

An account that has never been online has no list yet. `GET /symbols` and `GET /instruments` answer **409** `SYMBOLS_NOT_SYNCED`, and so does an order naming an instrument. Bringing the account online once while the member is still on the connect screen — which the [signals guide](/signals#check-the-credentials-straight-away) already does to check the password — takes care of it.

## Related [#related]

* [Signals and click-to-trade](/signals): naming instruments in signals.
* [Trading](/trading): orders, outcomes and history.
* [Errors](/errors): every code.
