Official Python SDK for the SiftingIO market data API (sync + async REST, plus WebSocket).
Project description
siftingio
Official Python SDK for the SiftingIO market data API — sync and async REST clients plus a live WebSocket, fully type-hinted.
- Sync and async.
SiftingClientfor scripts, notebooks, and pandas;AsyncSiftingClientfor asyncio services. Same method names, same shapes. - Typed. Every endpoint, parameter, and response is annotated (
py.typed); responses are plain dicts withTypedDictshapes for editor autocomplete. - Resource-mapped. Methods mirror the API docs 1:1.
- Batteries included. Auto-retry on 429/5xx, gzip negotiation, cursor auto-pagination, and an auto-reconnecting WebSocket client.
Install
pip install siftingio
Requires Python 3.9+. Depends only on httpx and websockets.
Quick start (sync)
from siftingio import SiftingClient
client = SiftingClient(api_key="sft_...") # or env-driven; see below
# Live price
trade = client.last.trade("crypto", "BTCUSDT")
print(trade["p"], trade["t"])
# Company fundamentals
profile = client.stocks.profile("AAPL")
ratios = client.stocks.ratios("AAPL")
# Historical bars (gzip handled for you)
bars = client.crypto.bars("BTCUSD", start="2024-01-01", interval="1h")
print(len(bars["data"]), "bars")
client.close() # or use `with SiftingClient(...) as client:`
Quick start (async)
import asyncio
from siftingio import AsyncSiftingClient
async def main():
async with AsyncSiftingClient(api_key="sft_...") as client:
quote = await client.last.quote("crypto", "ETHUSDT")
print(quote["b"], quote["a"])
asyncio.run(main())
Authentication
Get an API key from your SiftingIO dashboard. It's sent as the X-API-Key header. You can also supply it dynamically (e.g. from a secrets manager or a rotating token):
client = SiftingClient(get_api_key=lambda: read_secret("SIFTING_API_KEY"))
# Async: the hook may be sync or async
async_client = AsyncSiftingClient(get_api_key=fetch_token_async)
Configuration
SiftingClient(
api_key="sft_...", # X-API-Key header
get_api_key=callable, # dynamic alternative to api_key
base_url="https://api.sifting.io", # override for proxies/staging
ws_url="wss://stream.sifting.io/ws/v1", # WebSocket endpoint
timeout=30.0, # per-request timeout (seconds)
max_retries=2, # automatic retries for 429 / 5xx
headers={"X-Trace": "…"},# extra headers on every request
http_client=httpx.Client(...), # bring your own httpx client
)
AsyncSiftingClient takes the same arguments (with httpx.AsyncClient).
Resources
| Namespace | Endpoints | Highlights |
|---|---|---|
client.last |
/v1/last/* |
trade, quote, tvl — live snapshots |
client.stocks |
/v1/fnd/stocks/*, /v1/hist/stocks/* |
search, profile, filings, financials, ratios, insiders, events, screener, bars, … |
client.filers |
/v1/fnd/filers/* |
holdings — 13F positions |
client.markets |
/v1/fnd/markets/* |
list, status, hours, calendar |
client.forex |
/v1/hist/forex/* |
bars |
client.crypto |
/v1/hist/crypto/* |
bars |
client.dex |
/v1/fnd/dex/* |
wallet portfolios |
client.economic_calendar |
/v1/fnd/economic-calendar |
list |
Python keyword params that collide with reserved words use a trailing underscore: pass
from_=...(sent to the API asfrom).
Pagination
List endpoints return {"data": [...], "meta": {...}} with an opaque meta["next_cursor"]. Stream every page with auto_paginate (sync) or aauto_paginate (async):
from siftingio import auto_paginate, collect_all
for filing in auto_paginate(lambda cursor: client.stocks.filings("AAPL", cursor=cursor, form="10-K")):
print(filing["accession"], filing["filed_at"])
insiders = collect_all(lambda cursor: client.stocks.insiders("TSLA", cursor=cursor), max_items=100)
from siftingio import aauto_paginate
async for filing in aauto_paginate(lambda cursor: client.stocks.filings("AAPL", cursor=cursor)):
...
Live WebSocket
Async:
async with client.ws() as socket: # client = AsyncSiftingClient(...)
socket.on("tick", lambda t: print(t["s"], t.get("p")))
socket.on("error", lambda e: print("server error:", e["code"], e["message"]))
await socket.subscribe("cex", ["BTCUSDT", "ETHUSDT"]) # products: cex|dex|fx|us|tvl
async for frame in socket: # or rely purely on handlers
...
Sync:
socket = client.ws() # client = SiftingClient(...)
socket.on("tick", lambda t: print(t["s"], t.get("p")))
socket.connect()
socket.subscribe("cex", ["BTCUSDT"])
for frame in socket.stream():
...
socket.close()
Subscriptions are tracked and replayed automatically on reconnect, so you subscribe once and keep receiving data across drops. In the sync client, handlers run on a background thread.
Error handling
from siftingio import SiftingAPIError, SiftingConnectionError
try:
client.stocks.profile("NOPE")
except SiftingAPIError as err:
err.status # 404
err.code # "unknown_ticker"
err.retry_after # seconds, on 429
err.request_id # X-Request-Id — quote this in support tickets
err.body # full parsed error body
except SiftingConnectionError as err:
err.timeout # True if it was a client-side timeout
The client automatically retries 429 and 5xx up to max_retries, honoring Retry-After.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file siftingio-0.1.0.tar.gz.
File metadata
- Download URL: siftingio-0.1.0.tar.gz
- Upload date:
- Size: 23.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ec0b29dc0690045f7c93280824043d9df4eb4671a43a55ab9737889f1b84587
|
|
| MD5 |
9a670a11c462bc5ee1812d860201e951
|
|
| BLAKE2b-256 |
e37ab09339a9fb64cd493748dcd3673ab7ca3b4331d145380eb83fff5acaeeca
|
File details
Details for the file siftingio-0.1.0-py3-none-any.whl.
File metadata
- Download URL: siftingio-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1abf7aca38e2e62eb1d17dfa77dd807bec9c70f1fa199b2c199eb4114f28de12
|
|
| MD5 |
a5f6322998e356f977047c2e97f35587
|
|
| BLAKE2b-256 |
202faab0dec5eef38004a022353a1dc9be5a3fb793e4727077a311130845df48
|