[New] Subtask Date Rollups API support

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_mismatch field 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}/rollup starts an asynchronous job that updates dates across the task’s subtask tree.
  • Reconcile a project: POST /projects/{project_gid}/rollup starts an asynchronous job across the project.
  • Track progress: Poll GET /jobs/{job_gid}. Project rollup jobs return progress via dates_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 earliest start_on / start_at among its subtasks
  • due_on / due_at = the latest due_on / due_at among 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_on set while its subtasks have both start_on and due_on, rollup may adjust the parent’s due_on, but start_on stays unset. If the parent has no scheduling fields at all, rollup leaves the task unchanged, and has_subtasks_date_mismatch returns false. 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_mismatch only flags descendants that fall outside the parent’s range, so a parent with a wider range returns false. 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.

Resources

2 Likes

@Dominik_Brdak, just so I understand this clearly. Are you saying that the Asana API can now flag parent tasks whose dates don’t cover their subtasks? It can auto-adjust their dates to the earliest subtask start and latest subtask due date, correct?

Hi @Karl_LEASuccess, that’s correct!

Instead of manually calculating the schedule on your side and making multiple GET and PUT requests to adjust task dates, you can now use one of the new endpoints to align the parent task’s dates with its subtasks in a single request, or use the new has_subtasks_date_mismatch field to identify the inconsistency in the task schedule.

Let me know if you have any other questions or if I can clarify anything!

1 Like