Tote developers
All guides

Stores & drivers

Store catalog & inventory

How a store's products, prices and stock relate to Tote's shared catalog, and every way to change them โ€” by hand, by category, or by a full sync.

Tote keeps one shared product catalog โ€” names, images, barcodes, categories. A store does not create products; it links catalog products to itself and sets its own price, stock and active flag for each.

flowchart LR
    catalog["Tote catalog<br/>name, image, barcode, category"]
    link["Store's link<br/>price, stock, is_active"]
    store["Store"]
    catalog --> link --> store

Customers see a product in a store only when the link exists, is active, and the product itself is active in the catalog. Stock is only checked at checkout.

Every inventory endpoint is for the store's owner; staff get 403 or 404.

By hand#

By category#

These take store_id and category_id in the body:

A category with no products returns 404.

Full sync#

POST stores/products/sync updates many products at once from the store's own system โ€” this is what the sync agent calls.

{
  "store_id": 7,
  "products": [
    { "barcode": "6281007012345", "price": 4.5, "stock": 120 },
    { "barcode": "6281007099999", "price": "abc", "stock": 3 }
  ]
}
  • The barcode is the only identity. Any id sent is ignored. A product is matched to the catalog by its exact barcode.
  • A matched product that is not linked yet is linked and active. One that is already linked gets its price and stock refreshed and keeps its is_active, so a product the merchant switched off stays off.
  • A missing price uses the catalog price; a missing stock means 0.
  • Products left out of a sync are untouched. A sync never unlinks or zeroes anything; to stop selling something, send it with stock: 0 or switch it off.
  • Up to 100,000 products per request.

Every line is accounted for in the response:

{
  "store_id": 7,
  "summary": { "total": 2, "successful": 1, "failed": 1, "ignored": 0 },
  "successful_syncs": [{ "id": 88, "barcode": "6281007012345", "price": 4.5, "stock": 120 }],
  "failed_syncs": [{ "barcode": "6281007099999", "product_id": 91, "reason": "invalid_price" }],
  "ignored": []
}
Outcome reason Meaning
ignored missing_identity No barcode
ignored product_not_found The barcode is not in Tote's catalog. Tote adds catalog products; the store cannot
failed invalid_price price is not a number
failed invalid_stock stock is not a whole number
failed db_error The write failed; every pending line is reported failed. Retry the sync

Statistics#

GET stores/{store}/statistics returns the store's dashboard figures for the merchant app's home screen.