Build
Inventory sync
Push stock counts and adjustments without putting sold stock back on the shelf.
Customers only see what is in stock. Your POS is where most stock moves — the counter, deliveries from suppliers, write-offs — so your POS owns the count, and pushes it to Scanimart.
Push counts
curl -X PUT https://api.scanimart.com/v1/stores/1042/inventory \
-H "Authorization: Bearer $SCANIMART_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"as_of": "2026-10-08T10:00:00+05:30",
"items": [
{ "barcode": "8901725181222", "stock": 14, "price": "229.00", "mrp": "245.00", "external_id": "SKU-ATTA-5" },
{ "barcode": "8901262010016", "stock": 0 }
]
}'stockis units on the shelf according to your POS atas_of.nameis required the first time Scanimart sees a barcode; after that, only the fields you send change.external_idis your SKU. It is echoed on order lines, so your POS can find the product without a barcode lookup.- Up to 1,000 items per push, each barcode once. Up to 200 are applied immediately and the response is
200with the result. Bigger pushes are queued: you get202with anid, andGET …/inventory/syncs/{id}shows when it is done.
Rows that fail — an unknown barcode with no name, a negative price — are listed in the result's errors; the rest still apply.
Why as_of matters
Scanimart takes stock too: when a store accepts an online order, and when a customer pays for a Scan & Go basket in the aisle. Your POS only learns about those when it books the sale.completed. A count you took before booking one of our sales still includes those units — written as-is, it would put sold stock back on the shelf.
So for every push, Scanimart subtracts the units in its own sales that you had not booked by as_of:
stock = max(your count − Scanimart units you had not booked by as_of, 0)The result's adjusted_for_unbooked_sales lists the units subtracted per barcode. A sale counts as booked once your endpoint answered its sale.completed with 2xx, or you acknowledged it with POST …/sales/ack. Sales older than 72 hours are never subtracted.
Always send as_of — the moment your POS took the count, not the moment you send it. It defaults to now, which is only right if the count is that fresh.
Adjustments
For a single movement, send a delta instead of a count:
curl -X POST https://api.scanimart.com/v1/stores/1042/inventory/adjustments \
-H "Authorization: Bearer $SCANIMART_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "adjustments": [
{ "barcode": "8901725181222", "delta": -2, "reason": "sale", "reference": "BILL-20402" },
{ "barcode": "8901262010016", "delta": 24, "reason": "received", "reference": "GRN-118" }
] }'reason is one of sale, return, received, damaged, correction, other. Up to 500 per call. Use an Idempotency-Key: an adjustment applied twice is two adjustments.
Do not send adjustments for Scanimart's own sales — they already took the stock.
Reading stock
GET /v1/stores/{store_id}/inventory lists each product with:
| Field | Means |
|---|---|
stock |
Units on the shelf |
reserved |
Units held for paid online orders not yet accepted |
available |
stock − reserved: what can still be sold |
GET …/inventory/syncs shows your recent pushes and adjustments, and the dashboard shows the same.
How often
Push a full count once a day (after closing is a good time), and adjustments as they happen. If you cannot send adjustments, push changed items every few minutes instead.
