Python client for the sitewarm API. Pydantic models are generated from the OpenAPI 3.1 spec in openapi/openapi.yaml with datamodel-code-generator; the runtime is a thin, hand-written httpx client (sync and async). Python 3.10+.
Status: pre-release (0.1.0, not published to PyPI). The API and this client can still change. The spec describes the whole planned surface; the service may not offer every operation yet.
from sitewarm import SiteWarm
with SiteWarm(api_key=KEY, base_url="https://<api host>/v1") as sw:
site = sw.sites.create({"hostname": "example.com"})
sitemap = sw.sitemaps.create(site["id"], {"url": "https://example.com/sitemap.xml"})
started = sw.warm_runs.create(site["id"], {"source": {"type": "sitemap", "sitemap_id": sitemap["id"]}})
run = sw.warm_runs.wait(started["id"])
for r in sw.warm_runs.list_all_results(run["id"], final_state="miss"):
print(r["url"], r["final_state"])A site must be verified before a run is accepted; verification happens outside this API.
- Resource helpers:
sites,sitemaps,warm_runs(create,get,cancel,results,list_all_results,wait),cache_status_reports. Responses are plaindicts (decoded JSON). - Every operation of the spec is reachable through
sw.call("<operationId>", path={...}, query={...}, body=...), for examplesw.call("listSchedules", path={"siteId": site_id});call_rawalso returns status and headers. The operation table is generated and a test fails if it drifts from the spec. AsyncSiteWarmhas the samecall,call_raw,pagesandpaginate(useasync with/async for).- Typing and validation:
sitewarm.modelsholds the generated pydantic models. You can pass a model as a request body, or validate a response withmodels.WarmRun.model_validate(run). - Pagination:
sw.paginate(op, ...)yields items,sw.pages(op, ...)yields pages. Cursors are opaque. - Webhook callbacks (the
webhooks:section of the spec) are server-to-customer and not covered.
- Auth:
Authorization: Bearer <key>. The key is held in a redacting wrapper, so it is not inrepr(),str(),vars(), pickles, error messages or logs (the SDK never logs).api_keymust be printable ASCII without whitespace.base_urlmust be https (http only for localhost) and have no credentials. Redirects are never followed, even with your ownhttpxclient (follow_redirects=Falseis set on every request), so the key never goes to another origin; a 3xx is raised as an API error. - No default
base_url: pass the API host you were given. - Retries: up to
max_retries(3; a negative value keeps the default) on429,5xx(not501) and network errors, with exponential backoff and jitter capped atmax_retry_delay(30 s).Retry-Afteris honored; if it exceeds the cap the error is raised instead of sleeping.429is always retried;5xx, network errors and a response body that breaks off only when repeating is safe (GET,HEAD,PUT,OPTIONS, or a POST with anIdempotency-Key; neverDELETE/PATCH).timeout <= 0keeps the default (30 s). - More retry rules: a
409conflicton a keyed POST is retried (the first attempt may still be running);idempotency-key-reusednever. Certificate/TLS verification failures, unknown hosts and malformed requests are not retried.Retry-Afterhas a floor of the retry base delay and gets up to +25% jitter; aRetry-Afterabove the cap is raised, not slept. - Idempotency: every POST that accepts
Idempotency-Keysends one (a random UUID unless you passidempotency_key), generated once per call and reused by all its retries, so a retriedwarm_runs.createnever starts two runs. - Limits: response bodies over 32 MiB raise
SiteWarmResponseTooLargeError(not retried);pages/paginateraise on a repeated cursor or after 10,000 pages instead of stopping silently; alimitquery value outside 1..100 raises before the request (0 orNone= server default). - Errors:
SiteWarmApiError(status,problemas RFC 9457,code,retry_after_seconds,rate_limit) with subclasses for 401, 403, 404, 409, 400/422, 429 and 5xx;SiteWarmConnectionErrorandSiteWarmTimeoutErrorfor transport;SiteWarmWaitTimeoutErrorfromwarm_runs.wait, which does not cancel the run;SiteWarmDecodeError(status) for a 2xx body that is not JSON (the body is never included). TheUser-Agentissitewarm-python/<version> (+https://github.com/sitewarm/sdk-python); an emptyuser_agentkeeps it.
uv venv && uv pip install -e . --group dev # or: pip install -e . then the dev group
.venv/bin/python scripts/generate.py # regenerate src/sitewarm/_generated from openapi/openapi.yaml
.venv/bin/python -m pytest && .venv/bin/python -m mypy
To update the spec, replace openapi/openapi.yaml and run the generator; CI fails if src/sitewarm/_generated is out of date. The package carries the Private :: Do Not Upload classifier, so PyPI refuses an upload until that line is removed on purpose.
Apache-2.0, see LICENSE.