# Product Catalogs and Commerce

A catalog is one token ID per product and one purchase approval per token ID. Each approval carries that product's price, its supply cap, and whether the buyer keeps a receipt token or the token burns on purchase (a consumable). Payment goes from the buyer to the store address in the same transaction as the mint. There is no cart contract and no escrow; a purchase is one MsgTransferTokens from `Mint`.

The receipt token is what makes the rest of the standard available: a receipt can gate a download with BB-402, be refunded through a return approval, or expire for a time-limited license.

## What Makes It Work

| Requirement | Token-standard primitive |
| --- | --- |
| Independent price per SKU | `coinTransfers` on each purchase approval, `overrideFromWithApproverAddress: false` so the buyer pays. See [Coin Transfers](https://docs.bitbadges.io/token-standard/approval-criteria/coin-transfers) |
| Exactly one unit per purchase | `predeterminedBalances.incrementedBalances.startBalances` of amount `1` for that token ID |
| Limited stock | `maxNumTransfers.overallMaxNumTransfers` = supply; `0` for unlimited. See [Approval Trackers](https://docs.bitbadges.io/token-standard/approval-criteria/approval-trackers) |
| Consumable versus keepsake | `toListId: "All"` mints a receipt to the buyer; `toListId` = burn address consumes it on purchase |
| Buyer can discard a receipt | One `!Mint` to burn-address approval over every product ID |
| Prices cannot change under a buyer | All permissions frozen at creation. See [Permissions](https://docs.bitbadges.io/token-standard/concepts/permissions) |

## The Fields That Matter

```json
{
  "approvalId": "product-purchase-1",
  "fromListId": "Mint",
  "toListId": "All",
  "initiatedByListId": "All",
  "tokenIds": [{ "start": "1", "end": "1" }],
  "approvalCriteria": {
    "predeterminedBalances": {
      "incrementedBalances": { "startBalances": [{ "amount": "1", "tokenIds": [{ "start": "1", "end": "1" }], "ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }] }] },
      "orderCalculationMethod": { "useOverallNumTransfers": true }
    },
    "coinTransfers": [{ "to": "bb1p0rrel3365scadq5k9pv0x0zp9j22js6dnw70d", "coins": [{ "amount": "25000000", "denom": "ibc/E1116484B327AEE59CDC3DA73D319834781A13DB2A7DFC1F38A30CD45ABF58B8" }], "overrideFromWithApproverAddress": false, "overrideToWithInitiator": false }],
    "maxNumTransfers": { "overallMaxNumTransfers": "100", "amountTrackerId": "product-purchase-1" },
    "overridesFromOutgoingApprovals": true,
    "overridesToIncomingApprovals": true
  }
}
```

Product 2 is the same approval on token ID 2 with its own price, and `toListId` set to the burn address if it is a consumable.

```bash
bb build product-catalog --store-address bb1p0rrel3365scadq5k9pv0x0zp9j22js6dnw70d \
  --uri ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi/collection.json \
  --products '[{"name":"Widget","price":25,"denom":"USDC","maxSupply":100},{"name":"Pass","price":5,"denom":"USDC","burn":true}]'
```

This emits a `Products` collection with two purchase approvals, one burn approval, per-product token metadata, and frozen permissions.

## Variations

- Members-only pricing: a second purchase approval on the same token ID with a lower price and `mustOwnTokens` of a [membership](https://docs.bitbadges.io/use-cases/memberships-and-address-lists); buyers prioritize the one they qualify for.
- Pay in credits: `mustOwnTokens` of a [credit token](https://docs.bitbadges.io/use-cases/loyalty-points-and-credits) plus a burn of those credits in the same transaction.
- Time-limited license: mint receipts with `ownershipTimes` so the download gate closes after a year.
- Returns: a `!Mint` to burn-address approval with `coinTransfers` from the mint escrow back to the initiator, bounded by `transferTimes` to the return window.
- Drops: bound each purchase approval's `transferTimes` to the sale window, and add `perInitiatedByAddressMaxNumTransfers: "1"` for one per customer.

## Build It

- Skill: [Product Catalog](https://docs.bitbadges.io/agents/skills/product-catalog)
- Guide: [Mint and Distribute](https://docs.bitbadges.io/guides/mint-and-distribute) for paid mints, [Token-Gated Access](https://docs.bitbadges.io/use-cases/token-gated-access) to gate the delivery
- CLI: [`bb build product-catalog`](https://docs.bitbadges.io/cli/build#product-catalog), `bb products` from [Standards](https://docs.bitbadges.io/cli/standards#products)

```text
Load the product-catalog skill. Build a store paid to bb1p0rrel3365scadq5k9pv0x0zp9j22js6dnw70d with three products: Sticker Pack at 3 USDC unlimited, Poster at 20 USDC with 50 in stock, and Day Pass at 5 USDC that burns on purchase. Validate, review, simulate, then give me the review link.
```
