> ## 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 Line Item Operations

## Asynchronous Execution

Bulk line item 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 line item — only the `id` and `object`. To retrieve full line item bodies, follow up with a [list query](/api-reference/earning-line-items/list-earning-line-items) (filtered by the returned IDs) or fetch individual entities 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 Line Items

Nmbr's API allows you to create a line item on select pay stubs within a single payroll. This endpoint is useful when you need to create line items on one or more pay stubs in one API call, such as applying a company-wide bonus to a group of employees.

### Endpoint

`POST /<type>_line_items/bulk/create`

`<type>` can be one of the following types:

* `allowance`
* `deduction`
* `earning`
* `employee_benefit`
* `employer_benefit`
* `reimbursement`

### Request

```json theme={null}
{
  "payroll_id": ULID,
  "pay_stubs": {
    "include": "all" | criteria object,
    "exclude": criteria object (optional)
  },
  "data": {
    ...type-specific line item properties...
  }
}
```

#### Request Properties

| Property            | Type                       | Required | Description                                 |
| ------------------- | -------------------------- | -------- | ------------------------------------------- |
| `payroll_id`        | ULID                       | Yes      | ID of the payroll containing the pay stubs  |
| `pay_stubs.include` | criteria object or `"all"` | Yes      | Criteria for selecting pay stubs to include |
| `pay_stubs.exclude` | criteria object            | No       | Criteria for selecting pay stubs to exclude |
| `data`              | object                     | Yes      | The properties of the line item to create   |

The `data` object contains any line item properties specific to the type of line item being created. For example, for earning line items:

| Property                       | Description                                               |
| ------------------------------ | --------------------------------------------------------- |
| `earning_type`                 | Type of earning (e.g., `"wage"`, `"bonus"`, `"overtime"`) |
| `business_preset_id`           | ID of a business preset to use as template                |
| `custom_amount`                | Amount for the line item                                  |
| `custom_hours`                 | Hours for the line item                                   |
| `title`                        | Title for the line item                                   |
| `expense_accounting_code_id`   | ID of the expense accounting code                         |
| `liability_accounting_code_id` | ID of the liability accounting code                       |

These properties are documented in more detail in the API reference for each line item type.

#### Request Criteria Objects

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

* `ids`: Array of pay stub IDs to include
* `work_assignment_ids`: Array of work assignment IDs. Selects the pay stubs for those work assignments
* `payee_type`: `"employee"` or `"contractor"`

`include` can also be the string `"all"` to include all pay stubs.

### 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 line item:

```json theme={null}
{
  "id": "asnct_01KS0G8Z2YD3T9KQNFW1XEA7HB",
  "object": "async_task",
  "data": {
    "type": "bulk_create",
    "status": "completed",
    "completed_at": "2026-05-19T16:14:35Z",
    "results": [
      {
        "id": "ernli_01J8KXC9R4MQVW2FXZN7Y5H3B8",
        "object": "earning_line_item"
      },
      {
        "id": "ernli_01KBMZDVV9G7713DJRYP9RJFTP",
        "object": "earning_line_item"
      }
    ],
    "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 line item properties will be applied to all selected pay stubs.
* When using a `business_preset_id`, properties must either be omitted or match the preset's values.
* The operation only affects pay stubs within the specified payroll. Pay stubs in other payrolls will not be affected.
* Invalid pay stub 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.
* The payroll's totals are automatically recalculated after the bulk creation.
* The payroll must be in draft status.

### Examples

#### Create an earning line item on all pay stubs

`POST /earning_line_items/bulk/create`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "data": {
    "earning_type": "bonus_discretionary",
    "custom_amount": 500.0,
    "title": "Year-end Bonus"
  }
}
```

#### Create earning line items using a business preset

`POST /earning_line_items/bulk/create`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "data": {
    "business_preset_id": "rps_01J8KXD3M7RQWN2FXZV9Y4H6B1",
    "custom_amount": 100.0
  }
}
```

#### Create earning line items for specific pay stubs

`POST /earning_line_items/bulk/create`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": {
      "ids": [
        "payst_01J8KXB4N6RQWM2FVZH9Y3T5C8",
        "payst_01J8KXB7P2MQVW4RXZN6Y8H3F1",
        "payst_01J8KXBA3TWQNM7FXZR9Y2V5C4"
      ]
    }
  },
  "data": {
    "earning_type": "wage",
    "custom_amount": 1000.0,
    "title": "Special Assignment Pay"
  }
}
```

#### Create earning line items on all employee pay stubs, excluding specific pay stubs (and implicitly excluding contractor pay stubs)

