Skip to main content

Infoway SDK

PyPI version Python License: MIT

English | 中文

Official Python SDK for Infoway real-time financial data API. Full documentation at docs.infoway.io.

Installation

pip install infoway-sdk

Quick Start

from infoway import InfowayClient, KlineType

client = InfowayClient(api_key="YOUR_API_KEY")

# Real-time trades
trades = client.stock.get_trade("AAPL.US")

# Daily K-lines for crypto
klines = client.crypto.get_kline("BTCUSDT", kline_type=KlineType.DAY, count=30)

# Instrument list for a market
symbols = client.basic.get_symbols("STOCK_US")

# Market temperature
temp = client.market.get_temperature(market="HK,US")

# Sector/plate rankings
plates = client.plate.get_industry("HK", limit=10)

Symbol codes

Market Format Example
US equities TICKER.US AAPL.US
Hong Kong NNNNN.HKzero-padded to 5 digits 00700.HK (not 700.HK)
China A-shares NNNNNN.SH / NNNNNN.SZ 600519.SH, 000001.SZ
Japan / India / Korea CODE.JP / .IN / .KS 7203.JP, RELIANCE.IN
Crypto pair BTCUSDT
Forex / metals pair USDJPY, XAUUSD

A missing or wrong suffix is answered with [500] All product not exists.

Response fields

The API returns short field names and string-encoded numbers. These are the real names:

Endpoint Shape
get_trade [{"s","t","p","v","vw","td"}]t is epoch milliseconds, vw is turnover (not a VWAP)
get_depth [{"s","t","a","b"}]a/b are column-major [[price...],[qty...]], not asks/bids
get_kline [{"s","respList":[{"t","o","h","l","c","v","vw","pc","pca"}]}] — candles are nested under respList, and t is a string in seconds

Optional normalisation (parse=True)

Off by default, so raw payloads keep flowing to existing code. Turn it on per call or client-wide to get Decimals, timezone-aware datetimes, flattened K-lines and (price, qty) depth pairs:

client = InfowayClient(api_key="YOUR_API_KEY", parse=True)

candles = client.crypto.get_kline("BTCUSDT", kline_type=KlineType.MIN_1, count=100)
candles[0]["c"]               # Decimal("63039.00000")
candles[0]["t"]               # datetime(2026, 8, 15, 6, 27, tzinfo=timezone.utc)
candles[0]["turnover"]        # Decimal — renamed from "vw"
candles[0]["change_percent"]  # Decimal("-0.0001") — from "pc" (REST) / "pfr" (WS)

book = client.crypto.get_depth("BTCUSDT")
book[0]["a"][0]               # (Decimal("63039.00"), Decimal("45.06"))

# per-call override
raw = client.crypto.get_trade("BTCUSDT", parse=False)

WebSocket Streaming

import asyncio
from infoway.ws import InfowayWebSocket

async def main():
    ws = InfowayWebSocket(api_key="YOUR_API_KEY", business="crypto")

    async def on_trade(data):
        # `data` is the unwrapped payload: {"s","t","p","v","vw","td"}
        print(data["s"], data["p"])

    ws.on_trade = on_trade
    # merge every symbol into ONE subscribe frame
    await ws.subscribe_trade("BTCUSDT,ETHUSDT")   # a list works too
    await ws.connect()

asyncio.run(main())

Choose the channel that matches your instruments

business Instruments
stock US / HK / CN equities
japan .JP
india .IN
korea .KS (KOSPI + KOSDAQ)
crypto BTCUSDT, ... (24x7)
common forex / metals / futures, e.g. XAUUSD

The server acknowledges a subscription with 10001 ok even when the channel is wrong or the code does not exist — and then never pushes anything. If you get an ack but no data, check the business first.

WebSocket behaviour

  • Callbacks receive msg["data"], matching what the REST methods return. The K-line callback keeps ty (the interval).
  • Auto-reconnect with exponential backoff (1s to 30s cap), except on HTTP 401 — a rejected API key raises InfowayAuthError and stops, instead of hammering the gateway.
  • Auto-resubscribe on reconnect.
  • Heartbeat every 30s. The server sends no reply to heartbeats; never treat a missing heartbeat ack as a dead connection.
  • Rate limit: 60 frames per minute per connection, heartbeats included. Always merge codes into a single subscribe frame rather than one frame per symbol.
  • Non-JSON frames (the plaintext You have permission to subscribe to all market data greeting on business=stock) and the {"code":200,"msg":"ws connect success"} welcome frame are handled internally.
  • unsubscribe_kline(codes, kline_type) sends klineTypes so only that interval is dropped — without it the server would clear every interval for those instruments.
await ws.subscribe_kline("BTCUSDT", KlineType.DAY)
await ws.unsubscribe_kline("BTCUSDT", KlineType.DAY)   # other intervals stay subscribed

Real-time news

