> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dmly.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Sell products and track stock

> Add products to your catalogue, track stock levels, get alerted when stock runs low, and send a product to a contact from a flow.

**Products** is the second tab of **Offerings** — the things your business sells rather than
does. Retail items in a salon, supplements in a clinic, consumables you bill on an order. A
service is time; a product is a thing on a shelf.

Products carry a price and tax, they can track stock, and they drop onto orders and invoices as
line items. They are also the only part of the catalogue with CSV import and export, which
matters the moment you have more than a handful.

<Note>
  These are your own products, kept in DMLY. They are not the same as products synced from a
  Shopify or WooCommerce store — those are a separate mirror with their own triggers, and
  nothing you do on this tab touches them. If you are building around `store_inventory_low` or
  `store_product_back_in_stock`, you are working with the store mirror, not with these.
</Note>

## Add a product

<Steps>
  <Step title="Open the Products tab">
    Go to **Offerings** and select **Products**.
  </Step>

  <Step title="Create it">
    Select **New product** and give it a name and a price.
  </Step>

  <Step title="Set tax">
    Set **Tax rate (%)**, or leave it blank to fall back to the default tax rate from
    [Finance settings](/finance/settings). Turn on **Price includes tax** if the price you typed
    already has tax in it.
  </Step>

  <Step title="Fill in the rest">
    **SKU**, **Image**, **Cost price** and a category are all optional. Cost price is private to
    your workspace — it never appears to a client, and it is included in the CSV export, so you
    can work out margin yourself.
  </Step>
</Steps>

Categories are shared with the rest of the catalogue and managed from inside the tab — see
[Categories](/offerings/categories).

<Warning>
  **Delete product** is final: the dialog reads `Delete the product "<name>"? This can't be
      undone.` Orders and invoices that already include the product are safe, because each line is
  a copy (see below) — but the product itself does not come back.

  One exception: a product bundled into a plan is not deleted. DMLY deactivates it instead and
  tells you so — `A product used by a plan was deactivated instead of deleted.` Only a product
  no plan references is actually removed, along with its stock movements.
</Warning>

## Track stock

Stock tracking is off until you ask for it. Turn on **Track stock** on a product and set its
**Stock quantity**; leave it off for anything you never count, like a digital item or something
you order in per client.

Set **Low stock threshold** to the level at which you want to know. A product counts as low only
when all three of these are true:

* **Track stock** is on
* **Low stock threshold** has a number in it
* **Stock quantity** is at or below that threshold

Leave the threshold blank and the product is never low, no matter how far the count falls.

Once tracking is on, DMLY keeps the count for you rather than waiting for you to remember:

* **Confirming an order decrements stock** for the products on it. See
  [Orders](/finance/orders). Confirming the same order again does not decrement a second time.
* **Every change is recorded** — sales, corrections and manual edits all go through one ledger,
  so the current count always has a history behind it.

On the Products tab, low stock is flagged with a **Low** badge, and the **Low stock only**
filter narrows the list to just those products. That filter is the fastest reorder list you
have.

<Tip>
  Set the threshold to roughly what you sell during your reorder lead time, not to zero. A
  threshold of zero only tells you about the problem after it has already cost you a sale.
</Tip>

## Get alerted when stock runs low

Low stock and back-in-stock are automation triggers, so what happens next is yours to build in
the [flow builder](/automation/flow-builder).

The part that catches people: **these fire on a crossing, not on a state.** DMLY compares the
count before the change with the count after it.

* **Stock low** fires when the count was *above* the threshold and the change takes it *to or
  below* it. Going 4 → 3 with a threshold of 3 fires. Going 3 → 2 does not — it was already low,
  so nothing was crossed.
* **Back in stock** fires when the count was at zero (or below) and the change takes it above
  zero. Restocking from 5 to 50 fires nothing, because it was never out.

Both need **Track stock** on. A product with tracking off never fires either one.

