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 inerror. The operation becomespartial.
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 withPATCH /products/{id}instead. quantity: 0is a real value. It sold-outs the variant everywhere.- Watch
operation.completedinstead 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
(
inventoryonGET /channel_accounts). - Channel price rules apply on top of the prices you set or adjust
(
pricingon the channel account).
Last updated on October 17, 2026
Need help?
Email us and a human replies, usually within one business day.