News is a separate connection on its own path (wss://data.infoway.io/news) and needs a separate entitlement on your API key.

import asyncio
from infoway import InfowayNewsWebSocket, InfowayAuthError

async def main():
    news = InfowayNewsWebSocket(api_key="YOUR_API_KEY")

    async def on_news(item):
        # dk, country, lang, route, title, published (Unix SECONDS),
        # urgency (lower = more urgent), provider, symbols[], link, content, sd
        print(item["title"], item["symbols"])

    news.on_news = on_news
    await news.subscribe("en")   # en, zh-Hans, zh-Hant, ja, ko, de, fr, es, pt, ru, tr
    try:
        await news.connect()
    except InfowayAuthError as e:
        print("news channel unavailable:", e)

asyncio.run(main())

Notes: subscribing again replaces the previous language (there is no per-item unsubscribe), and one connection per API key is allowed. Without the news entitlement the handshake is rejected with HTTP 401 and InfowayAuthError is raised immediately rather than reconnecting forever.

REST API Modules

Module Accessor Description
Stock client.stock HK, US, CN equities -- trade, depth, K-line
Crypto client.crypto Cryptocurrency pairs -- trade, depth, K-line
Japan client.japan Japan market data -- trade, depth, K-line
India client.india India market data -- trade, depth, K-line
Common client.common Cross-market data -- trade, depth, K-line
Basic client.basic Symbol lists, static info, adjustment factors, trading calendar
Market client.market Market temperature, breadth, indexes, leaders
Plate client.plate Sector/industry/concept plates, members, charts
Stock Info client.stock_info Fundamentals -- valuation, ratings, company, panorama, events

client.basic

# instrument list — `type` is required
# STOCK_US STOCK_CN STOCK_HK STOCK_JP STOCK_KS STOCK_IN CRYPTO FOREX FUTURES
client.basic.get_symbols("STOCK_US")
client.basic.get_symbols("STOCK_US", symbols="AAPL.US,TSLA.US")

# static/reference info (max 500 symbols)
client.basic.get_symbol_info("STOCK_US", "AAPL.US")

# forward adjustment factors — dates are YYYYMMDD strings
client.basic.get_adjustment_factors("AAPL.US", "US", "20260801", "20260814")

# trading calendar → {"trade_days": [...], "half_trade_days": [...]}
client.basic.get_trading_days("US", "20260801", "20260831")

# sessions/holidays for non-equity instruments
# type: ENERGY | FOREX | FUTURES | METAL | INDICES
client.basic.get_trading_schedule(type="METAL")

get_trading_hours() is a deprecated alias of get_trading_schedule() and emits a DeprecationWarning; the old /markets/trading_hours path does not exist on the server.

Configuration

You can pass api_key directly or set it via environment variable:

export INFOWAY_API_KEY="YOUR_API_KEY"
# Reads INFOWAY_API_KEY from environment automatically
client = InfowayClient()

Client Options

client = InfowayClient(
    api_key="YOUR_API_KEY",
    base_url="https://data.infoway.io",  # default
    timeout=15.0,                         # request timeout in seconds
    max_retries=3,                        # retries (connection errors, timeouts, rate limits)
    parse=False,                          # normalise market-data payloads
)

Error Handling

from infoway import (
    InfowayClient, InfowayAPIError, InfowayAuthError,
    InfowayRateLimitError, InfowayTimeoutError,
)

client = InfowayClient(api_key="YOUR_API_KEY")

try:
    trades = client.stock.get_trade("AAPL.US")
except InfowayAuthError:
    print("Invalid API key")
except InfowayRateLimitError:
    print("Rate limited — back off and retry")
except InfowayTimeoutError:
    print("Request timed out")
except InfowayAPIError as e:
    print(f"API error [{e.ret}]: {e.msg}")

InfowayRateLimitError subclasses InfowayAPIError. Rate limiting is also served with HTTP 200 and a body of {"detail": "Rate limit exceeded"}, which older SDK versions silently turned into None; it is now raised (and retried with backoff) properly.

License

MIT


Get your free API key at infoway.io -- 7-day free trial, no credit card required.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

infoway_sdk-0.2.0.tar.gz (62.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

infoway_sdk-0.2.0-py3-none-any.whl (27.6 kB view details)

Uploaded Python 3

File details

Details for the file infoway_sdk-0.2.0.tar.gz.

File metadata

  • Download URL: infoway_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 62.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for infoway_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 572e1e811a4292bb6dbc2e7f2ae30b01542119a4b43213a9f9ad7b84f46099fb
MD5 23c780044d105abef5b634ec9b6cd48c
BLAKE2b-256 0424cbd711d055cff41221dd166550626c97292e623477bc47fc4e711cff4406

See more details on using hashes here.

File details

Details for the file infoway_sdk-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: infoway_sdk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 27.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for infoway_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dad9cf21347497187316fb91507c23ccbeb16593d249d42d3450ef05bce2f35d
MD5 f4a8b3aa40088e5b437015a22bead6d8
BLAKE2b-256 f1da94c0c00c0b3f91eae2957787f78e44a7cb43d890e099699a49f8d8837f30

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page