`POST /earning_line_items/bulk/create`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": {
      "payee_type": "employee"
    },
    "exclude": {
      "ids": ["payst_01J8KXB4N6RQWM2FVZH9Y3T5C8"]
    }
  },
  "data": {
    "earning_type": "bonus_discretionary",
    "custom_amount": 250.0,
    "title": "Appreciation Bonus",
    "expense_accounting_code_id": "accod_01J8KXF2N4MQRW3VXZH7Y9B5C8",
    "liability_accounting_code_id": "accod_01J8KXF5P6RQNW4MXZV8Y2H7F1"
  }
}
```

#### Create earning line items for all pay stubs except contractors

`POST /earning_line_items/bulk/create`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all",
    "exclude": {
      "payee_type": "contractor"
    }
  },
  "data": {
    "earning_type": "bonus_discretionary",
    "custom_amount": 200.0,
    "title": "Christmas Bonus"
  }
}
```

## Bulk Create Line Items Scope

The create scope endpoint previews which pay stubs will have new line items created on them by a bulk create operation. It accepts the same request body as the bulk create endpoint, but instead of creating line items, it returns the pay stubs that match the criteria.

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

### Endpoint

`POST /<type>_line_items/bulk/create/scope`

`<type>` can be one of the following types:

* `allowance`
* `deduction`
* `earning`
* `employee_benefit`
* `employer_benefit`
* `reimbursement`

### Request

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

### Response

On success, the operation will return `200 OK` with an array of pay stubs that the bulk create would create line items on:

```json theme={null}
{
  "data": [
    {
      "id": "payst_01J8KXB4N6RQWM2FVZH9Y3T5C8",
      "data": {
        ...pay stub properties...
      }
    },
    ...
  ]
}
```

## Bulk Update Line Items

Nmbr's API allows you to update all line items of a single type on select pay stubs within a single payroll. This endpoint is useful when you need to update the same property on one or more line items in one API call, such as changing the amount or accounting code on a group of line items.

### Endpoint

`POST /<type>_line_items/bulk/update`

`<type>` can be one of the following types:

* `allowance`
* `deduction`
* `earning`
* `employee_benefit`
* `employer_benefit`
* `reimbursement`

### Request

```json theme={null}
{
  "payroll_id": "string",
  "pay_stubs": {
    "include": "all" | criteria object,
    "exclude": criteria object (optional)
  },
  "business_presets": {
    "include": { "ids": [...] },
    "exclude": { "ids": [...] }
  },
  "expense_accounting_codes": {
    "include": { "ids": [...] },
    "exclude": { "ids": [...] }
  },
  "liability_accounting_codes": {
    "include": { "ids": [...] },
    "exclude": { "ids": [...] }
  },
  "data": {
    ...properties to update...
  }
}
```

#### Request Properties

| Property                                 | Type                       | Required | Description                                                                                                                               |
| ---------------------------------------- | -------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `payroll_id`                             | ULID                       | Yes      | ID of the payroll containing the pay stubs                                                                                                |
| `pay_stubs.include`                      | criteria object or `"all"` | Yes      | Criteria for selecting pay stubs to include                                                                                               |
| `pay_stubs.exclude`                      | criteria object            | No       | Criteria for selecting pay stubs to exclude                                                                                               |
| `business_presets.include.ids`           | array of ULIDs or `null`   | No       | Only update line items with one of these business preset IDs. Use `null` to match line items with no business preset.                     |
| `business_presets.exclude.ids`           | array of ULIDs or `null`   | No       | Exclude line items with one of these business preset IDs. Use `null` to exclude line items with no business preset.                       |
| `expense_accounting_codes.include.ids`   | array of ULIDs or `null`   | No       | Only update line items with one of these expense accounting code IDs. Use `null` to match line items with no expense accounting code.     |
| `expense_accounting_codes.exclude.ids`   | array of ULIDs or `null`   | No       | Exclude line items with one of these expense accounting code IDs. Use `null` to exclude line items with no expense accounting code.       |
| `liability_accounting_codes.include.ids` | array of ULIDs or `null`   | No       | Only update line items with one of these liability accounting code IDs. Use `null` to match line items with no liability accounting code. |
| `liability_accounting_codes.exclude.ids` | array of ULIDs or `null`   | No       | Exclude line items with one of these liability accounting code IDs. Use `null` to exclude line items with no liability accounting code.   |
| `data`                                   | object                     | Yes      | The properties to update on the matching line items                                                                                       |

The `data` object contains any line item properties to update. These are the same properties accepted by the single-resource update endpoint for each line item type, and are documented in the API reference for each type.

