Tenants
A tenant is one feed. Your access key names the tenants you may use; the welcome frame on connect tells you what each one carries right now, so treat that frame as authoritative over this table.
| ID | Slug | Name | Market field | Streams | Modes |
|---|---|---|---|---|---|
1 | US_Equity | US Equities | — (omit) | trade quote aggregate | full ltp |
4 | Currencies | Currencies | forex (required) | quote aggregate | full ltp |
crypto (required) | trade quote aggregate | full ltp | |||
5 | Futures | Futures | — (omit) | trade quote aggregate | full ltp |
Every feed delivers each event as its own frame tagged with its kind — a trade, a quote and a one-second OHLC bar for the same symbol are three separate frames, never merged. Forex has no trade stream at source, so it carries the two kinds it can.
Tenant 4 carries two markets under one ID. Because a pair like DOP-USD exists in both — a currency and a token — every subscribe on tenant 4 must say which market it means. Tenants 1 and 5 carry one market and reject a market field.
On tenant 5 a symbol is one contract, not a product: ESZ6 is the E-mini S&P for December 2026 (product code, month code, year digit). Prices are per unit of the underlying; apply the contract multiplier yourself. Recency is set by the plan.
Authentication
One credential. Your access key is issued to you during onboarding; it is what a client presents to the WebSocket and to historical bars, and it carries your tenant grants and per-client limits. The ticker list is public and takes no credential at all.
Access keys are issued during onboarding; there is no public sign-up.
Ticker list
The full instrument universe, across every tenant. No credential is needed; what you may actually subscribe to is decided by your access key on the WebSocket. symbol and market in each row are exactly what a subscribe frame takes.
| Parameter | Meaning |
|---|---|
tenant | slug or ID; omitted lists every tenant |
market | forex or crypto — narrows tenant 4 to one market |
search | prefix match on symbol, substring match on name |
active | true / false; omitted returns both |
limit, offset | paging; limit defaults to 100, max 1000 |
US Equities
curl -s "https://socket-edith.data.wedafeeds.com/api/v1/tickers?tenant=US_Equity&search=apple&limit=5"
market on single-market rows{"error":false,"statusCode":200,"status":"OK","message":"Tickers",
"data":{"tenants":[{"id":"1","slug":"US_Equity"}],"total":3,"limit":5,"offset":0,
"tickers":[
{"id":"…","tenant":"1","symbol":"AAPL","name":"Apple Inc.","assetClass":"equity",
"locale":"us","primaryExchange":"XNAS","type":"CS","currency":"USD","active":true,
"identifiers":{"cik":"0000320193","compositeFigi":"BBG000B9XRY4"}},
…]}}
Currencies — forex
curl -s "https://socket-edith.data.wedafeeds.com/api/v1/tickers?tenant=Currencies&market=forex&limit=3"
{"error":false,"statusCode":200,"status":"OK","message":"Tickers",
"data":{"tenants":[{"id":"4","slug":"Currencies"}],"total":1204,"limit":3,"offset":0,
"tickers":[
{"tenant":"4","symbol":"AED-AUD","name":"United Arab Emirates dirham - Australian dollar","assetClass":"forex","market":"forex","locale":"global","currency":"AUD","active":true},
{"tenant":"4","symbol":"AED-BHD","name":"United Arab Emirates dirham - Bahraini dinar","assetClass":"forex","market":"forex","locale":"global","currency":"BHD","active":true},
{"tenant":"4","symbol":"AED-CAD","name":"United Arab Emirates dirham - Canadian dollar","assetClass":"forex","market":"forex","locale":"global","currency":"CAD","active":true}]}}
Currencies — crypto
curl -s "https://socket-edith.data.wedafeeds.com/api/v1/tickers?tenant=Currencies&market=crypto&search=btc"
{"error":false,"statusCode":200,"status":"OK","message":"Tickers",
"data":{"tenants":[{"id":"4","slug":"Currencies"}],"total":7,"limit":100,"offset":0,
"tickers":[
{"tenant":"4","symbol":"BTC-AUD","name":"Bitcoin - Australian Dollar","assetClass":"crypto","market":"crypto","locale":"global","currency":"AUD","active":true},
{"tenant":"4","symbol":"BTC-EUR","name":"Bitcoin - Euro","assetClass":"crypto","market":"crypto","locale":"global","currency":"EUR","active":true},
{"tenant":"4","symbol":"BTC-USD","name":"Bitcoin - United States dollar","assetClass":"crypto","market":"crypto","locale":"global","currency":"USD","active":true},
…]}}
An unknown tenant or a misspelled market is 400.
Historical bars
OHLC bars for one symbol over a date window, paged by number. Three routes, one contract. Send your access key exactly as you do to the socket — X-API-Key header, Authorization: Bearer, or ?apiKey=. Each route needs the grant for the tenant that streams the same instruments.
| Route | symbol | Key must be granted |
|---|---|---|
GET /api/v1/equity/historical | ticker — AAPL, BRK.B | tenant 1 (US Equities) |
GET /api/v1/crypto/historical | pair — BTC-USD or BTC/USD | tenant 4 (Currencies) |
GET /api/v1/forex/historical | pair — EUR-USD or EUR/USD | tenant 4 (Currencies) |
GET /api/v1/futures/historical | contract — ESZ6, CLZ6 | tenant 5 (Futures) |
The asset class is in the path, not a parameter, because the symbol alone cannot say which history you mean: DOP-USD is both a currency and a token, and both have bars. Pairs are spelled exactly as the ticker list and a subscribe frame spell them.
| Parameter | Meaning |
|---|---|
symbol | required; case-insensitive; a ticker on the equity route, a BASE-QUOTE pair on the others |
from, to | required; inclusive window, YYYY-MM-DD or a millisecond timestamp |
timespan | second minute hour day week month quarter year; default day |
multiplier | a bar is multiplier × timespan wide — 5 + minute is a five-minute bar; default 1 |
limit | source records per page (see note); default 5000, max 50000 |
page | 1-based; default 1, max 100 |
US Equities — daily bars, five per page
curl -s -H "X-API-Key: YOUR_ACCESS_KEY" \ "https://socket-edith.data.wedafeeds.com/api/v1/equity/historical?symbol=AAPL&from=2024-01-01&to=2024-01-31×pan=day&limit=5&page=1"
nextPage says there is more{"error":false,"statusCode":200,"status":"OK","message":"Historical bars",
"data":{"assetClass":"equity","symbol":"AAPL","timespan":"day","multiplier":1,"from":"2024-01-01","to":"2024-01-31",
"adjusted":true,"page":1,"limit":5,"count":5,"nextPage":true,
"bars":[
{"timestamp":1704171600000,"open":187.15,"high":188.44,"low":183.885,"close":185.64,"volume":82488674,"vwap":185.9374,"trades":1008875},
{"timestamp":1704258000000,"open":184.22,"high":185.88,"low":183.43,"close":184.25,"volume":58414460,"vwap":184.3226,"trades":656853},
…]}}
// page=5 — January 2024 had 21 trading days {"error":false,"statusCode":200,"status":"OK","message":"Historical bars", "data":{"assetClass":"equity","symbol":"AAPL","timespan":"day","multiplier":1,"from":"2024-01-01","to":"2024-01-31", "adjusted":true,"page":5,"limit":5,"count":1,"nextPage":false, "bars":[{"timestamp":1706677200000,"open":187.04,"high":187.095,"low":184.35,"close":184.4,"volume":55467803,"vwap":185.3525,"trades":679844}]}} // page=9 — past the end is empty, not an error {"error":false,"statusCode":200,"status":"OK","message":"Historical bars", "data":{"assetClass":"equity","symbol":"AAPL","timespan":"day","multiplier":1,"from":"2024-01-01","to":"2024-01-31", "adjusted":true,"page":9,"limit":5,"count":0,"nextPage":false,"bars":[]}}
Crypto — hourly bars
curl -s -H "X-API-Key: YOUR_ACCESS_KEY" \ "https://socket-edith.data.wedafeeds.com/api/v1/crypto/historical?symbol=BTC-USD&from=2024-01-01&to=2024-01-02×pan=hour"
{"error":false,"statusCode":200,"status":"OK","message":"Historical bars",
"data":{"assetClass":"crypto","symbol":"BTC-USD","timespan":"hour","multiplier":1,"from":"2024-01-01","to":"2024-01-02",
"adjusted":true,"page":1,"limit":5000,"count":48,"nextPage":false,
"bars":[
{"timestamp":1704067200000,"open":42241.1,"high":42591,"low":42241.1,"close":42452.66,"volume":499.65044691,"vwap":42416.5499,"trades":9099},
…]}}
Forex — daily bars
curl -s -H "X-API-Key: YOUR_ACCESS_KEY" \ "https://socket-edith.data.wedafeeds.com/api/v1/forex/historical?symbol=EUR-USD&from=2024-01-01&to=2024-01-10&limit=3"
volume and trades count quotes{"error":false,"statusCode":200,"status":"OK","message":"Historical bars",
"data":{"assetClass":"forex","symbol":"EUR-USD","timespan":"day","multiplier":1,"from":"2024-01-01","to":"2024-01-10",
"adjusted":true,"page":1,"limit":3,"count":3,"nextPage":true,
"bars":[
{"timestamp":1704067200000,"open":1.1038,"high":1.1077,"low":1.091,"close":1.1037,"volume":8793,"vwap":1.1042,"trades":8793},
…]}}
Futures — session bars
curl -s -H "X-API-Key: YOUR_ACCESS_KEY" \ "https://socket-edith.data.wedafeeds.com/api/v1/futures/historical?symbol=ESZ6&from=2026-09-01&to=2026-09-17&limit=3"
{"error":false,"statusCode":200,"status":"OK","message":"Historical bars",
"data":{"assetClass":"futures","symbol":"ESZ6","timespan":"day","multiplier":1,"from":"2026-09-01","to":"2026-09-17",
"adjusted":false,"page":1,"limit":3,"count":3,"nextPage":true,
"bars":[
{"timestamp":1788220800000,"open":7713.5,"high":7757,"low":7685.5,"close":7736,"volume":3305,"vwap":7730.4372,"trades":2447,
"settlementPrice":7743.5,"sessionDate":"2026-09-02"},
…]}}
On futures, day is one trading session, which opens the evening before it settles — so timestamp falls on the calendar day before sessionDate. Intraday bars carry sessionDate but no settlement. Here limit counts bars. Minute bars go up to 59; ask for hour beyond that, or the answer is 400.
// a key granted only tenant 1 asking the crypto route
{"error":true,"statusCode":403,"status":"Forbidden","message":"Access key is not granted Currencies"}
timestamp is the bar's open in Unix milliseconds. Equity prices are split-adjusted. A bar built from over-the-counter prints carries "otc":true; every other bar omits the field. assetClass and symbol echo the route and the symbol as this API spells it.
Paging is a number and a flag. nextPage says whether a further page exists; ask for page+1. There is no cursor and no URL to follow. Page n costs more to serve than page 1, which is why page stops at 100 — raise limit to reach further.
limit counts source records, not bars. A daily bar is its own record, so limit=5 on day is five bars. Hourly bars are built from minutes, weekly and longer from days, N-second bars from seconds — limit=100 on hour is a page built from 100 minutes, roughly a bar and a half. count reports what a page actually holds; the 5000 default is enough for most windows.
A missing from, a timespan of fortnight, limit=ten or page=0 is 400 naming the parameter. No key, or an unknown or revoked one, is 401; a valid key without the route's grant is 403 naming the tenant. If the data source cannot be reached the answer is 502; retry later.
WebSocket
Connect
Present the access key as a header where you can; browsers cannot set headers on the handshake, so the query string is accepted too.
wss://socket-echo.data.wedafeeds.com/ws?apiKey=YOUR_ACCESS_KEY
# or, for non-browser clients:
X-API-Key: YOUR_ACCESS_KEY
Authorization: Bearer YOUR_ACCESS_KEY
The first frame describes what your key may use. available:false means granted but currently down — distinct from not granted. A tenant with a markets array requires market on every subscribe.
{"type":"welcome","message":"connected","ts":1789390028000,
"tenants":[
{"id":"1","name":"US Equities","assetClass":"equity",
"streams":["trade","quote","aggregate"],"modes":["full","ltp"],"available":true},
{"id":"4","name":"Currencies","assetClass":"currency",
"streams":["quote","aggregate","trade"],"modes":["full","ltp"],
"markets":[
{"market":"forex", "assetClass":"forex", "streams":["quote","aggregate"], "modes":["full","ltp"]},
{"market":"crypto","assetClass":"crypto","streams":["trade","quote","aggregate"],"modes":["full","ltp"]}],
"available":true}]}
US Equities — tenant 1
One market, so there is no market field. Omitting mode means full.
{"action":"subscribe","tenant":"1","tickers":["AAPL","MSFT"]}
{"type":"ack","tenant":"1","tickers":["AAPL","MSFT"],"mode":"full","message":"subscribed","ts":1789390028000}
{"type":"data","tenant":"1","symbol":"AAPL","kind":"trade",
"data":{"kind":"trade","symbol":"AAPL","price":"224.28","size":"100","eventTime":1788948548063,"tradeId":"52983525029262"}}
{"type":"data","tenant":"1","symbol":"AAPL","kind":"quote",
"data":{"kind":"quote","symbol":"AAPL","bidPrice":"224.27","bidSize":"3","askPrice":"224.29","askSize":"5","eventTime":1788948548071}}
{"type":"data","tenant":"1","symbol":"AAPL","kind":"aggregate",
"data":{"kind":"aggregate","symbol":"AAPL","open":"224.26","high":"224.31","low":"224.25","close":"224.28","volume":"1840","eventTime":1788948548000}}
{"action":"subscribe","tenant":"1","tickers":["AAPL"],"mode":"ltp"}
{"type":"ack","tenant":"1","tickers":["AAPL"],"mode":"ltp","message":"subscribed","ts":1789390028000}
{"type":"data","tenant":"1","symbol":"AAPL","kind":"ltp",
"data":{"kind":"ltp","symbol":"AAPL","ltp":"224.28","eventTime":1788948548000}}
On US Equities the last price is the one-second bar's close, not the individual print — many prints (odd lots, extended-hours, average-price) are not eligible to set the consolidated last, and the bar already applies those rules. In full mode you still receive every trade.
Currencies — tenant 4
market is required. A slash in a pair is accepted and folded to a hyphen, so USD/JPY and USD-JPY are the same subscription — the ack shows the canonical form.
{"action":"subscribe","tenant":"4","market":"forex","tickers":["EUR-USD","USD/JPY"]}
{"type":"ack","tenant":"4","market":"forex","tickers":["EUR-USD","USD-JPY"],"mode":"full","message":"subscribed","ts":1789390028000}
{"type":"data","tenant":"4","market":"forex","symbol":"EUR-USD","kind":"quote",
"data":{"kind":"quote","symbol":"EUR-USD","bidPrice":"1.15324","askPrice":"1.15329","eventTime":1789389703000}}
{"type":"data","tenant":"4","market":"forex","symbol":"EUR-USD","kind":"aggregate",
"data":{"kind":"aggregate","symbol":"EUR-USD","open":"1.1529","high":"1.1529","low":"1.1529","close":"1.1529","volume":"1","eventTime":1789393857000}}
{"action":"subscribe","tenant":"4","market":"forex","tickers":["EUR-USD"],"mode":"ltp"}
{"type":"ack","tenant":"4","market":"forex","tickers":["EUR-USD"],"mode":"ltp","message":"subscribed","ts":1789390028000}
{"type":"data","tenant":"4","market":"forex","symbol":"EUR-USD","kind":"ltp",
"data":{"kind":"ltp","symbol":"EUR-USD","ltp":"1.1529","eventTime":1789393857000}}
{"action":"subscribe","tenant":"4","market":"crypto","tickers":["BTC-USD","ETH-USD"]}
{"type":"ack","tenant":"4","market":"crypto","tickers":["BTC-USD","ETH-USD"],"mode":"full","message":"subscribed","ts":1789390028000}
{"type":"data","tenant":"4","market":"crypto","symbol":"BTC-USD","kind":"trade",
"data":{"kind":"trade","symbol":"BTC-USD","price":"77791.5","size":"0.00101162","eventTime":1789390028834,"tradeId":"1092498786"}}
{"type":"data","tenant":"4","market":"crypto","symbol":"BTC-USD","kind":"quote",
"data":{"kind":"quote","symbol":"BTC-USD","bidPrice":"77739","bidSize":"0.06431702","askPrice":"77754","askSize":"0.064306","eventTime":1789389693541}}
{"type":"data","tenant":"4","market":"crypto","symbol":"BTC-USD","kind":"aggregate",
"data":{"kind":"aggregate","symbol":"BTC-USD","open":"78337.8","high":"78342.67","low":"78337.8","close":"78342.45","volume":"0.0050004","eventTime":1789393851000}}
{"action":"subscribe","tenant":"4","market":"crypto","tickers":["SOL-USD"],"mode":"ltp"}
{"type":"ack","tenant":"4","market":"crypto","tickers":["SOL-USD"],"mode":"ltp","message":"subscribed","ts":1789390028000}
{"type":"data","tenant":"4","market":"crypto","symbol":"SOL-USD","kind":"ltp",
"data":{"kind":"ltp","symbol":"SOL-USD","ltp":"142.31","eventTime":1789390029102}}
Mode is per subscribe, not per connection: one socket can hold BTC-USD in full and SOL-USD in ltp. Re-subscribing a symbol with a different mode switches it in place.
Futures — tenant 5
One market, so no market field. A symbol is one contract: ESZ6 is the E-mini S&P 500 for December 2026 — product code, month code (F G H J K M N Q U V X Z), year digit. Subscribe to the expiry you want; there is no continuous or product-level symbol.
{"action":"subscribe","tenant":"5","tickers":["ESZ6","CLZ6"]}
{"type":"ack","tenant":"5","tickers":["ESZ6","CLZ6"],"mode":"full","message":"subscribed","ts":1789731745145}
{"type":"data","tenant":"5","symbol":"ESZ6","kind":"trade",
"data":{"kind":"trade","symbol":"ESZ6","price":"7715.25","size":"1","eventTime":1789731745600}}
{"type":"data","tenant":"5","symbol":"ESZ6","kind":"quote",
"data":{"kind":"quote","symbol":"ESZ6","bidPrice":"7715.25","bidSize":"7","askPrice":"7715.5","askSize":"22","eventTime":1789731745600}}
{"type":"data","tenant":"5","symbol":"ESZ6","kind":"aggregate",
"data":{"kind":"aggregate","symbol":"ESZ6","open":"7715.25","high":"7715.25","low":"7715.25","close":"7715.25","volume":"1","eventTime":1789731741000}}
Prices are per unit of the underlying; multiply by the product's contract multiplier for notional. size and volume count contracts. On this tenant ltp comes from the trade itself, as on crypto — a futures print is a real last price. Recency (10-minute delayed or real-time) is set by the plan.
The ticker list carries every listed contract under tenant=Futures: search by product with ?tenant=Futures&search=ES, and read the expiry, tick sizes and the product's settlement terms from each row's metadata.
Unsubscribe, list, ping
{"action":"unsubscribe","tenant":"1","tickers":["MSFT"]}
{"action":"unsubscribe","tenant":"1"}
{"action":"unsubscribe","tenant":"4","market":"crypto","tickers":["ETH-USD"]}
{"action":"unsubscribe","tenant":"4","market":"crypto"}
{"type":"ack","tenant":"4","market":"crypto","tickers":["BTC-USD","ETH-USD"],"message":"unsubscribed","ts":1789390038058}
{"action":"list"}
tenant:symbol, or tenant:market:symbol on tenant 4{"type":"status","message":"active subscriptions",
"tickers":["1:AAPL","4:forex:EUR-USD","4:forex:USD-JPY","4:crypto:BTC-USD"],
"tenants":[…same shape as welcome…],"ts":1789390038058}
{"action":"ping"}
{"type":"pong","ts":1789390038058}
The server also sends protocol-level pings every ~54 s and expects a pong within 60 s; most WebSocket libraries answer these automatically.
Data frames
Every feed emits the same envelope. Prices and sizes are strings so decimal precision survives; eventTime is epoch milliseconds from the source. Fields absent from an event are omitted, not sent as null.
| Envelope field | Meaning |
|---|---|
type | always data for market data |
tenant | tenant ID |
market | present only on multi-market tenants (tenant 4) |
symbol | the symbol as you subscribed it |
kind | trade · quote · aggregate · ltp |
data | the event; its own kind and symbol are repeated inside for convenience |
| kind | Fields in data | Notes |
|---|---|---|
trade | price size eventTime tradeId buyerIsMaker? | one frame per execution |
quote | bidPrice bidSize? askPrice askSize? eventTime | forex quotes carry no sizes; much higher volume than trades |
aggregate | open high low close volume eventTime | one-second bar; eventTime is the window start |
ltp | ltp eventTime | only in mode:"ltp"; from the trade on crypto, from the bar's close on equities and forex |
Errors
Errors are frames, not disconnects. Each names the tenant it concerns and says what to send instead.
// tenant not on your key {"type":"error","tenant":"99","message":"access denied for tenant","ts":…} // tenant granted but not running {"type":"error","tenant":"4","message":"tenant is not available","ts":…} // market omitted on tenant 4 {"type":"error","tenant":"4","message":"market is required for this tenant (forex, crypto)","ts":…} // market sent to a single-market tenant {"type":"error","tenant":"1","message":"tenant carries a single market; remove \"crypto\"","ts":…} // typo in market or mode — never silently defaulted {"type":"error","tenant":"4","message":"unknown market: fx (want \"forex\" or \"crypto\")","ts":…} {"type":"error","tenant":"4","message":"unknown mode: LAST (want \"full\" or \"ltp\")","ts":…} // over your per-connection symbol cap {"type":"error","tenant":"4","message":"ticker limit exceeded: 98 of 100 in use","ts":…}
At the handshake, an invalid key is 401, a key with no grants 403, and a key already at its connection cap 429 — all as JSON, before the upgrade, so your client reads a real message rather than a socket that opens and closes.
Rules & limits
- Symbols
- Upper-cased and de-duplicated on receipt. Currency pairs are
BASE-QUOTE; a slash is folded to a hyphen. market- Required on tenant 4, refused on tenant 1. The value comes straight from the ticker list's
marketcolumn. mode- Per subscribe. Omitted means
full.ltpis offered only where the welcome frame lists it. - Idempotence
- Subscribing a symbol you already hold does not count against your cap; it re-acks (and may switch the mode).
- Symbol cap
- Concurrent symbols per connection, across all tenants — your key's
maxTickers. - Connection cap
- Concurrent sockets per key — your key's
maxConnections. Refused at the handshake with 429; existing sockets are never dropped to make room. - Slow consumers
- Each socket has a bounded outbound queue. A client that stops reading is disconnected rather than allowed to stall others.
- Reconnects
- Subscriptions do not survive a disconnect; re-send them after reconnecting. Read the fresh
welcomefirst. - Inbound surface
- Clients can only manage their own subscriptions. There is no publish action.