English | 中文
Official Infoway Node.js / TypeScript SDK for REST market data, fundamentals, and WebSocket streams.
| Item | Description |
|---|---|
| Package | infoway-sdk@0.4.0 |
| Runtime | Node.js 18+ |
| REST | https://data.infoway.io |
| Quotes WebSocket | wss://data.infoway.io/ws |
| News WebSocket | wss://data.infoway.io/news |
| Rate limits | REST · WebSocket |
| Error codes | REST · WebSocket |
| Endpoints | Endpoints |
If apiKey is omitted, the SDK reads INFOWAY_API_KEY. REST methods are async.
npm install infoway-sdk@0.4.0import { InfowayClient, KlineType } from "infoway-sdk";
const client = new InfowayClient();
console.log(await client.stock.getTrade("AAPL.US"));
console.log(await client.crypto.getKline("BTCUSDT", KlineType.DAY, 30));
console.log(await client.packages.getInfo());| Market | Format | Valid | Invalid |
|---|---|---|---|
| US | {code}.US |
AAPL.US |
AAPL |
| Hong Kong | 5-digit + .HK |
00700.HK |
700.HK |
| Shanghai | {code}.SH |
600519.SH |
600519.CN |
| Shenzhen | {code}.SZ |
000001.SZ |
000001.CN |
| Japan | {code}.JP |
7203.JP |
|
| Korea | {code}.KS |
005930.KS |
|
| India | {code}.IN |
RELIANCE.IN |
|
| Taiwan | {code}.TW |
2330.TW |
|
| Crypto | Pair | BTCUSDT |
|
| FX | Pair | USDJPY |
basic / financial take a product type such as STOCK_US or CRYPTO, not a market code like US.
| Parameter | Default | Description |
|---|---|---|
apiKey |
INFOWAY_API_KEY |
API key |
baseUrl |
https://data.infoway.io |
REST base URL |
timeout |
15000 |
Per-request timeout (milliseconds) |
maxRetries |
3 |
Retry count |
| Client | Use |
|---|---|
stock / crypto / japan / india / korea / taiwan / common |
Trade, depth, candles |
basic / packages |
Symbols, calendar, plan |
market / plate |
Overview, sectors |
stockInfo / financial |
Fundamentals, statements |
Prefer enums: KlineType, SymbolType, Market, Lang, NewsLang, PeriodType, Business, RankSort, SortOrder, ScheduleType.
Join symbols with commas. Rate limits: REST API Limitation.
| Method | Description |
|---|---|
getTrade(codes) |
Latest trade |
getDepth(codes) |
Order book |
getKline(codes, klineType, count, options?) |
Candles |
Trade fields: s symbol, p price, v volume, vw turnover, t milliseconds, td side. Candles are under respList; t is seconds. Up to 500 bars per symbol; multi-symbol calls return 2 bars each.
await client.stock.getTrade("AAPL.US,TSLA.US");
await client.crypto.getDepth("BTCUSDT");
await client.korea.getTrade("005930.KS");
await client.taiwan.getTrade("2330.TW");
await client.crypto.getKline("BTCUSDT", KlineType.MIN_1, 100);| Enum | Value | Interval |
|---|---|---|
MIN_1 / MIN_5 / MIN_15 / MIN_30 |
1–4 | Minutes |
HOUR_1 / HOUR_2 / HOUR_4 |
5–7 | Hours |
DAY / WEEK / MONTH / QUARTER / YEAR |
8–12 | Daily and above |
Dates use YYYYMMDD. getTradingHours is deprecated; use getTradingSchedule.
import { Market, ScheduleType, SymbolType } from "infoway-sdk";
await client.basic.getSymbols(SymbolType.STOCK_US);
await client.basic.getSymbolInfo(SymbolType.STOCK_US, "AAPL.US");
await client.basic.getStockDetail(SymbolType.STOCK_US, "AAPL.US");
await client.basic.getAdjustmentFactors("AAPL.US", Market.US, "20260801", "20260815");
await client.basic.getTradingDays(Market.US, "20260801", "20260815");
await client.basic.getTradingSchedule();
await client.basic.getTradingScheduleByType(ScheduleType.ENERGY);
await client.basic.getMarkets();
await client.packages.getInfo();import { Lang, Market, PeriodType, RankSort, SortOrder, SymbolType } from "infoway-sdk";
await client.market.getTemperature("HK,US", Lang.ZH_CN);
await client.market.getBreadth(Market.US, Lang.ZH_CN);
await client.market.getTurnover(Market.US);
await client.market.getIndexes(Lang.EN);
await client.market.getLeaders(Market.US, 10);
await client.market.getOverview(Market.US, Lang.ZH_CN);
await client.market.getRankCategories(Market.US);
await client.market.getRank(Market.US, "all", {
sort: RankSort.CHG,
order: SortOrder.DESC,
limit: 30,
});
await client.plate.getIndustry("HK", 200);
await client.plate.getConcept("HK", 100);
await client.plate.getMembers("IN20293.HK");
await client.plate.getIntro("IN20293.HK");
await client.plate.getChart("HK", 50);
await client.stockInfo.getValuation("AAPL.US");
await client.stockInfo.getRatings("AAPL.US");
await client.stockInfo.getCompany("AAPL.US", "zh-CN");
await client.stockInfo.getPanorama("AAPL.US");
await client.stockInfo.getConcepts("AAPL.US");
await client.stockInfo.getEvents("AAPL.US", 20);
await client.stockInfo.getDrivers("AAPL.US");
await client.financial.getEarningStatus("AAPL.US", SymbolType.STOCK_US);
await client.financial.getIncomeStatement("AAPL.US", SymbolType.STOCK_US, PeriodType.FQ);
await client.financial.getRevenue("AAPL.US", SymbolType.STOCK_US);
await client.financial.getCashFlow("AAPL.US", SymbolType.STOCK_US, PeriodType.FY);
await client.financial.getBalanceSheet("AAPL.US", SymbolType.STOCK_US);
await client.financial.getStatistics("AAPL.US", SymbolType.STOCK_US);
await client.financial.getDividend("00700.HK", SymbolType.STOCK_HK);
await client.financial.getDividendPayout("AAPL.US", SymbolType.STOCK_US);
await client.financial.getEarnings("AAPL.US", SymbolType.STOCK_US, PeriodType.FQ);Rank key values come from getRankCategories. Financial methods require symbol and type. periodType: fq quarter, fy year, fh half-year.
Pass { parse: true }.
const trades = await client.crypto.getTrade("BTCUSDT", { parse: true });
trades[0].price;
trades[0].time;
trades[0].turnover;
const candles = await client.crypto.getKline("BTCUSDT", KlineType.MIN_1, 100, { parse: true });
candles[0].close;
candles[0].change_percent;| Raw | Normalized |
|---|---|
| Price / volume as strings | number |
Trade / depth t in ms; candle t in seconds |
Date |
REST pc / WS pfr |
change_percent |
Candle respList |
flattened list |
Book a/b columns |
{ price, volume } |
vw |
turnover |
business must match the symbol market. connect() blocks — keep the promise. 60 frames per minute per connection. See WebSocket Limitation.
import { InfowayWebSocket, KlineType } from "infoway-sdk";
const ws = new InfowayWebSocket({ business: "crypto" });
ws.onTrade = (data) => console.log(data.s, data.p);
ws.onError = (err) => console.error(err);
const running = ws.connect();
ws.subscribeTrade("BTCUSDT,ETHUSDT");
ws.subscribeKline("BTCUSDT", KlineType.MIN_1);
ws.unsubscribeKline("BTCUSDT", KlineType.MIN_1);
ws.close();
await running;Equity trade types: subscribeTrade(codes, true).
| Behavior | Description |
|---|---|
| Heartbeat | 10010 every 30 seconds; server does not reply |
| Reconnect | Replays the current subscription set |
onReconnect |
After a later successful open |
onDisconnect |
Unexpected drop only. close() does not fire it |
| HTTP 401 | Stops reconnecting |
| Dir | Code | Description |
|---|---|---|
| out | 10000 / 10003 / 10006 | Subscribe trade / depth / kline |
| out | 11000 / 11001 / 11002 | Unsubscribe |
| out | 10010 | Heartbeat |
| in | 10002 / 10005 / 10008 | Push |
| in | 11010 | Unsubscribe ack |
| in | 200 | Connected |
An ack means the request was accepted. Merge symbols into one comma-separated string.
wss://data.infoway.io/news requires a separate entitlement. One news connection per key.
import { InfowayNewsWebSocket, NewsLang } from "infoway-sdk";
const news = new InfowayNewsWebSocket({ lang: NewsLang.ZH_HANS });
news.onNews = (item) => console.log(item.title);Subscribe 10020, unsubscribe 11020, push 10022. A later subscribe replaces the language.
REST uses ret. WebSocket uses code. 508–514 mean different things on each side. Full tables: REST API Error Codes and WebSocket Error Codes.
import { InfowayAPIError, InfowayAuthError, InfowayRateLimitError } from "infoway-sdk";
try {
await client.stock.getTrade("INVALID");
} catch (e) {
if (e instanceof InfowayAuthError) console.error(e.msg);
else if (e instanceof InfowayRateLimitError) console.error(e.ret, e.msg);
else if (e instanceof InfowayAPIError) console.error(e.message, e.traceId);
}REST budget is about 1200 calls/minute/key. An invalid key raises InfowayAuthError on REST; WebSocket handshake HTTP 401 does not reconnect.
REST ret |
Description |
|---|---|
| 200 | Success |
| 400 | Bad request |
| 500 | Server error |
| 501 / 502 | Rate limit |
| 503 | Candle count exceeded |
| 505 | Symbol count exceeded |
| 506 / 507 | Invalid / missing parameter |
| 508 | Symbol not found |
| 509 | Permission expired |
| 513 | Timestamp outside plan history |
| 514 | No permission |
WebSocket code |
Description |
|---|---|
| 501 / 502 | Rate limit |
| 505 / 516 | Subscription count exceeded |
| 506 / 507 | Invalid / missing parameter |
| 508–511 | API key expired / invalid / empty / blacklisted |
| 512 | Connection count exceeded |
| 513 | Heartbeat timeout |
| 515 | Not JSON |
| 517–521 | Handshake failed |
0.4.0 — Breaking. Client-side limits are now enforced before the request: over 100 symbols raises ret 505, over 500 bars raises 503, and several symbols with more than 2 bars raises 506 (the server used to truncate to 2 and return 200). An explicitly empty API key is no longer replaced by INFOWAY_API_KEY; keys are trimmed. A ret=500 envelope is reclassified into 501–514. Terminal WebSocket codes stop the client instead of reconnecting. Calling a closed client raises.
0.2.0 — basic.* parameters fixed (breaking):
| Old | New |
|---|---|
getSymbols("US") |
getSymbols(SymbolType.STOCK_US) |
getSymbolInfo("AAPL.US") |
getSymbolInfo("STOCK_US", "AAPL.US") |
getAdjustmentFactors("AAPL.US") |
getAdjustmentFactors("AAPL.US", "US", "20260801", "20260814") |
getTradingDays("US") |
getTradingDays("US", "20260801", "20260814") |
getTradingHours() |
getTradingSchedule() |
WebSocket callbacks now receive data. unsubscribeKline is per interval. An invalid key stops reconnecting.
{market} = stock / crypto / japan / india / korea / taiwan / common. Full list: Endpoints.
| API | Path |
|---|---|
| Latest trade | GET /{market}/batch_trade/{codes} |
| Order book | GET /{market}/batch_depth/{codes} |
| Candles | POST /{market}/v2/batch_kline |
| Symbols / calendar / financials | GET /common/basic/* |
| Overview / sectors / stock info | GET /common/v2/basic/* |
| Package | GET /package/info |
MIT. API key: infoway.io.