Skip to content

Timestamps

Every SDK method that takes a timestamp requires a tz-aware datetime. Naive datetimes raise ValueError at the call site — never silently converted, never assumed UTC.

Constructing one

from datetime import datetime, timezone

start = datetime(2024, 1, 1, tzinfo=timezone.utc)
end   = datetime(2024, 1, 2, tzinfo=timezone.utc)

For non-UTC zones:

from datetime import datetime
from zoneinfo import ZoneInfo

start = datetime(2024, 1, 1, 8, 0, tzinfo=ZoneInfo("America/Los_Angeles"))

The SDK serializes to UTC ISO-8601 internally regardless of the input zone.

Wire formats — two flavors

The server is inconsistent about timestamp formats across endpoints (RESEARCH §2 documents which use which):

  • Alarms / events / positions — Unix milliseconds.
  • Reports — ISO-8601 strings.

The SDK picks the right format per endpoint. You always pass the same Python datetime; the SDK handles the conversion.

Parsing server responses

Returned model fields use datetime for any timestamp. They are tz-aware (UTC). Compare them with your own tz-aware values:

report = client.reports.heatmap(start=start, end=end, tag_uids=["t-1"])
if report.created_at > start:
    ...

Anti-patterns

# WRONG — naive datetime raises ValueError
start = datetime(2024, 1, 1)
client.alarms.list(start=start, end=end)

# WRONG — int seconds; the SDK only accepts datetime
client.alarms.list(start=1704067200, end=end)

These are intentional. Naive datetimes are a frequent source of silent off-by-N-hour bugs; the SDK refuses to guess.