Conventions
| Context | Format |
|---|---|
| Timestamps in JSON payloads (reads) | ISO 8601 with offset or Z. Example: "2026-06-12T18:30:00Z". |
Date-only query params (since, until, start_date, end_date, email_sent_date, …) | YYYY-MM-DD. No time component. |
Token expiry (ExpiresIn) | Integer seconds from now. |
| Display | Use the partner’s profile.zoneinfo (e.g. Europe/Berlin). The API does not normalise to UTC for display fields. |
Sending date params
Always validate before sending. The reference webapp usesmoment to
ensure YYYY-MM-DD:
Parsing timestamps from responses
GET /profile/ and use
profile.zoneinfo:
DST and partner zoneinfo
profile.zoneinfo is an IANA TZ identifier (Europe/Berlin, America/New_York).
Modern Intl.DateTimeFormat and date-fns/tzdata handle DST correctly. The
field is set on user provisioning; partners can update it via
PUT /profile/ { zoneinfo: "..." }.
Token expiry — ExpiresIn
ExpiresIn is seconds, not milliseconds. Easy to confuse — multiply
by 1000 when constructing Date or epoch ms.
Filter date ranges
A common UX is “last 14 days”, “last 8 weeks”, “all”:since: "1900-01-01" and until: "2100-01-01" is the canonical “all time”
range — the reference webapp uses exactly these on /daily_revenue_summary/.
Common mistakes
Sending the user's local date for "today"
Sending the user's local date for "today"
new Date().toISOString().slice(0,10) returns UTC date, which may be
yesterday for users in the Americas. Compute in the user’s zone, or
use the partner zoneinfo, depending on UX.Treating timestamps as naïve local time
Treating timestamps as naïve local time
2026-06-12T18:30:00 (no offset, no Z) is ambiguous. Future Demand
sends offsets; if you ever strip them, do it at the display layer only.Multiplying ExpiresIn by 1 instead of 1000
Multiplying ExpiresIn by 1 instead of 1000
Yields
expiresAt = ~1 hour ago. Token “always expired”, refresh loop.
Easy mistake; double-check the unit.Showing UTC offsets that don't match the venue
Showing UTC offsets that don't match the venue
A concert in Munich on
2026-06-12T18:30:00Z is actually 20:30 local.
For event-time displays, use event.tz (when present) or
profile.zoneinfo, not the user’s browser zone.