Inventory Extension
Telegram Shopping doesn't store products itself. It pulls them from the Inventory extension, a separate LNbits extension that acts as your product catalog.
This separation means one inventory can serve multiple sales channels. The same products could power a Telegram bot, a point-of-sale terminal, or a web shop — each seeing only the items you want it to see.
Setting it up
Install the Inventory extension from the LNbits extension manager. Create an inventory, give it a name and currency.
The shop currency is automatically synced from your Inventory settings. Set the currency here — the Telegram Shopping extension reads it on every product refresh.
Adding products
Each product has these fields:
| Field | Purpose |
|---|---|
| Name | Product title shown in the Mini App |
| Price | Base price in your inventory currency |
| Description | Appears on the product card |
| Images | Product photos displayed in the Mini App; first one used for inline query results |
| SKU | Optional reference code |
| Quantity in stock | Stock count; purchases blocked at zero |
| Tags | Comma-separated labels for categories and filtering |
| Weight (grams) | Product weight; used for per-kg shipping rate calculation |
| Tax rate | Per-product tax; falls back to inventory default |
| Discount | Per-product discount percentage |
| Active | Inactive products are hidden from all extensions |
| Approved | For manager workflows; unapproved items stay hidden |
Images
Multiple images are supported, separated by ||| or commas. The Mini App displays all images. The first image is used for inline query results when customers share products.
Image sources that work:
- Public URLs —
https://example.com/photo.jpg(preferred, Telegram fetches directly) - LNbits asset IDs — bare UUIDs are resolved to
/api/v1/assets/{id}/binaryautomatically - Relative API paths —
/api/v1/...paths are made absolute using your LNbits base URL - Data URIs — base64-encoded images are proxied through a local endpoint (only works when your LNbits instance is publicly reachable)
Tags as categories
Tags become the Mini App's category filter. Products tagged caps, t-shirts, stickers show up as three browsable categories.
A product with multiple tags appears in each matching category.
Filtering with omit_tags
The key feature for multi-channel setups. The inventory has an omit_tags setting. Any product whose tags overlap with this list is hidden from extensions that check it. Telegram Shopping checks it.
Example: You have 50 products. 10 are wholesale-only, tagged wholesale. Set omit_tags to wholesale. Those 10 products never appear in the Mini App. Your wholesale channel can still access them separately.
Individual products can have their own omit_tags for finer control.
Shop-level tag filtering
Beyond the Inventory's omit_tags, each shop can apply its own tag filters:
| Setting | Effect |
|---|---|
| Include tags | Only products matching these tags appear. Empty = show all. |
| Omit tags | Products matching these tags are hidden. Applied after include filter. |
This lets multiple shops share one inventory while showing different product subsets. See Shop Configuration — Tag filtering for details.
Tax and discounts
Two levels of configuration:
| Setting | Scope | Fallback |
|---|---|---|
| Default tax rate | All items | 0% |
| Per-item tax rate | One specific product | Inventory default |
| Global discount | All items | 0% |
| Per-item discount | One specific product | Inventory global |
| Tax-inclusive pricing | Whether listed prices include tax | On |
Telegram Shopping reads all of these and calculates correct totals in the cart.
Stock management
When a customer pays, Telegram Shopping reduces the stock count automatically. The change is logged in Inventory's audit trail with source telegramshop, so you can see exactly which sales caused which stock changes.
At zero stock, the product still shows but can't be added to the cart.
Product refresh
Products are fetched from Inventory:
- When the shop starts
- After every successful payment
- When you hit the Refresh button in the admin panel
The fetch pulls all items matching: is_active = true, is_approved = true, tags not in omit_tags (both inventory-level and shop-level). It also syncs currency, default tax rate, tax-inclusive flag, global discount, and omit_tags from your inventory settings.
