Skip to main content

Overview

silo-client is a small Python client for the Data API. One class, one method per endpoint, PostgREST underneath. It exists to make the two things that bite hand-written callers impossible to miss: a capped response raises instead of returning a short series, and views page while functions do not. It lives in the repository and is not on PyPI, deliberately, while the API’s surface is still moving.

Install

Python ≥ 3.10. Or copy sdk/silo_client/ into your project.

Configure

Pass url= / key= or set SILO_URL / SILO_ANON_KEY to override the built-in project and key. To move to the signed-in tier, pass a user JWT as token= (or set SILO_TOKEN); silo.tier says which ceiling you are under.

First calls

panel validates metric names against the live catalog, so a typo raises ValueError client-side instead of returning an empty panel. Missing observations stay NaN — never filled. ids and metrics each accept one bare string or any sequence of them. The single-string case is handled explicitly, not left to Python’s sequence semantics: str is a Sequence[str], so an unguarded list("PETR4") would ask for five one-character ids and the server’s empty answer would read as “no data for PETR4”.

Every method

One per published endpoint. Dates accept date objects or ISO strings; None means the server’s default, which for fund windows is the honest one.

The three rules the client enforces

A capped response raises

PostgREST stops every response at 1,000 rows and answers 200 with the oldest page. The client asks for a true count (Prefer: count=exact) and raises rather than hand you the short answer:
For the three long series the server refuses instead (SiloOverCap), and each pages with its own cursor:
For option_history, termo_history, financials, company_financials, anbima_classes, inflation, inflation_items, fidc_tranches, fidc_aging, fund_documents, fund_restatements, fund_restatement_diff, company_events, macro_series, ptax, future_curve, future_series, curve, curve_history and the screen_* functions there is no cursor: SiloOverCap means narrow the window. panel(wide=True) refuses to pivot a CNPJ that files under two families in the same month — pass entity_type=, or take wide=False and keep asset_class in your own key.

Views page; functions do not

view_all / iter_view require an order — offset paging without a total order can duplicate a row at one boundary and drop one at the next. A view() with no limit that lands on the cap still raises: that is the silent cut, not a page.

The client tells you when it is out of date

catalog() compares the server’s catalog version against the one the client was written for and warns SiloCatalogDrift on a mismatch. It never refuses — everything read off the catalog keeps working. silo.limits() is the tier table straight from the server.

Errors

The client never retries a 4xx into a different answer, and connection retries are safe only because every endpoint is read-only.

Source

sdk/silo_client/client.py is short enough to read in one sitting, and tests/test_sdk_client.py is the contract: offline, via httpx.MockTransport, no network.