Skip to content

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   ✗ rejected

Timezone Handling

Most date-range endpoints convert the YYYY-MM-DD boundary parameters into Unix timestamps using a timezone:

  • If you supply a timezone query 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 groupMax 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 fieldEndpoint
timesheets[].start_timestampGET /v1/timesheet_idle_times/
timesheets[].end_timestampGET /v1/timesheet_idle_times/
timesheets[].idle_times[].start_timestampGET /v1/timesheet_idle_times/
timesheets[].idle_times[].end_timestampGET /v1/timesheet_idle_times/
[].start_timestampGET /v1/screenshots/
[].end_timestampGET /v1/screenshots/
[].screenshots[].timestampGET /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:

FormatExample
{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/Dhaka

31 days — within the limit.

GET /v1/time_activity_reports/?start_date=2025-05-01&end_date=2025-05-31&timezone=Asia/Dhaka

31 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_York

Walking 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