SchedulingChanges#

A set of edits to a JsonProject: tasks, links, resources and assignments to add, update or remove, plus an optional baseline check. Send it as changes_json to apply or preview, or as changes of a candidate passed to evaluate. suggestAssignments returns one as changes.

type SchedulingChanges = {
  baselineId?: string;
  tasks?: { add?: TaskData[]; update?: TaskUpdate[]; remove?: Id[] };
  links?: { add?: LinkAdd[]; update?: LinkUpdate[]; remove?: Id[] };
  resources?: { add?: ResourceData[]; update?: ResourceUpdate[]; remove?: Id[] };
  assignments?: { add?: AssignmentData[]; update?: AssignmentUpdate[]; remove?: Id[] };
};

Fields#

Field Type Required Default Description
baselineId string | null no absent Baseline token the edits were made against. Absent or null skips the check. A token that doesn't name the project's current baseline fails the whole call with kind: "project", code: "stale-baseline", before any operation runs.
tasks bucket of TaskData / TaskUpdate | null no empty Tasks to add, update or remove.
links bucket of LinkAdd / LinkUpdate | null no empty Links to add, update or remove.
resources bucket of ResourceData / ResourceUpdate | null no empty Resources to add, update or remove.
assignments bucket of AssignmentData / AssignmentUpdate | null no empty Assignments to add, update or remove.

The field is spelled baselineId. Take the token from the latest result that carries one, such as the ScheduleResult of a solve.

There's no calendars field. Calendars can't be added or edited through a change set; that takes solve with full data. Updates can still point tasks and resources at existing calendars through calendar_id.

The change set and its buckets reject unknown fields: {"tasks": {"rename": []}} fails the whole call with parse. The records inside add and update ignore unknown fields. See Wire format.

Note

A priority outside 0..1000 or a malformed hour range fails the whole call with a validation error that has no path. In apply, this means no operation from that change set is applied.

Buckets#

Each of tasks, links, resources and assignments is an object with up to three lists. Any list can be omitted.

Field Type Description
add record array New records.
update update array Edits to existing records, each naming its record by id. In an update, an omitted field stays unchanged and null clears it; see Wire format.
remove Id[] Ids of records to remove.

When present, each list must be an array; null there is a parse error.

Bucket add update remove
tasks TaskData TaskUpdate task ids
links LinkAdd LinkUpdate link ids
resources ResourceData ResourceUpdate resource ids
assignments AssignmentData AssignmentUpdate assignment ids

Every list entry is one operation, named by its path: tasks.update[0], links.remove[2]. ApplyReport lists accepted and rejected operations by these paths.

Removing a task also removes its descendants and the links and assignments that use them. Removing a resource also removes its assignments. The removed ids are listed in ChangeEffects.

Operation order#

Operations run in a fixed order, not in the order the fields appear in the JSON. Buckets run in the order tasks, links, resources, assignments. Within a bucket:

Bucket Order
tasks remove, add, update
links remove, update, add
resources remove, add, update
assignments remove, update, add

Entries of one list run in array order. Because removals run first, an add can reuse an id removed in the same change set, and links and assignments can refer to tasks and resources added in it.

Rejected operations#

A malformed change set, such as a missing required field or a wrong JSON type, fails the whole call. An operation that decodes but doesn't fit the project is rejected on its own and listed in rejected of the ApplyReport:

Operation Rejected when
any remove No record of that kind has the id (unknown task id, unknown link id, ...).
any update No record of that kind has the id.
any add The id is already used by a record of that kind (duplicate task id, ...).
any add / update The resulting record fails the same validation as project data, such as an unknown calendar_id.
links.update, assignments.update A required field (source, target, task, resource, value) is set to null.

LinkAdd#

A new link in links.add. The fields mean the same as on LinkData, except that id is optional. Unknown fields are ignored.

Field Type Required Default Description
id Id | null no generated Id of the new link. Omitted or null: the first free id of the form $generated_link_1, $generated_link_2, and so on. Generated ids are listed in generatedLinks of ChangeEffects.
source Id yes - Id of the predecessor task.
target Id yes - Id of the successor task.
type string | number | null, see link type no "fs" "fs", "ss", "ff" or "sf"; also 0-3 and "0"-"3". null reads as "fs".
lag number | null no 0 Working time between the two ends, in lag_unit. null reads as 0.
lag_unit TimeUnit | null no config.duration_unit "minute", "hour" or "day".

An endpoint that names no task, or an unscheduled task, doesn't reject the operation. The link is added and listed in droppedLinks of ChangeEffects.

LinkUpdate#

An edit to one existing link in links.update. Unknown fields are ignored.

Field Type Required null Description
id Id yes - Id of the link to edit. The id itself can't change.
source Id no rejected New predecessor task.
target Id no rejected New successor task.
type string | number, see link type no resets to "fs" New link type.
lag number no resets to 0 New lag, in the link's lag unit.
lag_unit TimeUnit no clears it: lag is read in config.duration_unit New unit of lag for this link.

An omitted field stays unchanged. A new source or target that names no task, or an unscheduled task, doesn't reject the operation; the link is listed in droppedLinks.

ResourceUpdate#

An edit to one existing resource in resources.update. The fields mean the same as on ResourceData. Unknown fields are ignored.

Field Type Required null Description
id Id yes - Id of the resource to edit.
capacity number no clears it: config.default_resource_capacity applies New capacity.
calendar_id Id no clears it: the resource has no calendar of its own New calendar. Must name a calendar already in the project.

An omitted field stays unchanged. A calendar change can move the dates of tasks whose assignments work on that resource's calendar; see Resources and assignments.

AssignmentUpdate#

An edit to one existing assignment in assignments.update. The fields mean the same as on AssignmentData. Unknown fields are ignored.

Field Type Required null Description
id Id yes - Id of the assignment to edit. The id itself can't change.
task Id no rejected Moves the assignment to another task. task_id is accepted as an alias; when both are present, task wins.
resource Id no rejected Hands the assignment to another resource. resource_id is accepted as an alias; when both are present, resource wins.
value number no rejected New units booked.
offset number no clears it: the slice starts at the task start New start of the slice, as worked time from the task start.
duration number no clears it: the slice runs to the task end New worked time of the slice.

An omitted field stays unchanged. Changes to offset and duration never move task dates.

Used by#

Example#

Move one task, remove another, link two tasks and raise a resource's capacity, checked against the current baseline:

{
  "baselineId": "1-b0605af8cba3d7c9",
  "tasks": {
    "update": [{ "id": "design", "start_date": "2026-08-12 08:00" }],
    "remove": ["draft"]
  },
  "links": {
    "add": [{ "source": "design", "target": "build", "type": "fs" }]
  },
  "resources": {
    "update": [{ "id": "team", "capacity": 2 }]
  },
  "assignments": {
    "update": [{ "id": "a1", "offset": null, "duration": 3 }]
  }
}