Skip to content

API reference

Client / AsyncClient

Client(
    api_key: str | None = None,   # defaults to $TOPOLAB_API_KEY
    *,
    base_url: str | None = None,  # explicit override (wins over environment)
    environment: str | None = None,  # "production" (default) | "staging"
    timeout: float = 60.0,
    max_retries: int = 3,
    proxy_url: str | None = None,
    user_agent: str | None = None,
)

AsyncClient takes the same arguments and is an async context manager (async with AsyncClient(...) as tl: ...) or close with await tl.aclose().

Member Returns Notes
tl.datasets.list(*, page, limit, search, theme, country, sort_by, sort_order) DatasetPage Catalog listing
tl.datasets.owned(*, limit=None, offset=None) OwnedDatasets Datasets your organization licences; limit 1–200 (server default 50), offset ≥ 0
tl.datasets.iter_owned(*, page_size=50, total_limit=None) iterator of OwnedDataset Pages owned() by offset until total is reached
tl.dataset(slug) Dataset Lazy handle for one dataset
tl.sql(query, *, max_rows=None) SqlResult Read-only SELECT across licensed datasets; needs the Enterprise sql-access entitlement

Dataset / AsyncDataset

Method Returns Notes
.metadata(locale=None) DatasetSummary Dataset metadata
.sample(format="geojson") dict | str Free preview; csv/json/geojson/kml
.to_geojson() dict Full dataset (requires API_ACCESS)
.download(path, format="geojson") str Streamed; csv/json/geojson/kml/shp
.to_geodataframe() geopandas.GeoDataFrame Requires the geo extra
.items(*, bbox, limit=100, offset, category, city, country) dict One page of OGC features
.iter_items(*, page_size=100, total_limit=None, bbox, category, city, country) iterator of dict Auto-paginates
.archives() list[Archive] Available monthly archives, newest first
.archive(path, *, month="latest", format="geojson") str Streams one monthly archive (zip) to path
.coordinates(*, limit=None, offset=None) CoordinatePage Coordinate rows; limit ≤ 50000, offset ≥ 0

On AsyncClient, every Dataset method is awaitable and iter_items is an async iterator.

Collections are addressed by slug

The OGC collectionId is the dataset's table slug (e.g. nl-domino-poi) — the same value you pass to dataset(). The SDK calls /v1/ogc/collections/{slug}/items directly; there is no slug→uuid resolution step.

Models

Model Fields
OwnedDatasets items: list[OwnedDataset], total, limit, offsettotal counts all licensed datasets, not the page
OwnedDataset table, name, recordCount, latestArchiveMonth, latestArchiveFormats, archiveMonthsAvailable, links
OwnedDatasetLinks current, archives, latestArchive — absolute URLs; current and latestArchive contain a literal {format} placeholder, and latestArchive is None when no archive is in range
Archive month (YYYY-MM), formats, archiveDate
CoordinatePage rows: list[CoordinateRow], total, returned, offset — the counts come from the X-Total-Count / X-Returned-Count / X-Offset response headers
CoordinateRow id, location (GeoJSON geometry), latitude, longitude, metadatalatitude/longitude are strings, kept verbatim (a numeric value is stringified, never parsed as a float)
SqlResult columns, rows, rowCount, truncated, elapsedMs, datasets

Models ignore nothing: unknown fields the API adds later are preserved rather than dropped.

Addressing an archive

month accepts latest, YYYY-MM, or YYYY-MM-DD (the month containing that date). The value is checked as a real calendar value before the request goes out, so 2026-13, 2026-07-99 and 2026-02-29 raise ValueError locally instead of costing a round trip.