StockStream SDK
The typed Python client for StockStream — async and sync, fully type-hinted, zero server-tree dependency.
stockstream-sdk is a typed Python client for the StockStream REST API — a market-data sync engine
(yfinance-backed) that tracks assets, OHLCV price series, composed indices, FX pairs and scheduled
syncs. The SDK ships both an asynchronous and a synchronous client with an identical surface, is
fully type-hinted (py.typed, Pydantic v2 models), and has zero dependency on the StockStream
server tree — it talks to the API over HTTP only (httpx + pydantic + hand-written models
mirroring the public REST contract), so it can be vendored or published independently.
- ✅ Async + sync — the same methods with and without
await. - ✅ Typed end to end — request/response Pydantic models, no
dict-spelunking. - ✅ Context-managed — connection pooling via
async with/with. - ✅ Typed errors — one exception hierarchy for connection, auth, 404, 409, 422…
- ✅ Tiny footprint — only
httpxandpydantic.
Install
pip install stockstream-sdk
Requirements
- Python 3.12+
- A running StockStream API (self-hosted). The examples assume
http://localhost:8000. - An API token when the server has auth enabled (
API_AUTH_ENABLED).
Quickstart
Async
import asyncio
from stockstream_sdk import AsyncClient, AssetCreateRequest
async def main() -> None:
async with AsyncClient("http://localhost:8000", api_token="ss_root_...") as client:
# Liveness
print(await client.health.ping())
# Track an asset, then trigger a sync
asset = await client.assets.create(AssetCreateRequest(symbol="AAPL", timeframe="1d"))
trigger = await client.assets.sync(asset.asset_id)
print(trigger.job_id, trigger.status)
# Read its OHLCV series (optionally currency-converted)
prices = await client.assets.prices("AAPL", timeframe="1d", target_currency="EUR")
for bar in prices.data[-5:]:
print(bar.timestamp, bar.close)
asyncio.run(main())
Sync
The synchronous client is the async one without await — same resources, same signatures.
from stockstream_sdk import Client
with Client("http://localhost:8000", api_token="ss_root_...") as client:
for asset in client.assets.list(quote_type="equity", limit=20).items:
print(asset.asset_id, asset.symbol, asset.quote_type)
Both clients accept the same constructor:
AsyncClient(base_url: str, timeout: float = 30.0, api_token: str = "")
Client(base_url: str, timeout: float = 30.0, api_token: str = "")
| Argument | Default | Meaning |
|---|---|---|
base_url |
— | API origin, e.g. "http://localhost:8000". |
timeout |
30.0 |
Per-request timeout in seconds. |
api_token |
"" |
Bearer token; empty means unauthenticated requests. |
Always use the client as a context manager (
async with/with) so the underlying HTTP connection pool is opened and closed cleanly. You can construct it directly, but then you ownawait client.aclose()/client.close().
Authentication
When the StockStream server runs with auth enabled, pass a bearer token as api_token. It is sent as
Authorization: Bearer <token> on every request. Mint and manage tokens through client.auth:
from stockstream_sdk import Client, ApiTokenCreateRequest
with Client("http://localhost:8000", api_token="ss_root_...") as client:
created = client.auth.create_token(
ApiTokenCreateRequest(name="reporting-bot", permissions=["assets.*", "jobs.*"])
)
print("SAVE THIS NOW:", created.jwt_token) # plaintext, only returned once
Resources & methods
Every resource hangs off the client (client.<resource>.<method>(...)). The async and sync surfaces
are identical.
| Resource | Highlights |
|---|---|
health |
ping(), ready() |
assets |
create/list/get/update/delete, categories, prices, precheck, bulk_import, composed list_composed/create_composed/get_composed/update_composed/delete_composed, detail analyst/holders/events/financials/metadata_history, sync |
jobs |
list, get, delete |
cron |
create/list/get/update/delete, dismiss_error, run, optimizer_preview, optimizer_apply |
currency_pairs |
list_codes, upsert, list, precheck, prices, delete, sync |
timezone |
list, validate, convert |
auth |
me, permissions, token create_token/list_tokens/get_token/update_token/delete_token/issue_token, usage |
ui |
overview, options, asset_relations, currency_relations |
Error handling
Every failure raises a subclass of StockStreamError, so you can catch broadly or precisely.
from stockstream_sdk import (
Client,
StockStreamError,
APIConnectionError,
APITimeoutError,
APIStatusError,
AuthError,
NotFoundError,
ConflictError,
UnprocessableError,
)
with Client("http://localhost:8000", api_token="ss_...") as client:
try:
client.assets.get("does-not-exist")
except NotFoundError:
... # 404
except AuthError:
... # 401 / 403 — bad or unscoped token
except UnprocessableError as e:
... # 422 — validation errors (see e.status_code / e.body)
except APITimeoutError:
... # request exceeded `timeout`
except APIConnectionError:
... # server unreachable
except StockStreamError:
... # catch-all
Hierarchy:
StockStreamError
├── APIConnectionError
│ └── APITimeoutError
└── APIStatusError # any non-2xx (carries .status_code + .body)
├── AuthError # 401 / 403
├── NotFoundError # 404
├── ConflictError # 409
└── UnprocessableError # 422
Type hints & discoverability
The package ships py.typed, so editors and type-checkers see every request/response type. All
public models and clients are re-exported from the top level (from stockstream_sdk import ...).
Versioning & compatibility
The SDK tracks the StockStream REST contract; a CI parity gate diffs the SDK models against the
server's OpenAPI on every change (tests/check_schema_drift.py), so a published version is coherent
with the API it targets. Pin a version in production:
pip install "stockstream-sdk==0.1.0"
Development & tests
uv sync
uv run ruff check .
uv run mypy --strict stockstream_sdk
uv run pytest -q -m "not live" # unit + parity (offline)
Live tests
The tests/live/ suite is opt-in and hits a running StockStream stack:
export STOCKSTREAM_E2E_URL="http://localhost:8000"
export STOCKSTREAM_E2E_TOKEN="ss_root_..." # when auth is enabled
uv run pytest -q -m live
It auto-skips when no API is reachable, so it is safe to leave in CI without a live backend.
Schema drift gate
# <current.json> is a freshly-dumped backend OpenAPI document
uv run python tests/check_schema_drift.py <current.json>
Exits non-zero (with a fix instruction) when a tracked schema's property names or required fields
diverge from the committed tests/openapi_snapshot.json.
License
MIT — see LICENSE.
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 stockstream_sdk-0.1.0.tar.gz.
File metadata
- Download URL: stockstream_sdk-0.1.0.tar.gz
- Upload date:
- Size: 105.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e41fe328964713390cd57fdf68a405c338f7a8197469ced89cad381f7cce393
|
|
| MD5 |
a865ef674e512b837d72503777842b22
|
|
| BLAKE2b-256 |
5bbbcf1565a7a1266655f7284a8e5074efa7f4dc725bbca6b4fc2408c0e7f950
|
Provenance
The following attestation bundles were made for stockstream_sdk-0.1.0.tar.gz:
Publisher:
release-sdk.yml on Florian-BARRE/StockStream
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stockstream_sdk-0.1.0.tar.gz -
Subject digest:
0e41fe328964713390cd57fdf68a405c338f7a8197469ced89cad381f7cce393 - Sigstore transparency entry: 2696973566
- Sigstore integration time:
-
Permalink:
Florian-BARRE/StockStream@6f1f9718a31a2fdab9d6ddfbfdbc217a110fda6a -
Branch / Tag:
refs/tags/sdk-v0.1.0 - Owner: https://github.com/Florian-BARRE
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-sdk.yml@6f1f9718a31a2fdab9d6ddfbfdbc217a110fda6a -
Trigger Event:
push
-
Statement type:
File details
Details for the file stockstream_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: stockstream_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 56.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a787584a843f42e3cba6f944c8a94bc48aed16f93547d832770ddbdec9656b6c
|
|
| MD5 |
ac2146a6ac61a947cd51ec50b4cc2e5e
|
|
| BLAKE2b-256 |
67fbcad3d4e9e6625bc7e507559459a98e678aa562f207ae2d719349b7aad3fe
|
Provenance
The following attestation bundles were made for stockstream_sdk-0.1.0-py3-none-any.whl:
Publisher:
release-sdk.yml on Florian-BARRE/StockStream
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stockstream_sdk-0.1.0-py3-none-any.whl -
Subject digest:
a787584a843f42e3cba6f944c8a94bc48aed16f93547d832770ddbdec9656b6c - Sigstore transparency entry: 2696973676
- Sigstore integration time:
-
Permalink:
Florian-BARRE/StockStream@6f1f9718a31a2fdab9d6ddfbfdbc217a110fda6a -
Branch / Tag:
refs/tags/sdk-v0.1.0 - Owner: https://github.com/Florian-BARRE
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-sdk.yml@6f1f9718a31a2fdab9d6ddfbfdbc217a110fda6a -
Trigger Event:
push
-
Statement type: