A 50-line Python slice client

Slices are the right primitive when you download the same thing repeatedly. Here's a small, dependency-light class wrapping the slice CRUD — create, list, download (streaming), and delete — that you can drop into any project.

The client

import requests

class WeatherFiles:
    """A minimal client for the WeatherFiles slice API."""
    BASE = "https://api.weatherfiles.com/v1"

    def __init__(self, token):
        self.s = requests.Session()
        self.s.headers["Authorization"] = f"Bearer {token}"

    def me(self):
        return self.s.get(f"{self.BASE}/auth/me").json()

    def models(self):
        return self.s.get(f"{self.BASE}/models").json()

    def slices(self):
        return self.s.get(f"{self.BASE}/slices").json()

    def create_slice(self, model_id, params, bbox=None,
                     time_window_h=None, label=None, tags=None):
        body = {"model_id": model_id, "params": params}
        for k, v in dict(bbox=bbox, time_window_h=time_window_h,
                         label=label, tags=tags).items():
            if v is not None:
                body[k] = v
        r = self.s.post(f"{self.BASE}/slices", json=body)
        r.raise_for_status()
        return r.json()

    def download(self, url, path):
        with self.s.get(url, stream=True) as r:
            r.raise_for_status()
            with open(path, "wb") as f:
                for chunk in r.iter_content(1 << 16):
                    f.write(chunk)

    def delete_slice(self, token):
        self.s.delete(f"{self.BASE}/slices/{token}")

Using it

wf = WeatherFiles("wf_pat_…")
print(wf.me()["tier"], wf.me()["daily_downloads_used_today"])

# create once...
s = wf.create_slice("harm-nl", ["wind", "gusts"],
                    bbox="3,7,51,54", time_window_h=48,
                    label="north-sea", tags=["routing"])

# ...download any time - always the latest run
wf.download(s["download_url"], "north-sea.grib2")

# refresh the freshest of all your slices
freshest = max(wf.slices(), key=lambda x: x["last_run_time"] or "")
wf.download(freshest["download_url"], "latest.grib2")

The download URL never changes and always serves the model's latest run, so "refresh" is just re-downloading. Use last_run_time / next_available_at from slices() to decide when (see the notifier tutorial). Wrap downloads in the 429-retry helper if you run them on a tight schedule.