Inventory
Stock levels per product and variant: list them, and set or adjust them in bulk.
List stock levels#
List stock per product and variant, newest product first. One row per product. Variants are reduced to id, title (falls back to variant name), sku, barcode, stock and price_cents (non-numeric stock/price become null).
Query parameters
Page size. Clamped to 1..200. Non-numeric values fall back to the default. Default: 50.
Value of next_cursor from the previous page. Returns items with created_at strictly before this timestamp.
true: product stock > 0; false: product stock <= 0. Filters on the product-level stock only.
Only for OAuth tokens that cover several shops: the shop to query. Must be one of the token's shops (else 403 forbidden). Required when the token covers more than one shop (else 400 shop_required). Optional for API keys (a key belongs to exactly one shop; any other value returns 403).
Response fields
Items of this page.
created_at of the last item when more items exist, otherwise null.
Product id.
Handle.
Title.
Product SKU.
Product barcode.
Product-level stock.
Active flag.
[{id, title, sku, barcode, stock, price_cents}]
Product creation; pagination key.
Last product update.
Errors
Any endpoint. Response carries header WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource".
Scope check per endpoint (and per body field on PATCH /orders/:id).
shop_id query parameter names a shop outside the credential's reach.
Multi-shop OAuth token without shop_id.
Any endpoint when the resolved shop has active=false.
Any endpoint. Header Retry-After (seconds until the next minute bucket).
Any endpoint.
curl "https://api.ecomone.shop/api/public/v1/inventory?limit=10" \
-H "X-Api-Key: $ECOMONE_API_KEY" \
-H "X-Api-Secret: $ECOMONE_API_SECRET"const res = await fetch("https://api.ecomone.shop/api/public/v1/inventory?limit=10", {
method: "GET",
headers: {
"X-Api-Key": process.env.ECOMONE_API_KEY,
"X-Api-Secret": process.env.ECOMONE_API_SECRET,
},
});
if (!res.ok) throw new Error((await res.json()).message);
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.ecomone.shop/api/public/v1/inventory?limit=10",
headers={
"X-Api-Key": os.environ["ECOMONE_API_KEY"],
"X-Api-Secret": os.environ["ECOMONE_API_SECRET"],
},
timeout=30,
)
res.raise_for_status()
data = res.json()["data"]{
"data": [
{
"product_id": "3b8b1f0a-1d2c-4f34-8a7c-6e2f9b4d5c11",
"handle": "linen-shirt-white",
"title": "Linen Shirt White",
"sku": "LS-W",
"barcode": null,
"stock": 42,
"active": true,
"variants": [
{
"id": "v1",
"title": "M",
"sku": "LS-W-M",
"barcode": null,
"stock": 18,
"price_cents": 3950
}
],
"created_at": "2026-06-02T11:20:00.000Z",
"updated_at": "2026-08-27T10:02:00.000Z"
}
],
"next_cursor": null
}Update stock levels#
Set or adjust stock for up to 200 products or variants in one transaction. Each entry addresses a product by sku, or by product_id (plus variant_id for a variant), and sets an absolute stock or a relative adjust. If any entry is invalid — unknown or ambiguous SKU, invalid value — nothing is written and the response lists every problem in errors with its index. Send an Idempotency-Key header to make retries safe: the same key with the same entries returns the stored result for 24 hours instead of applying the change again. Requires that the key creator (or OAuth user) can manage the shop.
Stock changes apply to the live shop immediately. The whole batch is one transaction: either every entry is written or none. Send an Idempotency-Key so a retry is never applied twice.
Header parameters
Optional. Reuse the same key when retrying the same batch; the change is applied only once (24 hours).
Query parameters
Only for OAuth tokens that cover several shops: the shop to query. Must be one of the token's shops (else 403 forbidden). Required when the token covers more than one shop (else 400 shop_required). Optional for API keys (a key belongs to exactly one shop; any other value returns 403).
Body parameters
1 to 200 stock changes.
SKU to look up (1-200 characters, surrounding spaces ignored). Matches a product SKU or a variant SKU in this shop. Send either sku or product_id. If the SKU matches more than one product or variant, the request stops with 400.
Product id. Send either sku or product_id.
Variant id or key (max 120 characters), as returned by GET /inventory or in order line_items. Only together with product_id. Without it the product-level stock is changed.
New absolute stock, 0 to 10,000,000. Send either stock or adjust.
Change relative to the current stock, e.g. -2 (-10,000,000 to 10,000,000). The result must stay between 0 and 10,000,000. Concurrent changes are retried, so no adjustment is lost.
Response fields
One entry per item that was saved, in request order.
Product id.
Variant id (or key if the variant has no id); null when the product-level stock was changed.
SKU of the variant, else of the product.
Stock after the change.
Items whose product or variant does not exist in this shop, returned exactly as sent. They were skipped.
Problems per entry: {index, error, message} with error one of not_found, ambiguous_sku, invalid_entry, invalid_stock, idempotency_conflict. When not empty, no entry was written.
Errors
Body invalid (max 200 entries; each needs sku or product_id and stock or adjust) or invalid Idempotency-Key.
Missing scope inventory:write, or the key creator may not manage the shop.
The stock transaction is temporarily unavailable; retry with the same Idempotency-Key.
curl -X POST "https://api.ecomone.shop/api/public/v1/inventory" \
-H "X-Api-Key: $ECOMONE_API_KEY" \
-H "X-Api-Secret: $ECOMONE_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"sku": "LS-W-M",
"stock": 18
},
{
"product_id": "3b8b1f0a-1d2c-4f34-8a7c-6e2f9b4d5c11",
"variant_id": "v2",
"adjust": -2
},
{
"sku": "LS-B-XL",
"stock": 5
}
]
}'const res = await fetch("https://api.ecomone.shop/api/public/v1/inventory", {
method: "POST",
headers: {
"X-Api-Key": process.env.ECOMONE_API_KEY,
"X-Api-Secret": process.env.ECOMONE_API_SECRET,
"Content-Type": "application/json",
},
body: JSON.stringify({
"items": [
{
"sku": "LS-W-M",
"stock": 18
},
{
"product_id": "3b8b1f0a-1d2c-4f34-8a7c-6e2f9b4d5c11",
"variant_id": "v2",
"adjust": -2
},
{
"sku": "LS-B-XL",
"stock": 5
}
]
}),
});
if (!res.ok) throw new Error((await res.json()).message);
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.ecomone.shop/api/public/v1/inventory",
headers={
"X-Api-Key": os.environ["ECOMONE_API_KEY"],
"X-Api-Secret": os.environ["ECOMONE_API_SECRET"],
},
json={
"items": [
{
"sku": "LS-W-M",
"stock": 18
},
{
"product_id": "3b8b1f0a-1d2c-4f34-8a7c-6e2f9b4d5c11",
"variant_id": "v2",
"adjust": -2
},
{
"sku": "LS-B-XL",
"stock": 5
}
]
},
timeout=30,
)
res.raise_for_status()
data = res.json()["data"]{
"data": [
{
"product_id": "6b1f8a2e-0c4d-4e1a-9f3b-2d5c7e9a1b20",
"variant_id": "size-m",
"sku": "TS-M",
"stock": 120
},
{
"product_id": "6b1f8a2e-0c4d-4e1a-9f3b-2d5c7e9a1b20",
"variant_id": "size-l",
"sku": "TS-L",
"stock": 41
}
],
"not_found": [],
"errors": []
}