Date and Timezone Guide
Date Format
All dates use YYYY-MM-DD. Both query parameter inputs and date-typed response fields use this format.
2025-01-15 ✓ correct
2025-1-15 ✗ rejected (VALIDATION_ERROR)
01/15/2025 ✗ rejected
15-01-2025 ✗ rejectedTimezone Handling
Most date-range endpoints convert the YYYY-MM-DD boundary parameters into Unix timestamps using a timezone:
- If you supply a
timezonequery parameter, that timezone is used. - Otherwise, the organization's configured timezone (from
GET /v1/organizations/) is used.
The timezone value must be a valid IANA timezone string (e.g. America/New_York, Asia/Dhaka, UTC). Passing an invalid string returns 400 VALIDATION_ERROR.
How boundaries are computed
Given start_date=2025-01-15 and end_date=2025-01-17 in America/New_York:
start boundary → 2025-01-15 00:00:00 EST (Unix: 1736917200)
end boundary → 2025-01-17 23:59:59 EST (Unix: 1737158399)Data whose timestamps fall within [start_boundary, end_boundary] is included.
This means if you specify `America/New_York` but the organization is set to `UTC`, you will get the data for the New York day boundaries, not the UTC day boundaries. Always specify timezone when you need results aligned to a specific timezone rather than inheriting the org setting.
Date Range Limits
| Endpoint group | Max range (days) |
|---|---|
GET /v1/timesheet_idle_times/ | 31 |
GET /v1/time_activity_reports/ | 31 |
GET /v1/manual_timesheet_reports/ | 31 |
GET /v1/clockinouts/ | 31 |
GET /v1/app_reports/ | 31 |
GET /v1/url_reports/ | 31 |
GET /v1/screenshots/ | Single day only (date param, not a range) |
The count is inclusive: 2025-01-01 to 2025-01-31 = 31 days (allowed). 2025-01-01 to 2025-02-01 = 32 days (rejected).
Payroll log endpoints (hourly_payment_log, one_time_payment_log) have no date range limit.
Screenshots — Single-Date Lookback Limit
GET /v1/screenshots/ accepts a date parameter (a single YYYY-MM-DD, not a range). The maximum lookback is 179 days from today. Requesting a date older than 179 days returns 404.
Timestamps in Responses
Several response fields return Unix timestamps (seconds since 1970-01-01 00:00:00 UTC):
| Response field | Endpoint |
|---|---|
timesheets[].start_timestamp | GET /v1/timesheet_idle_times/ |
timesheets[].end_timestamp | GET /v1/timesheet_idle_times/ |
timesheets[].idle_times[].start_timestamp | GET /v1/timesheet_idle_times/ |
timesheets[].idle_times[].end_timestamp | GET /v1/timesheet_idle_times/ |
[].start_timestamp | GET /v1/screenshots/ |
[].end_timestamp | GET /v1/screenshots/ |
[].screenshots[].timestamp | GET /v1/screenshots/ |
To convert to a local time for display: datetime.utcfromtimestamp(ts).replace(tzinfo=timezone.utc).astimezone(your_tz).
ISO 8601 timestamps
Clock-in/clock-out records return ISO 8601 strings with the timezone offset preserved:
"clock_in": "2025-01-15T09:00:00+05:30"Duration Formatting
Duration fields are formatted strings, not integers:
| Format | Example |
|---|---|
{h}h {m}m {s}s | "7h 45m 00s" — time activity report |
{h}h {m}m | "8h 30m" — hourly payment log |
The h component can be large: "102h 15m 30s" is a valid value for timesheets spanning multiple days. Minutes and seconds are zero-padded to 2 digits; hours are not padded.
End-of-Day Boundary Difference
The report and apps/URLs endpoints set the end-of-range boundary to 23:59:59 on end_date. The timesheet endpoint includes all timesheets where start_timestamp falls on or before end-of-day.
For the screenshots endpoint, the day is bounded by midnight-to-midnight in the specified (or org) timezone.
Payroll Date Fields
hourly_payment_log and one_time_payment_log return paid_for_date and paid_at as YYYY-MM-DD strings (not Unix timestamps). These represent the calendar date the payment was recorded for, independent of timezone.
invoice.issued_date and invoice.due_date are also YYYY-MM-DD strings.
Practical Examples
Fetching data for a complete month
GET /v1/time_activity_reports/?start_date=2025-06-01&end_date=2025-06-30&timezone=Asia/Dhaka31 days — within the limit.
GET /v1/time_activity_reports/?start_date=2025-05-01&end_date=2025-05-31&timezone=Asia/Dhaka31 days — also fine. To cover May and June in one call, you would need to split into two requests.
Fetching screenshots for yesterday
Replace 2025-06-29 with the actual date in YYYY-MM-DD:
GET /v1/screenshots/?user_id=...&date=2025-06-29&timezone=America/New_YorkWalking a 90-day window in 31-day chunks
Chunk 1: start=2025-01-01 end=2025-01-31
Chunk 2: start=2025-02-01 end=2025-03-01 (28 days for Feb 2025)
Chunk 3: start=2025-03-02 end=2025-04-01