shelfatlas
Official, typed Python client for the ShelfAtlas Catalog API — read access to normalised Danish retail catalog data (products, offers, stores, chains, and price history).
Install
pip install shelfatlas
Requires Python 3.10+. Depends on httpx and pydantic v2.
Authentication
Every request is authenticated with a ShelfAtlas API key
(Authorization: Bearer sa_live_<key>). Create one in your ShelfAtlas dashboard and
keep it server-side.
Quick start
from shelfatlas import CatalogClient
with CatalogClient(base_url="https://api.shelfatlas.com", api_key="sa_live_…") as client:
# Products for one brand, minus two discontinued items
products = client.products.list(
brand_ids=["<brand-uuid>"],
exclude_ids=["<product-uuid>", "<product-uuid>"],
limit=24,
)
for product in products.data:
print(product.id, product.canonical_name)
# Current offers for a batch of products
offers = client.offers.list(product_ids=[p.id for p in products.data])
# Daily minimum-price series
history = client.price_history.daily(product_ids=[p.id for p in products.data])
# Stores within 5 km of a coordinate
stores = client.stores.nearest(lat=55.68, lng=12.57, radius_km=5)
# All chains (not paginated)
chains = client.chains.list()
# Walk every page of a listing
for product in client.iter_products(chain_slug="netto"):
print(product.canonical_name)
Numeric price fields are decimal strings (Postgres numeric columns are
returned as strings, not floats) — parse with decimal.Decimal before arithmetic.
Methods
| Group | Method | Endpoint |
|---|---|---|
products |
list(**filters) → Page[Product] |
GET /products |
get(id) → Product |
GET /products/:id |
|
offers_for(id, ...) → Page[Offer] |
GET /products/:id/offers |
|
offers |
list(**filters) → Page[Offer] |
GET /offers |
get(id) → Offer |
GET /offers/:id |
|
stores |
list(...) → Page[Store] |
GET /stores |
nearest(lat, lng, radius_km=...) |
GET /stores (nearest) |
|
get(id) → Store |
GET /stores/:id |
|
chains |
list() → list[Chain] |
GET /chains |
price_history |
daily(product_ids, days=...) |
GET /price-history |
| client | iter_products/iter_offers/iter_stores |
cursor walkers (generators) |
Errors
Every failure raises CatalogAPIError with a .code:
unauthorized · rate_limited (carries .retry_after_sec) · invalid_params ·
not_found · server_error · network_error · invalid_response. GETs retry
automatically on 429/5xx (3 attempts, exponential backoff, honouring Retry-After).
from shelfatlas import CatalogAPIError
try:
client.products.get("missing")
except CatalogAPIError as err:
if err.code == "not_found":
...
Rate limits & quotas
Free keys: 1,000 requests lifetime, 60 requests/minute. Partner keys: no lifetime cap, 600 requests/minute.
API reference
The full machine-readable contract this client conforms to is published as OpenAPI 3.1 at https://shelfatlas.com/docs/openapi.json. Human docs: https://shelfatlas.com/docs.
Development
This SDK has its own toolchain (uv), independent of the JS monorepo:
make setup # uv venv (Python 3.12) + install -e ".[dev]"
make test # pytest
make build # uv build → sdist + wheel in dist/
make smoke CATALOG_API_KEY=sa_live_… # live end-to-end test
make openapi # regenerate tests/openapi.json from the TS source of truth
License
MIT
Release files for shelfatlas 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shelfatlas-1.0.0.tar.gz | 14.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shelfatlas-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.1 kB
Release files / shelfatlas-1.0.0.tar.gz
| Download URL | shelfatlas-1.0.0.tar.gz |
|---|---|
| Size | 14.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4f3d34472d4179f1dd1449f1a809b0b52009121506d85fa10818f959d618b4e9
|
|
BLAKE2b-256 checksum How to use checksums |
34670024f26b5a84c52976668b3902572aac0bf774d8d67a93ffc8ad5ce53fc3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / shelfatlas-1.0.0-py3-none-any.whl
| Download URL | shelfatlas-1.0.0-py3-none-any.whl |
|---|---|
| Size | 8.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ef35b61436f9c55038dbd9f153d440766af28099cdd4d64ad40147df4f1f767
|
|
BLAKE2b-256 checksum How to use checksums |
188eb62ad7adbc509ab3b04a08cec0e6a81f7c57e4f465af95bf8ddb17a436b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|