Skip to main content

Bulk changes

Available since 1.26.0. Permission: management. It is the same engine used by the app's bulk changes.

Routes​

MethodRouteUse
POST/bulk/previewCalculates the effect without applying anything.
POST/bulkRuns the change.
GET/bulk?limit=30History (1 to 100 jobs).
GET/bulk/{id}Status and problems of a job.
POST/bulk/{id}/revertUndoes a job.

Request body​

FieldRequiredNotes
entityYesproducts, extras, extra_categories or product_terms.
operationYesSee the operations table.
paramsNoOperation parameters.
targetYes{ "ids": [..] } or, for products only, { "filter": {..} }.
request_idYes, when running and undoingIdempotency key of 8 to 64 characters. If you repeat it, you get the existing job.
actorNoWho makes the change, for example "notifier:15".

The product filter accepts the wc/v3/products parameters: search, category, tag, brand, status, stock_status, min_price, max_price, type, on_sale, sku, modified_after, plus notiwoo_image, notiwoo_extras and notiwoo_extra_category.

Operations​

Entity and operationParameters
products price.regular, extras pricemode: set, increase_amount, decrease_amount, increase_percent or decrease_percent. value ≥ 0. round: none, 50, 100, 1000 or 900.
products price.salemode: set, percent_off or clear. value, and optionally from and to (YYYY-MM-DD). round.
products status.setstatus: publish, draft, private or pending.
products stock.setstock_status: instock, outofstock or onbackorder. quantity if the product manages stock.
products terms.categories, terms.tags, terms.brandsaction: add, remove or replace. ids: up to 100.
products extras.assignaction: add, remove, replace or clear. ids: extra categories. include_global with clear.
products extras.globaldisabled: yes or no ("No extras").
extras categories, extra_categories global_categoriesaction and ids.
extras enabled.set, extra_categories enabled.setenabled.
extras prechecked.setprechecked.
extra_categories rules.setrequired, minimum_options, maximum_options.
extra_categories unassign_productsscope: all, or product_category together with product_category_id.
products, extras, extra_categories delete—
product_terms deletetaxonomy: product_cat, product_tag or product_brand.
product_terms mergetaxonomy and target_id.
Destructive operations

delete, merge and unassign_products are destructive. Always show the preview and ask for confirmation before running them. On variable products, price changes apply to their variations.

Preview​

curl -X POST https://tienda.example.test/wp-json/notiwoo/v1/bulk/preview \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{
"entity": "products",
"operation": "price.regular",
"params": { "mode": "increase_percent", "value": 5, "round": "100" },
"target": { "filter": { "status": "publish" } }
}'
{
"success": true,
"data": {
"targets": 12, "total": 12, "changed": 12, "skipped": 0, "skip_reasons": {},
"samples": [
{ "type": "product", "id": 21, "label": "Combo para dos",
"before": { "regular_price": "34000" }, "after": { "regular_price": "35700" } }
],
"variations": 0,
"destructive": false
}
}

samples shows up to 10 examples. Possible skip reasons are no_price, sale_not_lower, unchanged, invalid_rules, unsupported, error and modified_since.

Run​

Send the same body to POST /bulk, adding request_id. It responds 201 with the job:

{
"id": 31, "entity": "products", "operation": "price.regular", "status": "done",
"total": 12, "processed": 12, "succeeded": 12, "skipped": 0, "failed": 0,
"actor": "notifier:15", "revert_of": null, "reverted_by": null,
"created_at": "2026-09-30T17:30:00+00:00", "finished_at": "2026-09-30T17:30:02+00:00",
"can_revert": true
}

Limits:

  • Up to 5000 items per job.
  • Up to 200 items are processed in the same request. Above that, they are processed in the background in batches of 50 and status is running until it finishes. Call GET /bulk/{id} to follow progress.
  • Only one job can run at a time per store (409 notiwoo_bulk_busy).

Undo​

POST /bulk/{id}/revert with a new request_id. You can only undo within 7 days and if can_revert is true. Items modified after the change are skipped with the reason modified_since.

Errors​

CodeHTTP
notiwoo_bulk_unknown_operation, notiwoo_bulk_invalid_params, notiwoo_bulk_invalid_price, notiwoo_bulk_invalid_target, notiwoo_bulk_empty_target, notiwoo_bulk_request_id400
notiwoo_bulk_too_many400
notiwoo_bulk_busy, notiwoo_bulk_cannot_revert409
notiwoo_bulk_not_found404
notiwoo_bulk_job_failed500