---
title: "Bulk product actions"
method: POST
path: "/api/v1/products/bulk"
tags: ["products"]
---

# Bulk product actions

`POST /api/v1/products/bulk`

## Request

- Base URL: `https://demo.invoiceninja.com`
- URL: `https://demo.invoiceninja.com/api/v1/products/bulk`
- Auth: none declared. Required headers: `X-API-TOKEN`, `X-Requested-With`
- TypeScript: <https://skmtc.dev/invoiceninja/apis/invoice-ninja-api-reference/docs/api/v1/products/bulk/post.ts> (a function with typed inputs; its response is checked against the schema)

##  POST /api/v1/products/bulk
Archive / Restore / Delete  / Set tax id in bulk

## Query parameters

- `index` string

## Headers

- `X-API-TOKEN` string, required
- `X-Requested-With` string, required

## Request body

- ProductBulkAction
  - `action` string, required: The action to perform ie. archive / restore / delete / set_tax_id
  - `ids` string[], required
  - `tax_id` string: The tax rate id to set on the list of products The following constants are available (default = '1') ``` PRODUCT_TYPE_PHYSICAL = '1' PRODUCT_TYPE_SERVICE = '2' PRODUCT_TYPE_DIGITAL = '3' PRODUCT_TYPE_SHIPPING = '4' PRODUCT_TYPE_EXEMPT = '5' PRODUCT_TYPE_REDUCED_TAX = '6' PRODUCT_TYPE_OVERRIDE_TAX = '7' PRODUCT_TYPE_ZERO_RATED = '8' PRODUCT_TYPE_REVERSE_TAX = '9' ```

## Response `200`

The Product response

- Product
  - `id` string: The hashed product ID.
  - `user_id` string: The hashed ID of the user that created this product.
  - `assigned_user_id` string: The hashed ID of the user assigned to this product.
  - `project_id` string: The hashed ID of the project that this product is associated with.
  - `vendor_id` string: The hashed ID of the vendor that this product is associated with.
  - `custom_value1` string: Custom value field 1.
  - `custom_value2` string: Custom value field 2.
  - `custom_value3` string: Custom value field 3.
  - `custom_value4` string: Custom value field 4.
  - `product_key` string: The product key.
  - `notes` string: Notes about the product.
  - `cost` number, double: The cost of the product. (Your purchase price for this product)
  - `price` number, double: The price of the product that you are charging.
  - `quantity` number, double: The quantity of the product. (used as a default)
  - `tax_name1` string: The name of tax 1.
  - `tax_rate1` number, double: The rate of tax 1.
  - `tax_name2` string: The name of tax 2.
  - `tax_rate2` number, double: The rate of tax 2.
  - `tax_name3` string: The name of tax 3.
  - `tax_rate3` number, double: The rate of tax 3.
  - `archived_at` integer: The timestamp when the product was archived.
  - `created_at` integer: The timestamp when the product was created.
  - `updated_at` integer: Timestamp
  - `is_deleted` boolean: Boolean flag determining if the product has been deleted
  - `in_stock_quantity` integer: The quantity of the product that is currently in stock
  - `stock_notification` boolean: Indicates whether stock notifications are enabled for this product
  - `stock_notification_threshold` integer: The minimum quantity threshold for which stock notifications will be triggered
  - `max_quantity` integer: The maximum quantity that can be ordered for this product
  - `product_image` string, uri-reference: The URL of the product image
  - `tax_id` string: The tax category id for this product.' The following constants are available (default = '1') ``` PRODUCT_TYPE_PHYSICAL = '1' PRODUCT_TYPE_SERVICE = '2' PRODUCT_TYPE_DIGITAL = '3' PRODUCT_TYPE_SHIPPING = '4' PRODUCT_TYPE_EXEMPT = '5' PRODUCT_TYPE_REDUCED_TAX = '6' PRODUCT_TYPE_OVERRIDE_TAX = '7' PRODUCT_TYPE_ZERO_RATED = '8' PRODUCT_TYPE_REVERSE_TAX = '9' ```
  - `income_account_id` string: The accounting income account identifier this product maps to (used by external accounting integrations such as QuickBooks).

## Other responses

- `401`: Authentication error
- `403`: Authorization error
- `422`: Validation error
- `429`: Rate Limit Exceeded
- `5XX`: Server error
- `default`: Unexpected Error

## Changes

- **2026-04-20** `69a36036d334`: 1 info
  - added the optional property `income_account_id` to the response with the `200` status
- **2025-05-24** `93bb427f804b`: 2 warning, 30 info
  - removed the optional property `data` from the response with the `200` status
  - removed the optional property `meta` from the response with the `200` status
  - added the optional property `archived_at` to the response with the `200` status
  - added the optional property `assigned_user_id` to the response with the `200` status
  - …28 more
- **2025-05-23** `783f03909c3a`: 30 warning, 2 info
  - removed the optional property `archived_at` from the response with the `200` status
  - removed the optional property `assigned_user_id` from the response with the `200` status
  - removed the optional property `cost` from the response with the `200` status
  - removed the optional property `created_at` from the response with the `200` status
  - …28 more
- **2024-06-06** `8e82a2bd77e0`: 5 breaking, 33 info
  - added the new required request property `action`
  - added the new required request property `ids`
  - the request's body type changed from no type to `object`
  - the response's body type changed from no type to `object` for status `200`
  - …34 more
- …earlier changes not shown

[Operation history](https://skmtc.dev/invoiceninja/apis/invoice-ninja-api-reference/changes/api/v1/products/bulk/post.md)

---

[API](https://skmtc.dev/invoiceninja/apis/invoice-ninja-api-reference.md) - [All operations](https://skmtc.dev/invoiceninja/apis/invoice-ninja-api-reference/llms.txt) - [OpenAPI document](https://skmtc.dev/invoiceninja/apis/invoice-ninja-api-reference/revisions/bcda1f823746?raw)
