Sync stock and prices in bulk

Push quantity and price changes for up to 100 SKUs per call, and read per-item outcomes.

For recurring syncs from an ERP or warehouse, POST /inventory/batch is the endpoint to build on: it addresses variants by SKU, so you don't need to store Nembol ids at all.

curl -X POST https://api.nembol.com/rest/v1/inventory/batch \
  -H "Authorization: Bearer $NEMBOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: stock-sync-2026-07-30T22:00" \
  -d '{"items": [
    {"sku": "VDJ-M-001", "quantity": 12},
    {"sku": "VDJ-L-001", "quantity": 0, "price": "44.90"}
  ]}'

The local write is immediate; channel propagation is asynchronous. The response is an operation. Items that can't be matched come back in rejected_items with a reason (sku_not_found, sku_ambiguous) without failing the rest, and they're also failed entries in results: the operation ends partial, so a SKU renamed in your system shows up in your alerts instead of silently stopping its sync. If no item can be applied, the call answers 422 no_items_applied (reasons in error.details.rejected_items) and nothing changes.

results[] has one entry per SKU and per channel the product is live on, with its channel_account_id and listing_id:

  • pending: saved in Nembol, the channel hasn't answered yet;
  • succeeded: that channel has the new stock / price;
  • failed: that channel refused it, with its message in error. The operation becomes partial.

A temporary refusal (e.g. Shopify's "this product is currently being modified" when two writes reach the same product together, or a rate limit) is retried by Nembol first: while it retries, the result stays pending, and only a push that still fails ends failed.

So you always know whether each shop got the stock, which is what prevents overselling: wait for the operation.completed webhook (or poll GET /operations/{id}) and act on the failed entries. A product live on no channel gets one entry with channel_account_id: null, already succeeded: saved in Nembol, nothing to push.

Full catalog upserts

To create-or-update whole products (content included), use POST /products/batch. It has the same per-SKU matching (an ambiguous SKU fails with sku_ambiguous, nothing written), up to 100 items, per-item outcomes, status: "partial" when only some fail, and 422 no_items_applied when none applies. Unmatched SKUs are created (title required), matched ones are updated.

Bulk listing actions

POST /listings/batch runs one action (publish, delist, resync or retry) on up to 100 (product, channel account) pairs, e.g. to copy a catalog onto a second eBay account:

curl -X POST https://api.nembol.com/rest/v1/listings/batch \
  -H "Authorization: Bearer $NEMBOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: copy-to-ebay2-page-1" \
  -d '{"action": "publish",
       "items": [{"product_id": "prod_66a1f0", "channel_account_id": "chac_6aa12cab"},
                 {"product_id": "prod_66a1f1", "channel_account_id": "chac_6aa12cab"}]}'

Each pair gets its own result in the operation: pending until the channel answers, skipped when already in the requested state (e.g. already_listed), failed with a code otherwise. Results come back in the same order as your items, and each one repeats the product_id and channel_account_id you sent, unknown ones included, so you can always tell which pair a result is about. Page through larger catalogs 100 pairs at a time, with a distinct Idempotency-Key per page.

Bulk price changes

POST /inventory/price_adjustment raises or lowers every variant of up to 100 products by a percentage or an amount (optionally rounded to .99) and pushes the new prices to the live channels:

curl -X POST https://api.nembol.com/rest/v1/inventory/price_adjustment \
  -H "Authorization: Bearer $NEMBOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"product_ids": ["prod_66a1f0", "prod_66a1f1"], "mode": "percentage", "value": -15, "rounding": true}'

Every variant's result carries previous_price and price. To undo, send the previous prices back:

POST /inventory/batch
{"items": [{"sku": "TEE-M", "price": "19.99"}, {"sku": "TEE-L", "price": "21.99"}]}

Gotchas

  • One Idempotency-Key per batch run. Retrying a timed-out batch with the same key replays the stored outcome instead of double-applying it.
  • Batch updates don't take images. A matched item with images[] fails (per-item). Update images with PATCH /products/{id} instead.
  • quantity: 0 is a real value. It sold-outs the variant everywhere.
  • Watch operation.completed instead of polling if you sync frequently.
  • Prices are strings ("44.90"), always in the store's base currency.
  • A channel can show fewer units than you have (or "out of stock" on Google Merchant Center): sellers can set a per-channel quantity cap (inventory on GET /channel_accounts).
  • Channel price rules apply on top of the prices you set or adjust (pricing on the channel account).

Last updated on October 17, 2026

Need help?

Email us and a human replies, usually within one business day.

On this page