[Canonical page](<https://docs.dhtmlx.com/planning-engine/js/api/types/scheduling-changes/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# SchedulingChanges

One set of edits to a live [`Project`](<https://docs.dhtmlx.com/planning-engine/js/api/project.md>): tasks, links, resources and assignments to add, update or remove. Build it as a plain object and pass it to [`Project#apply`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md>) or [`Project#preview`](<https://docs.dhtmlx.com/planning-engine/js/api/project-preview.md>), or put it in a [`Candidate`](<https://docs.dhtmlx.com/planning-engine/js/api/project-evaluate.md#candidate>). [`Project#suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/js/api/project-suggest-assignments.md>) returns one in `result.changes`.

## Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `baselineId` | `string` | none | Baseline token the edits were made against. Omitted: no check. Set: it must name the project's current baseline, or the call throws [`ProjectError`](<https://docs.dhtmlx.com/planning-engine/js/api/types/errors.md>) `"stale-baseline"`. |
| `tasks` | bucket of [`TaskData`](<https://docs.dhtmlx.com/planning-engine/js/api/types/task-data.md>) / [`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/js/api/types/task-update.md>) | empty | Tasks to add, update or remove by id. |
| `links` | bucket of [`LinkAdd`](<https://docs.dhtmlx.com/planning-engine/js/api/types/common.md#linkadd>) / [`LinkUpdate`](<https://docs.dhtmlx.com/planning-engine/js/api/types/common.md#linkupdate-resourceupdate-assignmentupdate>) | empty | Links to add, update or remove by id. A `LinkAdd` without an `id` gets a generated one. |
| `resources` | bucket of [`ResourceData`](<https://docs.dhtmlx.com/planning-engine/js/api/types/common.md#resourcedata>) / [`ResourceUpdate`](<https://docs.dhtmlx.com/planning-engine/js/api/types/common.md#linkupdate-resourceupdate-assignmentupdate>) | empty | Resources to add, update or remove by id. |
| `assignments` | bucket of [`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/js/api/types/assignment-data.md>) / [`AssignmentUpdate`](<https://docs.dhtmlx.com/planning-engine/js/api/types/common.md#linkupdate-resourceupdate-assignmentupdate>) | empty | Assignments to add, update or remove by id. |

Each bucket is an object with three optional arrays:

| Field | Type | Default | Description |
|---|---|---|---|
| `add` | record array | `[]` | New records, in the bucket's add type. |
| `update` | record array | `[]` | Partial records: `id` is required, every other field is optional. |
| `remove` | [`Id`](<https://docs.dhtmlx.com/planning-engine/js/api/types/common.md#id>)`[]` | `[]` | Ids of the records to remove. |

A bucket set to `null` reads as empty. `null` in place of one of its arrays is a parse error. Unknown keys on the change set or on a bucket throw an [`InputError`](<https://docs.dhtmlx.com/planning-engine/js/api/types/errors.md>); unknown fields inside the records are ignored, so objects with extra UI fields can be passed as they are.

There's no calendars bucket. Calendars change only through a full [`solve(data)`](<https://docs.dhtmlx.com/planning-engine/js/api/project-solve.md>).

Take the token for `baselineId` from the latest solve result ([`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/js/api/types/schedule-result.md>) `baselineId`). Tokens are opaque: don't compare them across runs.

## Operation order

Operations run in a fixed order, not in the order the keys appear. Kinds run in the order tasks, links, resources, assignments. Within a kind:

| Kind | Order |
|---|---|
| `tasks` | `remove`, `add`, `update` |
| `links` | `remove`, `update`, `add` |
| `resources` | `remove`, `add`, `update` |
| `assignments` | `remove`, `update`, `add` |

Within an array, records run in array order. Each operation is named by its bucket and index, such as `"tasks.update[0]"`, in the `path` of the [`ApplyReport`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md#applyreport>) entries.

## Used by

- [`Project#apply`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md>): `changes` is committed to the accepted state
- [`Project#preview`](<https://docs.dhtmlx.com/planning-engine/js/api/project-preview.md>): `changes` is scheduled on a copy of the baseline
- [`Project#evaluate`](<https://docs.dhtmlx.com/planning-engine/js/api/project-evaluate.md>): each [`Candidate`](<https://docs.dhtmlx.com/planning-engine/js/api/project-evaluate.md#candidate>) carries one as `changes`
- [`Project#suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/js/api/project-suggest-assignments.md>): returns one as `result.changes`, ready for `apply`

## Example

Move task 1, link it to task 2 and check the edit against the current baseline.

```js
// solved: the result of the latest project.solve(...)
const changes = {
  baselineId: solved.baselineId,
  tasks: { update: [{ id: 1, start_date: "2026-08-12 08:00" }] },
  links: { add: [{ source: 1, target: 2, type: "fs" }] },
};
```

## Related

- [`Project#apply`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md>) - committing a change set
- [`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/js/api/types/task-update.md>) - the `tasks.update` records
- [`ApplyReport`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md#applyreport>) - what `apply` accepted and rejected
- [Editing a project](<https://docs.dhtmlx.com/planning-engine/js/live-projects/editing-a-project.md>) - change sets, applying and rescheduling
- [Previewing Changes](<https://docs.dhtmlx.com/planning-engine/js/live-projects/previewing-changes.md>) - previewing an edit before committing it