#### Pay Stub Criteria Objects

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

* `ids`: Array of pay stub IDs to include or exclude
* `work_assignment_ids`: Array of work assignment IDs. Selects the pay stubs for those work assignments
* `payee_type`: `"employee"` or `"contractor"`

`include` can also be the string `"all"` to include all pay stubs.

### 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 line items. See [Asynchronous Execution](#asynchronous-execution) for how to track completion and [Bulk Create Line Items › 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 line item fails per-model validation, the entire request fails and no line items are updated.

### Notes

* The same update properties will be applied to all selected line items.
* The operation only affects custom line items. Managed line items will not be affected.
* The payroll must be in draft status.
* The payroll's totals are automatically recalculated after the bulk update.
* The `pay_stubs` criteria select which pay stubs to look under. The `business_presets`, `expense_accounting_codes`, and `liability_accounting_codes` criteria further filter which line items under those pay stubs are updated.

### Examples

#### Update the amount on all earning line items

`POST /earning_line_items/bulk/update`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "data": {
    "custom_amount": 500.0
  }
}
```

#### Update the accounting code on all earning line items with a specific business preset

`POST /earning_line_items/bulk/update`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "business_presets": {
    "include": {
      "ids": ["rps_01J8KXD3M7RQWN2FXZV9Y4H6B1"]
    }
  },
  "data": {
    "expense_accounting_code_id": "accod_01J8KXF2N4MQRW3VXZH7Y9B5C8"
  }
}
```

#### Update earning line items that have no business preset

`POST /earning_line_items/bulk/update`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "business_presets": {
    "include": {
      "ids": [null]
    }
  },
  "data": {
    "custom_amount": 500.0
  }
}
```

## Bulk Update Line Items Scope

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

### Endpoint

`POST /<type>_line_items/bulk/update/scope`

`<type>` can be one of the following types:

* `allowance`
* `deduction`
* `earning`
* `employee_benefit`
* `employer_benefit`
* `reimbursement`

### Request

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

### Response

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

```json theme={null}
{
  "data": [
    {
      "id": "ernli_01J8KXC9R4MQVW2FXZN7Y5H3B8",
      "data": {
        ...line item properties...
      }
    },
    ...
  ]
}
```

### Notes

* Only custom line items are returned. Managed line items are excluded, matching the behavior of the bulk update operation.

## Bulk Delete Line Items

Nmbr's API allows you to delete all line items of a single type on select pay stubs within a single payroll. This endpoint is useful when you need to remove line items on one or more pay stubs in one API call.

**Important:** This operation deletes ALL line items of the specified type on the pay stubs, not specific line items. If you want to delete specific line items, you should use the batch delete line items endpoints instead.

### Endpoint

`POST /<type>_line_items/bulk/delete`

`<type>` can be one of the following types:

* `allowance`
* `deduction`
* `earning`
* `employee_benefit`
* `employer_benefit`
* `reimbursement`

### Request

```json theme={null}
{
  "payroll_id": "string",
  "pay_stubs": {
    "include": "all" | criteria object,
    "exclude": criteria object (optional)
  },
  "business_presets": {
    "include": { "ids": [...] },
    "exclude": { "ids": [...] }
  },
  "expense_accounting_codes": {
    "include": { "ids": [...] },
    "exclude": { "ids": [...] }
  },
  "liability_accounting_codes": {
    "include": { "ids": [...] },
    "exclude": { "ids": [...] }
  }
}
```

#### Request Properties

| Property                                 | Type                       | Required | Description                                                                                                                               |
| ---------------------------------------- | -------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `payroll_id`                             | ULID                       | Yes      | ID of the payroll containing the pay stubs                                                                                                |
| `pay_stubs.include`                      | criteria object or `"all"` | Yes      | Criteria for selecting pay stubs to include                                                                                               |
| `pay_stubs.exclude`                      | criteria object            | No       | Criteria for selecting pay stubs to exclude                                                                                               |
| `business_presets.include.ids`           | array of ULIDs or `null`   | No       | Only delete line items with one of these business preset IDs. Use `null` to match line items with no business preset.                     |
| `business_presets.exclude.ids`           | array of ULIDs or `null`   | No       | Exclude line items with one of these business preset IDs. Use `null` to exclude line items with no business preset.                       |
| `expense_accounting_codes.include.ids`   | array of ULIDs or `null`   | No       | Only delete line items with one of these expense accounting code IDs. Use `null` to match line items with no expense accounting code.     |
| `expense_accounting_codes.exclude.ids`   | array of ULIDs or `null`   | No       | Exclude line items with one of these expense accounting code IDs. Use `null` to exclude line items with no expense accounting code.       |
| `liability_accounting_codes.include.ids` | array of ULIDs or `null`   | No       | Only delete line items with one of these liability accounting code IDs. Use `null` to match line items with no liability accounting code. |
| `liability_accounting_codes.exclude.ids` | array of ULIDs or `null`   | No       | Exclude line items with one of these liability accounting code IDs. Use `null` to exclude line items with no liability accounting code.   |

#### Pay Stub Criteria Objects

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

* `ids`: Array of pay stub IDs to include or exclude
* `work_assignment_ids`: Array of work assignment IDs. Selects the pay stubs for those work assignments
* `payee_type`: `"employee"` or `"contractor"`

`include` can also be the string `"all"` to include all pay stubs.

### 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 deleted line items (still surfaced by ID — the records soft-delete and remain queryable). See [Asynchronous Execution](#asynchronous-execution) for how to track completion and [Bulk Create Line Items › Response](#response) for an example response shape — `data.type` will be `bulk_delete`. **⚠️ Partners must treat any 200-level response as success. ⚠️**

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

### Notes

* The operation only affects pay stubs within the specified payroll. Pay stubs in other payrolls will not be affected.
* The operation only affects custom line items. Managed line items (e.g. earning line items created by statutory holidays or automatic vacation payouts; statutory withholding line items) will not be affected.
* Invalid pay stub 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.
* The payroll's totals are automatically recalculated after the bulk deletion.
* The payroll must be draft.
* The `pay_stubs` criteria select which pay stubs to look under. The `business_presets`, `expense_accounting_codes`, and `liability_accounting_codes` criteria further filter which line items under those pay stubs are deleted.

### Examples

#### Delete all earning line items on all pay stubs in a payroll

`POST /earning_line_items/bulk/delete`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  }
}
```