<Note>
  A stock event is about a product, not a person — there is no customer to reply to. So the
  trigger asks you to name a tag, and the flow runs for the contacts carrying it, capped at 500
  contacts per run. Use it for a "notify me" waitlist tag, or a tag on your own team. Without a
  tag on the trigger, there is nobody to message.
</Note>

Because the recipients are tagged contacts rather than someone who just messaged you, most of
them will be outside WhatsApp's 24-hour window. Start the flow with a WhatsApp template — see
[Message templates](/broadcasts/message-templates) and
[Triggers](/automation/triggers).

<Warning>
  `offering.stock_low` and `offering.back_in_stock` appear in the webhook topic picker, but
  nothing emits them today — subscribing to either delivers nothing. Build stock alerts as
  flows, not webhooks.
</Warning>

## Send a product from a flow

The flow builder's **Offerings** group has a step that sends a product from your catalogue to
the contact in the conversation. You pick which product; the step handles the rest.

Alongside it is a **check stock** step, which is a branch rather than a send: it looks at a
product and sends the run down one of two paths, in stock or out of stock. Two things about it
are worth knowing before you build on it:

* **A product with stock tracking off is always treated as in stock.** There is no count to
  check, so the step will not claim otherwise.
* **A product it cannot find goes down the out-of-stock path**, on purpose. It never claims
  availability it cannot confirm — so a deleted product fails safe, in the direction that does
  not promise a client something you cannot sell.

The step makes the count available to later steps as `{{product.stock}}`, so you can put the
real number in the reply. It also defaults to the product from the trigger, which means it
chains straight off a stock event without you picking anything.

<Tip>
  The useful pattern is check stock *before* you send. A contact asking "do you have it?" gets
  the product and a booking-or-buy nudge on the in-stock path, and an honest "I'll let you know
  when it's back" plus a waitlist tag on the other — and that tag is exactly what your
  back-in-stock flow notifies later.
</Tip>

## Import and export

Products are the one part of the catalogue you can move in bulk.

<Steps>
  <Step title="Get the shape right">
    Select **Import**, then **Download sample CSV**. Use it as your template — matching its
    columns is the whole job.
  </Step>

  <Step title="Upload">
    In **Import products**, upload your file. Every row with a name becomes a **new** product.
  </Step>

  <Step title="Get your data back out">
    **Export** downloads your current products as a CSV — a useful backup before a bulk price
    change, so you have the old prices on record.
  </Step>
</Steps>

<Warning>
  Import only adds. It never matches an existing product, so re-importing the same file — or
  re-uploading an export — creates a second copy of every product in it. The panel's hint
  (**Upload a CSV file to add or update products in bulk**) overpromises: there is no update
  path. Editing prices in an exported CSV and importing it back duplicates your catalogue
  rather than updating it; make bulk price changes in the app instead.
</Warning>

## What does not work yet

The product editor shows two Meta catalogue controls — **Sync to Facebook** and **Sync to
Instagram** — under a heading that labels them honestly: **Meta catalogue** · **Coming soon**.
They are placeholders. Both switches are greyed out and disabled, so you cannot turn them on,
and nothing syncs your products to Facebook or Instagram.

## Products on orders and invoices

When a product goes onto an order or an invoice, DMLY **copies** its name, price and tax onto
that line. The line is a snapshot, not a live link.

This is deliberate, and it protects you: raise your prices next month and last month's issued
invoices still say what the client actually agreed to pay. The flip side is that editing a
product never corrects a document already issued — fix the document itself, in
[Invoices](/finance/invoices) or [Orders](/finance/orders).

## Where to next

<Columns cols={2}>
  <Card title="Offerings overview" icon="tags" href="/offerings/overview">
    How services, products and plans fit together.
  </Card>

  <Card title="Categories" icon="folder-tree" href="/offerings/categories">
    Group a long product list so it stays workable.
  </Card>

  <Card title="Orders" icon="receipt" href="/finance/orders">
    Sell a product — and decrement its stock.
  </Card>

  <Card title="Triggers" icon="bolt" href="/automation/triggers">
    Stock low, back in stock, and the rest of the commercial events.
  </Card>
</Columns>
