> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nmbr.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk Work Assignment Operations

Bulk work assignment operations create or update many work assignments in one API call. They follow the same shape as [Bulk Line Item Operations](./bulk-line-item-operations) and [Bulk Recurrence Operations](./bulk-recurrence-operations), with two differences:

* **Create** selects *payees* (employees and contractors) and creates one work assignment per payee on a pay schedule.
* **Update** selects *work assignments* directly, within a single business entity.

There is no bulk delete for work assignments.

## Asynchronous Execution

Bulk work assignment operations are asynchronous. Every bulk endpoint returns an [`async_task`](/api-reference/async-tasks/retrieve-an-async-task) handle that you use to track completion and retrieve the affected entities.

The task **may or may not have completed** by the time you receive the response. `data.status` could be `processing` or `completed`. **Partners must always check `data.status` and not assume the work has finished.**

You have two ways to observe completion:

* **Poll** the URL in `links.self` on the response until `data.status` is `completed` (or `error`).
* **Subscribe** to the [`async_task_completed`](/api/overview/webhook-structure) webhook event, which fires when the task finishes, whether it succeeded or failed.

The webhook carries no status. Fetch the task to see how it ended: `data.status` is `completed` on success and `error` on failure. See [Failed Tasks](/api/bulk-and-batch-operations/bulk-and-batch-operations#failed-tasks).

`data.results` contains one entry per affected work assignment, with only the `id` and `object`. To retrieve full work assignment bodies, follow up with a list query (filtered by the returned IDs) or fetch individual work assignments by ID.

Note: scope endpoints (`/bulk/*/scope`) are previews with no side effects and are synchronous - they return `200 OK` with the inline list of matched entities.

## Bulk Create Work Assignments

Nmbr's API allows you to create a work assignment for select payees on a single pay schedule. This endpoint is useful when you need to add a group of employees or contractors to a pay schedule in one API call, such as onboarding a new team onto a bi-weekly schedule.

### Endpoint

`POST /work_assignments/bulk/create`

### Request

```json theme={null}
{
  "payees": {
    "include": "all" | criteria object,
    "exclude": criteria object (optional)
  },
  "data": {
    "pay_schedule_id": ULID,
    ...other work assignment properties...
  }
}
```

#### Request Properties

| Property         | Type                       | Required | Description                                                                  |
| ---------------- | -------------------------- | -------- | ---------------------------------------------------------------------------- |
| `payees.include` | criteria object or `"all"` | Yes      | Criteria for selecting payees to include                                     |
| `payees.exclude` | criteria object            | No       | Criteria for selecting payees to exclude                                     |
| `data`           | object                     | Yes      | The properties of the work assignment to create, including `pay_schedule_id` |

The work assignment's business entity is taken from the pay schedule, so there is no top-level `business_entity_id` on create.

#### Payee Criteria Objects

`include` and `exclude` can be objects with one or more of the following properties:

* `ids`: Array of employee/contractor IDs to include or exclude
* `payee_type`: `"employee"` or `"contractor"`
* `payee_names`: Name search (partial match)
* `archived`: `true` to select archived payees, `false` (default) to select active payees

When you combine properties, they apply together. For example, `{ "payee_type": "employee", "archived": false }` selects active employees only.

`include` can also be the string `"all"` to include all payees.

#### Data Properties

The `data` object contains the work assignment properties to apply to each created work assignment. For example:

| Property          | Description                                                                                               |
| ----------------- | --------------------------------------------------------------------------------------------------------- |
| `pay_schedule_id` | (Required) The pay schedule to create the work assignment on. Sets the work assignment's business entity. |
| `title`           | Label for the work assignment                                                                             |
| `is_primary`      | Whether this is the payee's primary work assignment                                                       |
| `pay_split_id`    | ID of a pay split to apply to the work assignment                                                         |
| `external_ref`    | Your external identifier for the work assignment                                                          |
| `archived_at`     | Date to archive the work assignment (`YYYY-MM-DD`)                                                        |
| `tax_properties`  | Inline tax properties to set on the work assignment                                                       |
| `tag_assignment`  | Tag allocations for the work assignment                                                                   |

The payee for each work assignment comes from your selection. Don't set `employee_id` or `contractor_id` in `data`. These properties are documented in more detail in the API reference for work assignments.

### Response

On success, the operation returns `202 Accepted` with an [`async_task`](/api-reference/async-tasks/retrieve-an-async-task) handle. See [Asynchronous Execution](#asynchronous-execution) for how to track completion. **⚠️ Partners must treat any 200-level response as success. ⚠️**

For example, the response might look like:

```json theme={null}
{
  "id": "asnct_01KS0G8Z2YD3T9KQNFW1XEA7HB",
  "object": "async_task",
  "data": {
    "type": "bulk_create",
    "status": "processing",
    "completed_at": null,
    "results": [],
    "created_at": "2026-05-19T16:14:32Z",
    "updated_at": "2026-05-19T16:14:32Z"
  },
  "links": {
    "self": "/async_tasks/asnct_01KS0G8Z2YD3T9KQNFW1XEA7HB"
  }
}
```

Once the task completes, `data.results` will contain one entry per created work assignment:

```json theme={null}
{
  "id": "asnct_01KS0G8Z2YD3T9KQNFW1XEA7HB",
  "object": "async_task",
  "data": {
    "type": "bulk_create",
    "status": "completed",
    "completed_at": "2026-05-19T16:14:35Z",
    "results": [
      { "id": "wrkas_01J8KXC9R4MQVW2FXZN7Y5H3B8", "object": "work_assignment" },
      { "id": "wrkas_01KBMZDVV9G7713DJRYP9RJFTP", "object": "work_assignment" }
    ],
    "created_at": "2026-05-19T16:14:32Z",
    "updated_at": "2026-05-19T16:14:35Z"
  },
  "links": {
    "self": "/async_tasks/asnct_01KS0G8Z2YD3T9KQNFW1XEA7HB"
  }
}
```

On failure, the operation will return `422 Unprocessable Entity` with standard validation messages.

### Notes

* The same work assignment properties (other than the payee) are applied to every created work assignment.
* The business entity is taken from the pay schedule. You don't pass a `business_entity_id`.
* Payees that already have a work assignment on that pay schedule are skipped. There is one work assignment per pay schedule per payee. Skipped payees won't appear in `data.results`.
* Each new work assignment generates its draft pay stubs on upcoming draft payrolls for that pay schedule, the same as creating a single work assignment.
* Validation runs against every selected payee before any work assignment is created. If validation fails, no work assignments are created.
* Invalid payee IDs in the `include.ids` or `exclude.ids` arrays are silently ignored and won't cause an error.
* When both `include` and `exclude` criteria are provided, exclusions are applied after inclusions.

### Examples

#### Create work assignments for all employees on a pay schedule

`POST /work_assignments/bulk/create`

```json theme={null}
{
  "payees": {
    "include": {
      "payee_type": "employee"
    }
  },
  "data": {
    "pay_schedule_id": "paysc_01J8KX9R2FMQVW3TNZH5Y7B4C6"
  }
}
```

#### Create work assignments for specific payees

`POST /work_assignments/bulk/create`

```json theme={null}
{
  "payees": {
    "include": {
      "ids": [
        "emp_01J8KXB4N6RQWM2FVZH9Y3T5C8",
        "emp_01J8KXB7P2MQVW4RXZN6Y8H3F1",
        "cntct_01J8KXBA3TWQNM7FXZR9Y2V5C4"
      ]
    }
  },
  "data": {
    "pay_schedule_id": "paysc_01J8KX9R2FMQVW3TNZH5Y7B4C6",
    "title": "Engineering",
    "is_primary": true
  }
}
```

#### Create work assignments for all payees, excluding specific payees

`POST /work_assignments/bulk/create`

```json theme={null}
{
  "payees": {
    "include": "all",
    "exclude": {
      "ids": ["emp_01J8KXB4N6RQWM2FVZH9Y3T5C8"]
    }
  },
  "data": {
    "pay_schedule_id": "paysc_01J8KX9R2FMQVW3TNZH5Y7B4C6"
  }
}
```

#### Create work assignments with a pay split for all contractors

`POST /work_assignments/bulk/create`

```json theme={null}
{
  "payees": {
    "include": {
      "payee_type": "contractor"
    }
  },
  "data": {
    "pay_schedule_id": "paysc_01J8KX9R2FMQVW3TNZH5Y7B4C6",
    "pay_split_id": "paysp_01J8KXD3M7RQWN2FXZV9Y4H6B1"
  }
}
```

## Bulk Create Work Assignments Scope

The create scope endpoint previews which payees will receive a new work assignment from a bulk create operation. It accepts the same request body as the bulk create endpoint, but instead of creating work assignments, it returns the payees that match the criteria.

Because the work assignments don't exist yet, this endpoint returns *payees*, not work assignments. Payees that already have a work assignment on the target pay schedule are excluded, matching the create behavior.

This is useful for confirming which payees a bulk create will affect before executing it.

### Endpoint

`POST /work_assignments/bulk/create/scope`

### Request

The request body is the same as the [bulk create](#bulk-create-work-assignments) endpoint.

### Response

On success, the operation will return `200 OK` with an array of the payees that the bulk create would create work assignments for. The array can contain both employees and contractors:

```json theme={null}
{
  "data": [
    {
      "id": "emp_01J8KXB4N6RQWM2FVZH9Y3T5C8",
      "data": {
        ...employee or contractor properties...
      }
    },
    ...
  ]
}
```

## Bulk Update Work Assignments

Nmbr's API allows you to update select work assignments within a single business entity. This endpoint is useful when you need to update the same property on a group of work assignments in one API call, such as moving a team onto a pay split or archiving a set of work assignments.

### Endpoint

`POST /work_assignments/bulk/update`

### Request

```json theme={null}
{
  "business_entity_id": ULID,
  "work_assignments": {
    "include": "all" | criteria object,
    "exclude": criteria object (optional)
  },
  "data": {
    ...properties to update...
  }
}
```

#### Request Properties

| Property                   | Type                       | Required | Description                                               |
| -------------------------- | -------------------------- | -------- | --------------------------------------------------------- |
| `business_entity_id`       | ULID                       | Yes      | ID of the business entity containing the work assignments |
| `work_assignments.include` | criteria object or `"all"` | Yes      | Criteria for selecting work assignments to include        |
| `work_assignments.exclude` | criteria object            | No       | Criteria for selecting work assignments to exclude        |
| `data`                     | object                     | Yes      | The properties to update on the matching work assignments |

#### Work Assignment Criteria Objects

`include` and `exclude` can be objects with one or more of the following properties:

* `ids`: Array of work assignment IDs to include or exclude
* `payee_type`: `"employee"` or `"contractor"`
* `pay_schedule_id`: ID of the pay schedule to include or exclude
* `archived`: `true` to select archived work assignments, `false` (default) to select active ones
* `payee_names`: Name search (partial match)

When you combine properties, they apply together.

`include` can also be the string `"all"` to include all work assignments.

#### Data Properties

The `data` object contains the work assignment properties to update. For example:

| Property               | Description                                                                                 |
| ---------------------- | ------------------------------------------------------------------------------------------- |
| `title`                | Label for the work assignment                                                               |
| `is_primary`           | Whether this is the payee's primary work assignment                                         |
| `pay_split_id`         | ID of a pay split to apply to the work assignment                                           |
| `external_ref`         | Your external identifier for the work assignment                                            |
| `archived_at`          | Date to archive the work assignment (`YYYY-MM-DD`)                                          |
| `tag_assignment`       | Replaces the work assignment's tag allocations                                              |
| `tag_assignment_patch` | Additively modifies the existing tag allocations. Mutually exclusive with `tag_assignment`. |

You cannot change a work assignment's business entity, pay schedule, or payee. Sending `business_entity_id`, `pay_schedule_id`, `employee_id`, or `contractor_id` in `data` fails validation. These properties are documented in more detail in the API reference for work assignments.

### Response

On success, the operation returns `202 Accepted` with an [`async_task`](/api-reference/async-tasks/retrieve-an-async-task) handle whose `data.results` enumerates the updated work assignments. See [Asynchronous Execution](#asynchronous-execution) for how to track completion and [Bulk Create Work Assignments › Response](#response) for an example response shape. `data.type` will be `bulk_update`. **⚠️ Partners must treat any 200-level response as success. ⚠️**

On failure, the operation will return `422 Unprocessable Entity` with standard validation messages. If any matched work assignment fails per-model validation, the entire request fails and no work assignments are updated.

### Notes

* The same update properties are applied to all selected work assignments.
* The operation only affects work assignments within the specified business entity.
* You cannot change a work assignment's business entity, pay schedule, or payee.
* Validation is all-or-nothing. If any matched work assignment fails validation, the entire request fails and no work assignments are updated.
* Invalid work assignment IDs in the `include.ids` or `exclude.ids` arrays are silently ignored and won't cause an error.
* When both `include` and `exclude` criteria are provided, exclusions are applied after inclusions.

### Examples

#### Update the title on all work assignments

`POST /work_assignments/bulk/update`

```json theme={null}
{
  "business_entity_id": "be_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "work_assignments": {
    "include": "all"
  },
  "data": {
    "title": "Engineering"
  }
}
```

#### Archive work assignments on a specific pay schedule

`POST /work_assignments/bulk/update`

```json theme={null}
{
  "business_entity_id": "be_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "work_assignments": {
    "include": {
      "pay_schedule_id": "paysc_01J8KX9R2FMQVW3TNZH5Y7B4C6"
    }
  },
  "data": {
    "archived_at": "2026-06-01"
  }
}
```

#### Update a pay split for all employees, excluding specific work assignments

`POST /work_assignments/bulk/update`

```json theme={null}
{
  "business_entity_id": "be_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "work_assignments": {
    "include": {
      "payee_type": "employee"
    },
    "exclude": {
      "ids": ["wrkas_01J8KXB4N6RQWM2FVZH9Y3T5C8"]
    }
  },
  "data": {
    "pay_split_id": "paysp_01J8KXD3M7RQWN2FXZV9Y4H6B1"
  }
}
```

#### Add a tag to all work assignments without replacing existing allocations

`POST /work_assignments/bulk/update`

```json theme={null}
{
  "business_entity_id": "be_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "work_assignments": {
    "include": "all"
  },
  "data": {
    "tag_assignment_patch": {
      "add_tags": ["tag_01J8KXF2N4MQRW3VXZH7Y9B5C8"]
    }
  }
}
```

## Bulk Update Work Assignments Scope

The update scope endpoint previews which work assignments will be updated by a bulk update operation. It accepts the same request body as the bulk update endpoint, but instead of updating work assignments, it returns the work assignments that match the criteria.

### Endpoint

`POST /work_assignments/bulk/update/scope`

### Request

The request body is the same as the [bulk update](#bulk-update-work-assignments) endpoint.

### Response

On success, the operation will return `200 OK` with an array of the work assignments that would be updated:

```json theme={null}
{
  "data": [
    {
      "id": "wrkas_01J8KXB4N6RQWM2FVZH9Y3T5C8",
      "data": {
        ...work assignment properties...
      }
    },
    ...
  ]
}
```