#### Delete earning line items on specific pay stubs

`POST /earning_line_items/bulk/delete`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": {
      "ids": [
        "payst_01J8KXB4N6RQWM2FVZH9Y3T5C8",
        "payst_01J8KXB7P2MQVW4RXZN6Y8H3F1",
        "payst_01J8KXBA3TWQNM7FXZR9Y2V5C4"
      ]
    }
  }
}
```

#### Delete earning line items for all employees, excluding specific pay stubs

`POST /earning_line_items/bulk/delete`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": {
      "payee_type": "employee"
    },
    "exclude": {
      "ids": ["payst_01J8KXB4N6RQWM2FVZH9Y3T5C8"]
    }
  }
}
```

#### Delete earning line items for all pay stubs except contractors

`POST /earning_line_items/bulk/delete`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all",
    "exclude": {
      "payee_type": "contractor"
    }
  }
}
```

#### Delete only earning line items with a specific business preset

`POST /earning_line_items/bulk/delete`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "business_presets": {
    "include": {
      "ids": ["rps_01J8KXD3M7RQWN2FXZV9Y4H6B1"]
    }
  }
}
```

#### Delete earning line items that have no business preset

`POST /earning_line_items/bulk/delete`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "business_presets": {
    "include": {
      "ids": [null]
    }
  }
}
```

#### Delete earning line items with a specific expense accounting code

`POST /earning_line_items/bulk/delete`

```json theme={null}
{
  "payroll_id": "payrl_01J8KX9R2FMQVW3TNZH5Y7B4C6",
  "pay_stubs": {
    "include": "all"
  },
  "expense_accounting_codes": {
    "include": {
      "ids": ["accod_01J8KXF2N4MQRW3VXZH7Y9B5C8"]
    }
  }
}
```

## Bulk Delete Line Items Scope

The delete scope endpoint previews which line items will be deleted by a bulk delete operation. It accepts the same request body as the bulk delete endpoint, but instead of deleting line items, it returns the line items that match the criteria.

### Endpoint

`POST /<type>_line_items/bulk/delete/scope`

`<type>` can be one of the following types:

* `allowance`
* `deduction`
* `earning`
* `employee_benefit`
* `employer_benefit`
* `reimbursement`

### Request

The request body is the same as the [bulk delete](#bulk-delete-line-items) endpoint.

### Response

On success, the operation will return `200 OK` with an array of the line items that would be deleted:

```json theme={null}
{
  "data": [
    {
      "id": "ernli_01J8KXC9R4MQVW2FXZN7Y5H3B8",
      "data": {
        ...line item properties...
      }
    },
    ...
  ]
}
```

### Notes

* Only custom line items are returned. Managed line items are excluded, matching the behavior of the bulk delete operation.
