GET /schedule/work_day_rules
get_schedule_work_day_rules
One row per calendar day, both ends inclusive, no paging at 730 rows. A project_id or user_id that does not exist answers 200 with the studio default instead of an error.
API
Which calendar days count as work. duration and due_date on a Task are computed against this,
so a client that adds working days itself has to read it.
Params
| part | value |
|---|---|
start_date |
required. YYYY-MM-DD |
end_date |
required. YYYY-MM-DD, and must be greater than or equal to start_date |
user_id |
optional. Falls back to the studio rule when absent |
project_id |
optional. Falls back to the studio rule when absent |
Sample requests
A fortnight, studio-wide:
r = c.get("/schedule/work_day_rules",
params={"start_date": "2026-03-02", "end_date": "2026-03-15"})
14 rows for a 14-day window, first two shown:
{
"data": [
{"date": "2026-03-02", "working": true, "description": null, "reason": "STUDIO_WORK_WEEK"},
{"date": "2026-03-07", "working": false, "description": null, "reason": "STUDIO_WORK_WEEK"}
],
"links": {"self": "/api/v1/schedule/work_day_rules?end_date=2026-03-15&start_date=2026-03-02"}
}
A project id that is not on the site, which is not an error:
r = c.get("/schedule/work_day_rules",
params={"start_date": "2026-03-02", "end_date": "2026-03-15",
"project_id": 999999999})
{"data": [{"date": "2026-03-02", "working": true, "description": null,
"reason": "STUDIO_WORK_WEEK"}]}
A date that will not parse:
r = c.get("/schedule/work_day_rules",
params={"start_date": "03/02/2026", "end_date": "03/15/2026"})
{"status": "error", "error": "invalid date"}
A missing parameter:
r = c.get("/schedule/work_day_rules", params={"start_date": "2026-03-02"})
[{"id": "6e3ab12946d1c597355a5373e4ccca44", "status": 400, "code": 103,
"title": "Request Parameters invalid.", "source": {"end_date": ["end_date is missing"]},
"detail": null, "meta": null}]
| row key | shape |
|---|---|
date |
YYYY-MM-DD, one row per calendar day in the range |
working |
boolean |
description |
string or null. Set by the exception that made the day, if any |
reason |
one of STUDIO_WORK_WEEK, STUDIO_EXCEPTION, PROJECT_WORK_WEEK, PROJECT_EXCEPTION, USER_WORK_WEEK, USER_EXCEPTION |
Response codes
| status | when |
|---|---|
| 200 | including for a project_id or user_id that does not exist |
| 400 | {"start_date": ["start_date is missing"], "end_date": ["end_date is missing"]} |
| 400 | start_date_and_end_date 'end_date' must be greater than or equal to 'start_date' |
| 400 | {"status": "error", "error": "invalid date"} for a date that will not parse |
| 401 | Request rejected due to invalid credentials. |
Edge cases
- Two error shapes on one endpoint. A missing or out-of-order parameter is a JSON:API
errorsarray; an unparseable date is a bare{"status": "error", "error": "invalid date"}with noerrorskey at all. A client readingr.json()["errors"][0]["title"]raisesKeyErroron the second. - A
project_idoruser_idthat is not on the site answers 200 with the studio rule. Nothing in the body says which scope answered, other thanreason, andreasonreadsSTUDIO_WORK_WEEKfor both the fallback and a genuine studio-wide answer. Check the id exists before trusting the schedule. - Both ends are inclusive.
start_dateequal toend_datereturns one row. - No paging. A 730-day window returned 730 rows in 61631 bytes, with no
pageenvelope and nolinks.next. Bound the range yourself. links.selfechoes the parameters back, so two responses that differ only inproject_iddiffer in byte length while theirdatais identical.- The dates must be
YYYY-MM-DD.03/02/2026is refused, whateverdate_component_orderinGET /preferencessays the site displays.