Summary
Asana tasks can be organized into deep subtask hierarchies, but a parent task’s dates have always been independent of its subtasks’ dates. A parent could be due March 15 while a subtask ran to March 20, and nothing in the API surfaced that gap.
This release adds API support for detecting when a task’s dates no longer cover its descendants’ dates, and for triggering the same date-alignment operation available in the Asana web app.
- Detect mismatches: Request the new
has_subtasks_date_mismatchfield on a Task resource to see whether one or more descendant subtasks have dates outside the task’s own date range. - Reconcile one task tree:
POST /tasks/{task_gid}/rollupstarts an asynchronous job that updates dates across the task’s subtask tree. - Reconcile a project:
POST /projects/{project_gid}/rollupstarts an asynchronous job across the project. - Track progress: Poll
GET /jobs/{job_gid}. Project rollup jobs return progress viadates_rollup_progress.
Who is affected
The Task field and both endpoints are additive; applications that don’t request or call them are unaffected.
This is relevant to:
- Developers who read or display task scheduling data (e.g., dashboards, Gantt/timeline integrations, reporting tools) – you can now surface a subtask date conflict without walking the subtask tree yourself.
- Developers who manage schedules programmatically – you can trigger the same date-alignment action available in the web app instead of reading and rewriting dates throughout the hierarchy.
If your integration reads Job resources, note that we are adding two new resource_subtype values: rollup_task and rollup_project. Make sure your code handles Job subtypes it does not recognize, rather than failing on them.
Timeline
This is available now!
Usage
How the rollup is calculated
A rollup sets, for each parent task in scope:
start_on/start_at= the earlieststart_on/start_atamong its subtasksdue_on/due_at= the latestdue_on/due_atamong its subtasks
Behavior
- The rollup job does not add scheduling fields that aren’t already there. It won’t create a date range on an undated task, and it won’t add a start date to a task that only has a due date. For example, if the parent has only
due_onset while its subtasks have bothstart_onanddue_on, rollup may adjust the parent’sdue_on, butstart_onstays unset. If the parent has no scheduling fields at all, rollup leaves the task unchanged, andhas_subtasks_date_mismatchreturnsfalse. Note that this applies to which fields exist, not to their precision: an existing boundary can change between a date-only and an exact-time value when the descendant rollup requires it. - Undated subtasks contribute no date boundaries of their own and do not clear the parent’s dates. An undated intermediate task still passes up the dates of its dated descendants. Completed subtasks are included, so the calculated range reflects the full task hierarchy regardless of completion status.
- For nested hierarchies, the rollup runs bottom-up: each level is calculated from its immediate children first, then the result propagates upward through the tree.
has_subtasks_date_mismatchonly flags descendants that fall outside the parent’s range, so a parent with a wider range returnsfalse. Each boundary is checked separately: a descendant that starts before its parent is a mismatch, while a parent due date that is later than every descendant is just slack. Slack isn’t permanent – an explicit rollup can narrow the parent to fit its descendants.
Detect a date mismatch
Request has_subtasks_date_mismatch via opt_fields on a task read:
GET /tasks/{task_gid}?opt_fields=has_subtasks_date_mismatch
{
"data": {
"gid": "12345",
"resource_type": "task",
"start_on": "2026-03-02",
"due_on": "2026-03-13",
"has_subtasks_date_mismatch": true
}
}
Here, the flag is true because at least one descendant subtask starts before 2026-03-02 or is due after 2026-03-13.
Response fields
| Field | Type | Description |
|---|---|---|
has_subtasks_date_mismatch |
boolean | Whether one or more descendant subtasks have dates outside the task’s own date range. |
Roll up one task’s subtask tree
Send an empty request body. Requires the tasks:write OAuth scope and permission to edit the task’s scheduling fields (due_on, due_at, start_on, start_at).
POST /tasks/{task_gid}/rollup
{
"data": {
"gid": "1",
"resource_type": "job",
"resource_subtype": "rollup_task",
"status": "not_started"
}
}
A successful request returns a Job object with a 201 Created status code.
Calling this endpoint when has_subtasks_date_mismatch: false still creates a job, but it will not change the task’s due date.
Roll up an entire project
Send an empty request body. Requires the projects:write OAuth scope and permission to edit the task’s scheduling fields in the project (due_on, due_at, start_on, start_at).
POST /projects/{project_gid}/rollup
{
"data": {
"gid": "2",
"resource_type": "job",
"resource_subtype": "rollup_project",
"status": "not_started",
"dates_rollup_progress": {
"updated_tasks": 10,
"total_tasks": 22
}
}
}
A successful request returns a Job object with a 201 Created status code.
This endpoint considers all tasks in the project, including completed tasks. The rollup job runs only on tasks where has_subtasks_date_mismatch: true
Track job status
Poll GET /jobs/{job_gid} until status is succeeded or failed. For project rollup jobs, dates_rollup_progress is returned by default.
| Field | Type | Description |
|---|---|---|
dates_rollup_progress |
object | Object containing the progress of the rollup job. It may be empty (”dates_rollup_progress”: {}), before the job discovers tasks. |
updated_tasks |
integer | The number of tasks whose dates have been reconciled. |
total_tasks |
integer | The number of tasks discovered for reconciliation. May increase while the job runs; final once the job completes. |
Availability and errors
- If the task or project doesn’t exist or is inaccessible, the endpoint returns
404 Not Found. - If the caller cannot edit the required scheduling fields, the endpoint returns
403 Forbidden:
{
"errors": [
{
"error": "scheduling_field_restricted",
"message": "Cannot modify the following scheduling-related fields due to project permissions: due_on, due_at, start_on, start_at"
}
]
}
Why we’re making this change
A descendant subtask can be scheduled before its parent starts or after its parent is due. Integrations previously had to traverse the entire subtask hierarchy to detect these mismatches and update dates themselves. The new Task field and rollup endpoints let integrations detect and resolve the same scheduling inconsistencies now supported in the Asana web app.