Bulk Update SKU Orders
POST/api/storefront/instances/:id/orders/update-sku-orders
Re-read each order from the store, then push what changed into its linked SKU.io sales order: a store cancellation cancels the SKU sales order, a payment taken after import is recorded once, and the buyer's delivery choice is refreshed.
This endpoint currently requires session authentication; Personal Access Token scope support is in progress.
Orders with no linked SKU sales order are skipped and reported. If the store cannot be reached for an order, that order is still updated from the last mirrored data rather than failing the batch — refetch_failed counts how many took that path.
Request body
ids(array of integers, required unlessapply_to_allis sent).apply_to_all(boolean, optional).filters(object, nullable) — the set to target whenapply_to_allis true.
Choosing the orders Send exactly one of the two selection shapes:
ids— an explicit list of mirrored order ids. Ids that belong to another connection are silently dropped.apply_to_all: trueplusfilters— the action targets every order the filters match, however many that is, not just a page of them. Thefiltersobject is resolved server-side against the same filter setGET /ordersaccepts, so what you saw in the list is exactly what is acted on.
Inside filters (every key optional, all bare column names — no filter[...] brackets needed, though filter[status] style keys and a nested filter object are both unwrapped for you):
search— the same free-text search as the list, honoured like any other filter.search_columns,search_strict_columns— narrow or tighten that search.status,payment_status,currency_code— comma-separated value lists.sku_order—with,without,abandoned,failedorheld.has_unmapped_items— boolean.archived—only/archived, orall. Leaving it out means active orders only, matching the list's own default, so a filter-less apply-to-all never sweeps archived orders.placed_from,placed_to— date bounds.ids— a comma-separated id list, as a filter rather than a selection.<column>.<operator>— any advanced operator key the list accepts (e.g.total.greater_than).filter_groups— a base64-encoded JSON condition tree.
Pagination and display keys (page, per_page, sort, included, total, query) are ignored if present.
Failing closed. A filters payload that cannot be parsed, a malformed filter_groups tree, or a legacy {conjunction, filterSet} payload returns 422 rather than being treated as "no filters" — silently matching every order would be the wrong guess for a bulk action.
Immediate or background. A single order is processed inline and the outcome is in the response (tracked_job_log_id is null). More than one order is queued as a background task and the response returns straight away with tracked_job_log_id — the handle you poll for progress, per-order results and failures. total_orders is how many orders were selected.
A single order with no SKU sales order to update returns 422 rather than a silent success.
Requires the integrations.sync permission.
Authentication: Bearer token (session or PAT).
Request
Responses
- 200
- 401
- 403
- 404
- 422
- 429
OK
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Not found — no record with the given identifier (or the route does not exist). Verify the ID before retrying.
Unprocessable Content
Response Headers
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.