# A Developer's Guide to eToro Instrument Discovery

How to programmatically search, filter, and explore eToro's instrument catalog — asset classes, exchanges, industries, and historical data.

---


Building dashboards, scanners, or trading strategies starts with one question: **which instrument am I actually trading?** eToro exposes a rich **Market Data** surface on the public API so you can resolve symbols to stable IDs, enrich them with exchange and industry metadata, and pull OHLC history for backtests and charting. This guide walks through a practical discovery workflow using `https://public-api.etoro.com/api/v1/` with the headers every integration should send: `x-api-key`, `x-user-key` (when using key-based auth), and a fresh `x-request-id` per call for support correlation.

## Search: from ticker to instrument ID

The fastest way to turn a human-readable symbol into an API-ready `instrumentId` is **`GET /market-data/search`**. The endpoint requires a `fields` parameter listing the columns you want back—at minimum include the identifier, symbol, and display name. For an exact match on eToro’s internal symbol, pass `internalSymbolFull` and verify the result before storing the ID in your database.

<!-- skip-test -->
```bash
curl -s -G "https://public-api.etoro.com/api/v1/market-data/search" \
  --data-urlencode "internalSymbolFull=AAPL" \
  --data-urlencode "fields=instrumentId,internalSymbolFull,displayname,marketId" \
  --data-urlencode "pageSize=5" \
  -H "x-request-id: $(uuidgen)" \
  -H "x-api-key: $ETORO_API_KEY" \
  -H "x-user-key: $ETORO_USER_KEY"
```

If you use OAuth instead of API keys, replace the key headers with `Authorization: Bearer <access_token>`.

For broader exploration—sector screens, partial name matches—use `searchText` and paginate with `pageNumber` / `pageSize`. Always request only the fields you need; smaller payloads keep latency predictable when you run searches in a loop.

## Filtering the catalog: types, exchanges, and industries

Once you have IDs, **`GET /market-data/instruments`** lets you batch-fetch metadata and apply server-side filters. Typical query parameters include comma-separated **`instrumentIds`**, **`exchangeIds`**, **`stocksIndustryIds`**, and **`instrumentTypeIds`**. That combination is ideal when your app offers filters like “US tech stocks” or “crypto only”: first load reference data, then pass the selected filter IDs.

Pull the canonical lists of filter values from the reference endpoints so your UI stays in sync with the backend:

- **`GET /market-data/instrument-types`** — asset classes and instrument categories  
- **`GET /market-data/exchanges`** — optional `exchangeIds` to narrow  
- **`GET /market-data/industries`** — optional `stocksIndustryIds` for sector filters  

<!-- skip-test -->
```javascript
import { randomUUID } from "node:crypto";

const BASE = "https://public-api.etoro.com/api/v1";

function apiHeaders() {
  return {
    "x-request-id": randomUUID(),
    "x-api-key": process.env.ETORO_API_KEY,
    "x-user-key": process.env.ETORO_USER_KEY,
  };
}

export async function fetchInstrumentBatch(ids) {
  const qs = new URLSearchParams({
    instrumentIds: ids.join(","),
  });
  const res = await fetch(`${BASE}/market-data/instruments?${qs}`, {
    headers: apiHeaders(),
  });
  if (!res.ok) throw new Error(`instruments ${res.status}`);
  return res.json();
}
```

Stash `marketId` when you plan to use instrument feeds or social features that key off market identifiers rather than `instrumentId` alone.

## Latest rates and bulk closing prices

For **spot checks** and lightweight pricing widgets, **`GET /market-data/rates`** accepts comma-separated **`instrumentIds`**. Use it to refresh a watchlist strip or validate that a symbol still trades before placing an order.

For **portfolio analytics** and end-of-day reports, **`GET /market-data/instruments/history/closing-price`** returns historical closing prices in bulk—useful when you need a single daily series for many instruments without hammering per-instrument candle endpoints.

## OHLC candles for charts and backtests

For charting and strategy research, **`GET /market-data/instruments/history/candles`** returns candlesticks. Pass **`direction`** (`asc` or `desc`), **`interval`** (use values supported by the API for your asset class), and **`limit`** (maximum 1000) as query parameters. Fetch **descending** when you only need the most recent bars; use **ascending** when you are building a time series from the past forward.

<!-- skip-test -->
```bash
INSTRUMENT_ID=100000
curl -s -G "https://public-api.etoro.com/api/v1/market-data/instruments/history/candles" \
  --data-urlencode "instrumentId=${INSTRUMENT_ID}" \
  --data-urlencode "direction=desc" \
  --data-urlencode "interval=OneDay" \
  --data-urlencode "limit=120" \
  -H "x-request-id: $(uuidgen)" \
  -H "x-api-key: $ETORO_API_KEY" \
  -H "x-user-key: $ETORO_USER_KEY"
```

<!-- skip-test -->
```javascript
export async function fetchRecentDailyCandles(instrumentId, count = 120) {
  const qs = new URLSearchParams({
    instrumentId: String(instrumentId),
    direction: "desc",
    interval: "OneDay",
    limit: String(count),
  });
  const url = `${BASE}/market-data/instruments/history/candles?${qs}`;
  const res = await fetch(url, { headers: apiHeaders() });
  if (!res.ok) throw new Error(`candles ${res.status}`);
  const body = await res.json();
  return body.data?.candles ?? body.candles ?? body;
}
```

Normalize timestamps and timezone assumptions in your app; document which interval you used so backtests stay reproducible.

## Putting it together

A solid discovery pipeline looks like this: **search** to resolve symbols, **market-data/instruments** + reference endpoints to filter and enrich, **rates** for live checks, **closing-price** or **candles** for history. Cache reference data (exchanges, industries, types) for a TTL of hours, paginate search aggressively, and always propagate **`x-request-id`** so operations can trace a bad instrument ID or empty candle response end to end. For full request and response schemas, use the official API Portal as the source of truth alongside these patterns.
