# Set up a merchant and a product from the command line `sub3.mjs` is the management CLI: one file whose only dependency is `viem`. Every sub3 site serves it at `/sub3.mjs`, set to that site's network; the source is [cli/sub3.mjs](cli/sub3.mjs). ```sh curl -fsSO https://sub3.dev/sub3.mjs && npm install viem node sub3.mjs help ``` ## 1. Register the merchant handle The handle (`acme`) is permanent and costs $20, paid once to sub3. The owner wallet can later change the website and the payout address, and can transfer the merchant. ```sh export SUB3_PRIVATE_KEY=0x… # the owner wallet; keep it out of prompts, files and git node sub3.mjs merchant register acme --url https://acme.com --pay-to 0xYourPayoutAddress # prints the plan and simulates the approval of the $20 fee; nothing is sent node sub3.mjs merchant register acme --url https://acme.com --pay-to 0xYourPayoutAddress --send ``` Without `SUB3_PRIVATE_KEY` the CLI still validates and prints the transaction (`to`, `data`, `chainId`) for another signer; `--from
` simulates as that wallet. ## 2. Create a product and its items ```sh node sub3.mjs product create acme/app --name "Acme App" \ --tier basic:1:5:Basic --tier pro:2:20:Pro \ --lifetime forever:99:Forever \ --pack credits:5:1000:"1000 credits" ``` | Option | Format | Meaning | | ------------ | ------------------------------- | ---------------------------------------------------------------------------------- | | `--tier` | `key:level:monthlyPrice[:name]` | A subscription. 12 months cost 10. One tier per user; a higher level is an upgrade | | `--lifetime` | `key:price[:name]` | Bought once, owned forever | | `--pack` | `key:price:credits[:name]` | Bought any number of times; your backend credits each receipt once | Prices are dollars (`5`, `4.99`, at least `0.10`); the CLI converts them with the stablecoin's decimals (6 to 18, from `GET /v1/network`). Keys use `a-z`, `0-9` and inner `-`: handles 3–32 characters, product and item keys 1–32. **Handles and keys never change**; names and prices can. A product has at most 32 items. The CLI checks all of this, and that the signer owns the merchant, before simulating. Change items later. Existing memberships keep their end date; a new price applies to later payments: ```sh node sub3.mjs item set acme/app tier pro:2:25:Pro --send # change a price, or add a new item node sub3.mjs item disable acme/app basic --send # stop selling; nothing already bought changes node sub3.mjs product show acme/app ``` An item never changes kind; use a new key instead. `item set` on a disabled item puts it back on sale. ## 3. Verify the domain Publish `https://acme.com/.well-known/sub3.json` (on the host of the merchant URL): ```json { "merchant": "acme", "logo": "/logo.png" } ``` The logo is a path on that host or an `https://` URL; PNG, JPEG, WebP or SVG; at most 256 KB. Then: ```sh node sub3.mjs verify acme # explains exactly what is wrong; sub3 caches results for 10 minutes ``` Verified merchants show their logo, `@acme` and ✓ on the hosted sign-in and checkout pages. ## 4. Watch it ```sh node sub3.mjs merchant show acme node sub3.mjs stats acme/app ``` ## Environment | Variable | Meaning | | ------------------ | --------------------------------------------------------------------------------------------------- | | `SUB3_ENVIRONMENT` | `production`, `sandbox` or `local` (default: the site the file came from; `production` from source) | | `SUB3_API` | Use this API origin instead; the network, contract and token come from its `GET /v1/network` | | `SUB3_PRIVATE_KEY` | The owner wallet. Needed for `--send` | | `SUB3_RPC_URL` | Optional RPC for simulating and sending; defaults to the network's public RPC | | `SUB3_SITE` | Optional, for the checkout link printed after `product create` with a custom `SUB3_API` | Agents: run without `--send`, show the developer the printed plan, and let them broadcast. A successful simulation is not permission to send.