Plans, billing and walls
The plan catalog, promotion codes, the monthly statement, usage meters and the structured 402/409 walls agents can act on.
Amended 2026-09-15: one card rate per plan with no conditions and no promoted rates, Free = 1 storefront + 1 custom domain, and Free's share back at 1% so the all-in card rate is 3.9% + 30¢. Every public number sits in one table at pricing.
Related: email marketing (the marketing wall), shipping §2 (statement billing of labels), automations §12 (abandoned checkout), agents (the MCP tools and the 402/409 shapes).
1. The catalog
The pricing page (/pricing), the Plan & billing tab, the walls, the statements and the MCP tools all quote the same numbers:
| Free | Growth | Pro | |
|---|---|---|---|
| Price | $0 | $24 / month, $19 / month billed annually | $59 / month, $49 / month billed annually |
| Stores per account | 1 | 3 | 10 |
| Card / PayPal fee (product subtotal) | 1% — all-in card rate 3.9% + 30¢ (2.9% + 30¢ processing plus Formahand's 1%) | 0% (2.9% + 30¢ all-in) | 0% (2.9% + 30¢ all-in) |
| Manual, bank transfer, cash on delivery | 0% | 0% | 0% |
| Custom domains (apex + www = one) | 1, then $2 / month each | 10, then $2 | 20, then $2 |
| Team seats | 2 | 5 | 15 |
| Email from the store's domain | the store's email tier, the same on every plan (§1a) | same | same |
| Flows | unlimited | unlimited | unlimited |
| Automation runs | 50,000 / month fair use (paused at 2× with "contact us"; never charged) | unlimited | unlimited |
| API / MCP | unlimited, rate limited (10 / s, bursts of 30) | same | same |
| Media (walled and billed, never shown on the public plan cards or the pricing table) | 10 GB, then $0.05 / GB-month | 100 GB fair use | 1 TB fair use |
| App records (apps §10) | 100 MB, then $0.05 / GB-month | 1 GB fair use | 5 GB fair use |
| App files | 1 GB fair use | 20 GB fair use | 100 GB fair use |
| Rows an app may save in a day, all apps together | 100,000 | 1,000,000 | 5,000,000 |
| Emails one app may send in a day (apps §3) | 500 | 500 | 500 |
| Gift cards (payments § Gift cards) | free, and Formahand takes nothing for them | same | same |
| Formahand Shipping labels | postage + 8% | postage + 5% | postage + 4% (3% once statements can be paid by bank debit) |
| Label minimum | $0.10 per label | $0.10 | $0.10 |
| Built-in assistant | 5 runs / month | 20 | 100 |
| Priority support | — | — | yes |
One rate per kind since 2026-09-15. No plan promises a lower rate for connecting a domain, verifying a sender, shipping orders or referring a store, and no merchant-facing surface (home, pricing, plan cards, dashboard Plan tab, walls, footer, terms) says "promoted", "once your domain is connected" or "rates that drop as you grow". The public pages quote one all-in card rate per plan (allInCardRate) and never break it down. The public Free card lists "Custom domain · 500 marketing emails a month · Discounted shipping labels · 2 team seats" (plus assistant runs): it names no store count and no media allowance; paid cards say "3 stores / 10 stores per account".
The fee base is net of tax (payments §6c): the product subtotal, before shipping, with any tax that sits inside the line prices taken back out. A tax-exclusive store's line prices already are that number. A tax-inclusive store's are not — the VAT is in them — and charging the percentage on that would make the same sale cost a Berlin merchant more than a Boston one for no reason, on money that was never theirs. It is the same basis analytics reports revenue on, so the fee is always a percentage of a number the merchant can see. The one place it is approximate is a **card session on a tax-inclusive store**, where the tax is worked out from an address the buyer has not entered when the session is created: there the fee is taken on the gross subtotal, bounded by the VAT rate and always in Formahand's favour by a fraction of a percent of the tax. PayPal, bank transfer and payment links all know the tax before the buyer pays and are exact.
Refunds and the fee. Whether a refund returns the Formahand fee is decided from the fee the original payment actually carried, never from the store's rate today: a sale made during a fee holiday carries no fee and nothing is returned, and a sale made at 1% returns its fee even if the store is on 0% by the time of the refund. The current rate is only the fallback when the original payment cannot be read back.
1a. Email tiers (2026-09-19)
Email a store sends from its own domain — order confirmations, automation emails and campaigns — is priced by the store's email tier, the same on every plan. Mail Formahand sends to the owner and team (payment notices, new-order and low-stock alerts, statements) is Formahand's own mail to you and never counts.
| Tier | Price | Included a month | Past that | Daily cap |
|---|---|---|---|---|
free | $0 | 500 | $1.00 per 1,000 | 100 |
starter | $5 a month | 1,500 | $0.75 per 1,000 | 300 |
plus | $10 a month | 10,000 | $0.50 per 1,000 | 2,000 |
Without a card a store stops at the included amount; with one it may send up to ten times it, the rest billed per started thousand. A paid tier needs a card (POST /api/plan { action: "email-tier" }, owner session only) and is billed at whatever tier the store is on when the statement is assembled. Your remaining allowance is checked before a send, so a campaign can never overshoot it, and sending capacity is shared fairly between stores. The plan entitlements campaignEmailsPerMonth / emailOverageUsdPer1k remain for older readers and equal the free tier.
3. Promotions and effective pricing
A promotion lowers one rate. Kinds and what value means:
| kind | value | lowers |
|---|---|---|
fee_bps | basis points | the card / PayPal fee |
fee_holiday | ignored: the fee is 0 | the card / PayPal fee |
markup_bps | basis points | the label markup |
email_overage | cents per 1,000 | the email overage |
domain_price | cents per month | the extra-domain price |
plan_discount_pct | percent | the subscription price |
Effective pricing is the plan's list rates with the best live promotion per kind: the lowest resulting rate wins, nothing can ever raise a rate above list, and an expired promotion is ignored. The effective fee and markup are what the checkout, the refund and a label purchase actually use, so a promotion needs no further setup once it is applied.
A store that earned an activation reward before 2026-09-15 keeps it, but its value now resolves to the list rate, so its effective pricing is the list rate like everyone else's.
Annual pricing is not a promotion: it is a second price per plan, chosen with interval: "annual" on start_upgrade / POST /api/plan.
- Codes.
apply_promo_code { code }/POST /api/plan { action: "promo", code }/ the Plan tab's box. Only coupon codes can be typed; a code applies once per store, respects its start and end dates and its redemption limit, and expires a fixed number of months after it was applied (400 bad input, 404 unknown, 409 expired / already applied / fully redeemed). - Referrals (mechanics kept, reward retired). Every store has a
referral_code(8 lower-case characters, minted on first use;get_plan.referral.url)./r/<code>sets a referral cookie (30 days, HttpOnly) and redirects home; a store created while that cookie is set records who referred it. No fee holiday is granted for a referral today and nothing merchant-facing advertises one. A store cannot refer itself. - Activation rewards (mechanics kept, retired). Connecting a domain, verifying a sender and shipping orders granted a permanent rate reward until 2026-09-15. Nothing is granted today, and re-enabling a reward is a founder decision rather than a merchant action.
4. Walls
A wall is the structured refusal a feature returns until the store meets its conditions:
{ "error": "…", "wall": true, "feature": "customDomains", "reason": "setup", "plan": "free", "requiredPlan": "growth",
"steps": [{ "id": "card", "label": "Switch on extra domains ($2.00/month each, on your statement)", "done": false, "href": "/dashboard#activate/domains?option=extra", "activateHref": "/dashboard#activate/domains?option=extra" }],
"usage": { "used": 3, "limit": 3 } }
HTTP 402 for reason: "plan", 409 for setup, paused and limit; MCP tools return the same body as an isError result. Features today:
| Feature | Applies to | Rule |
|---|---|---|
stores | POST /api/onboarding (a second store), every plan change and every reopen | stores owned by the account < the account's best plan (402). A plan change that would leave the account over the lower plan's allowance is refused, and an involuntary downgrade pauses what no longer fits (§4b) |
customDomains | POST /api/domains, add_domain | within the allowance (1 on Free, apex + www = one): free; beyond it: $2/mo each on the statement, which needs a card on file → setup wall with steps card + plan. With a card the domain is added and counted as an extra domain for the month |
media | POST /api/product-images, the MCP image tools | Free stores stop at 10 GB without a card (limit); with a card the overage is billed; paid plans are fair use (never walled) |
marketing | GET/POST /api/campaigns | unchanged setup (live custom domain, verified sender on it, terms accepted, no pause, warm-up cap); the monthly allowance is a limit wall with card + monthly-cap steps only when the store has no card — with one, overage is billed (email marketing) |
assistant | POST /api/setup, POST /api/assistant | runs this month < the plan's allowance (402 naming the next plan; 409 on Pro). One run is one setup, or one merchant message to the dashboard assistant (agents → The dashboard assistant); approving a step it stopped on (/api/assistant/confirm) finishes that run and never counts a second. A message answered on the store's own model key is neither walled nor metered (below) |
automationRuns | flow runs Formahand drives for you | at twice the fair-use allowance: limit with a contact step; queued runs simply wait |
teamSeats | reported | members < seats |
flows, apiTokens | reported | unlimited (null) on every plan; POST /api/tokens keeps the hard ceiling of 200 active tokens against runaway scripts |
plan | start_upgrade, POST /api/plan { action: "upgrade" } | a paid plan that is not open for purchase yet: setup wall with the single step price ("coming soon") |
4a. Activations (the way out of a wall)
Since 2026-09-22 a wall's answer is not "add a card under Settings → Plan & billing" but an activation: one screen per paid feature that says what it is, what the packages cost and switches it on. Every price on it is the same number as §1 and §1a, so no price is written twice:
| Activation | Group | Options | Needs a payment profile |
|---|---|---|---|
email | the three email tiers (Free 500 · $5 for 1,500 · $10 for 10,000), plus overage ("keep sending past the included amount") | paid packages and overage | |
labels | Shipping | payg — discounted commercial rates, billed on the statement | yes |
domains | Online Store | extra — $2 per extra domain a month | yes |
media | Products | overage — $0.05 per GB a month past 10 GB on Free | yes |
automations | Automations | Growth $24 · Pro $59 (unlimited runs) | no: a plan, through start_upgrade |
assistant | Assistant | Growth $24 · Pro $59 (more runs) | no: a plan |
Each activation is in one of five states, derived from the store's meters — active, available, needs_card (past 80% of the allowance with no payment profile), needs_plan, limit_reached — and carries used, limit, options and activateHref (/dashboard#activate/<id>, with ?option=<id> when one option is the obvious next step). The states come from the same wall data describe_walls returns, so a wall and an activation can never disagree.
The flow (hash route #activate/<feature>[?option=&from=&apply=1]) is three steps: what it does (three benefit tiles, an illustration and three bullets), choose a package (radios for packages and plans, a checkbox for pay-as-you-go, a live "Total monthly cost") and switch it on. When the selection needs a payment profile and there is none, step 3 opens the hosted card page with `POST /api/plan { action: "card-setup", returnTo: "activate/<feature>?option=…&apply=1" }`; the return route lands the merchant back on that fragment and the selection is applied at once (email → email-tier, a plan → start_upgrade, pay-as-you-go → nothing beyond the profile). A cancelled card page comes back to choose a package with a neutral note and nothing charged.
Wall steps carry activateHref alongside href wherever the answer is an activation (the extra-domain, media, assistant and automation-run walls, the marketing gate's card and monthly-cap steps, and the shipping_labels readiness requirement), so the dashboard and an agent follow the same link. Everything else still points at Settings → Plan & billing.
GET /api/plan, the Plan tab and describe_walls return every feature with used, limit, wall, plus pricing (the effective rates), usage (this month's meters) and activity.
Sandboxes (environments): walls apply to the live store only. A store's test environment is unlimited (no media, flow, assistant or automation-run wall), never metered (api_calls, automation_runs, assistant_runs and the activity clock are untouched by fh_test_ tokens and sandbox flows), never on a statement (test labels accrue nothing, no card is ever charged) and does not count as a store for the Free plan's "1 store". Tokens stay rate limited in both environments; the plan, billing and domain tools refuse a sandbox token.
Bring your own model key: assistant messages for nothing. Every store can point its assistant and its writing help at a free community model instead of ours, and at its own key for that model (agents → Choosing a model). The choice is in the assistant drawer, under Model; the key is a secret named openrouter_api_key in Settings → Agents & API → Vault, stored scrambled and never shown again.
| The store's choice | The assistant wall | The assistant_runs meter |
|---|---|---|
| Formahand default | applies | counts |
| Free community model, our key | applies | counts |
| Free community model, the store's own key | not checked | not counted |
The reason is the plain one: the allowance exists because a message costs us money, and a message on the merchant's own free quota does not. Nothing else changes — the same tools, the same approval gate, the same limits per turn; free models are just slower and make more mistakes, which the drawer says. A store on its own key still meets every other wall (media, marketing, domains) exactly as before, and the setup assistant always runs on ours.
4b. Stores across a plan change (the downgrade rule)
An account's allowance is the best plan among the stores it owns, so nothing about owning three stores stops the account from dropping to Free — which would leave two stores entitled by a plan nobody is paying for. The rule, decided 2026-09-23, has two halves, because a downgrade arrives in two very different ways.
Voluntary — a downgrade is blocked, an upgrade never is. A plan change the merchant makes themselves (the plan picker, POST /api/plan { action: "upgrade" }, start_upgrade) is refused before any payment page opens when both of these hold: the target plan allows fewer stores than the plan the account is on today, and the account has more stores open than the target allows. The refusal is the stores wall:
{ "error": "Your account has 4 stores; Growth includes 3. Close or delete a store first.", "wall": true,
"feature": "stores", "reason": "limit", "plan": "pro",
"steps": [{ "id": "remove", "label": "Close or delete 1 store", "href": "/dashboard" },
{ "id": "plan", "label": "Or stay on Pro", "href": "/dashboard#settings/plan" }],
"usage": { "used": 4, "limit": 3 } }
reason: "limit" (409), not plan (402): the way through is to close a store, not to pay for one.
An upgrade is never refused, however many stores the account already has. Several accounts own more stores than their plan allows — the founder's own owns four on Free — because they were opened before the allowance existed. Being over the allowance is a legacy condition, not a reason to refuse money: Free → Growth with four stores opens the checkout page, and so does Growth → Pro. The upgrade pauses nothing either (see below); the account simply stays over until the owner closes one or buys the plan that covers them all. Paused stores never count against a voluntary change, because the allowance counts open stores everywhere else.
Involuntary — paused, newest first. A subscription cancelled at period end, or one that lapses after a failed payment, leaves nothing to refuse: the plan is already gone by the time Formahand hears about it, so the account is reconciled instead.
Only a fall in the allowance pauses anything. Formahand reads what the account is allowed before a billing event and again after it, and pauses stores only when the second number is smaller. Counting open stores against the current plan alone is not enough: for an account that is already over its allowance that test is true on every event it will ever receive, so an upgrade, a renewal, a subscription update that changed no plan, an invoice event and the very first event such an account gets would each pause a store and email the owner. The before/after comparison is also what makes a repeated event safe — the second application of the same state is not a decrease, so the owner is emailed once. (A redelivered billing event never gets that far in any case: each event is applied once and only once.)
When the allowance did fall, Formahand counts the account's open stores against the plan it now has and pauses the newest ones until they fit, using the same paused state an idle store gets (§8): the storefront answers the "This store is paused" holding page, and nothing is deleted. A paused store still appears in the dashboard, because the owner has to be able to see and choose between the stores they still have.
Newest first, except a store that is trading. A store with a paid order in the last 30 days goes to the back of the queue and is only picked when there is no other candidate: pausing a shop that is selling to keep an empty one is the wrong default. The evidence used here is what Formahand can see without opening each store — a shipping label bought for an order, and an order line marked fulfilled in live mode. A store that neither ships nor fulfils is treated like any other candidate, so this can only ever save a store, never doom one; and it defers a pause, never cancels it — if every candidate is trading, the newest still go.
The owner hears about it twice: an email from Formahand to the owner (a store's own sending account is never used for this, and the link in it is Plan & billing on formahand.com, never a storefront address) and a notice on **Settings → Plan & billing** naming the paused stores.
The owner picks which to keep. POST /api/plan { action: "reactivate" } reopens a paused store, and it is refused while the account already has its allowance open — so reopening one means closing another first. Nothing records why a store is paused, and nothing needs to: the allowance counts open stores, so an idle pause and a plan pause are gated by exactly the same check, and upgrading again reopens everything the merchant chooses to reopen.
What each surface says about a paused store. Because the two causes share one state, the storefront holding page names neither — "This store is paused… not taking orders right now" — and a shopper has no use for the reason anyway; telling them a store "has been quiet" when the owner's plan paused it is simply false. The owner gets the specific reason on Settings → Plan & billing, which branches on whether this store is one of the account's over-allowance pauses; the dashboard shell's banner states the fact and points there. A paused store stays fully open in the dashboard: the pause is the storefront, never the merchant's own access.
Rate limits. API calls are never capped or billed. Each token gets a bucket of 30 requests refilling at 10 a second, on /mcp and every /api/* route that takes a token; over it: 429 with Retry-After. The bucket is held by the server that answered the request rather than shared globally, so a client spread across regions may see a little more headroom than the nominal rate — plan for the published rate, not for the headroom. Every token request also adds one to api_calls and bumps the store's activity clock, after the response.
5. Usage meters and the monthly statement
Formahand meters, per store and UTC month: automation_runs (flow runs it drove for you), api_calls (every token request), assistant_runs (each POST /api/setup that starts a run, and each merchant message to the dashboard assistant answered on a Formahand key; an /api/assistant/confirm continuation is part of the same run, and a message on the store's own model key is not counted), media_bytes + media_checked_at (your media library is measured once a day), function_invocations (every store-function invocation on a live store; a sandbox's are never counted, store functions §10), apps_db_bytes + apps_files_bytes + apps_checked_at (what a store's apps are keeping, measured once a day, a live store only; every request to an app's own address also counts as one invocation on the same meter store functions use), extra_domains (the highest number in use during the month), and the label totals from each Formahand Shipping purchase. Once a day Formahand also refreshes your email counts (transactional_emails_sent, marketing_emails_sent, email_bounces, email_complaints; last month's too during the first three days of a month) and applies your email tier's monthly ceiling and daily cap to sending (§1a, email marketing §4a).
Labels are no longer charged per label. Buying a label still requires a card on file (readiness) but charges nothing at the time: the postage and the markup are accrued against the month and the ledger row says "Billed on your monthly statement". Voiding a label before the statement is issued drops the accrual entirely. A label bought in a sandbox accrues nothing. Labels bought before this release keep their own payment and are refunded through it on void, as before.
The statement:
| Line | Rule |
|---|---|
plan | only when the store is on Growth/Pro without a subscription (a plan applied by hand): the monthly price less any plan_discount_pct promotion |
email_plan | the store's email tier when it is a paid one ($5 or $10), read at statement time |
email_overage | max(0, transactional_emails_sent + max(marketing_emails_sent, campaign_emails_sent) − the tier's included emails) in started thousands × the tier's rate (an email_overage promotion may lower it, never raise it) |
extra_domains | extra_domains × the effective extra-domain price |
media_overage | Free only: ceil((media_bytes − 10 GB) / GB) × $0.05 |
| Gift cards | Never on a statement, at any size. A gift card is the merchant's own money moving between two of their own records — credit in, credit spent — and Formahand takes no part of it. The email that carries a code counts on the store's ordinary email allowance, like every other message the store sends |
apps_storage_overage | Free only: ceil((apps_db_bytes − 100 MB) / GB) × $0.05, assembled exactly as media_overage is. App files are fair use on every plan and never appear here: records are the tight half because a row costs many times what a picture does to keep (apps §10) |
function_invocations | max(0, function_invocations − the plan's allowance) in started hundred-thousands × $0.50. Past five times the allowance functions are skipped rather than billed further: every hook takes its fallback and the store keeps selling (store functions §10) |
label (one per label) | cost_minor + max(markup_minor, minimum) — the postage Formahand paid the carrier plus the markup, where the minimum is $0.10 in the label's currency: 10 in a two-decimal currency, 1 whole unit in a zero-decimal one (JPY), 100 in a three-decimal one |
Statements are issued on the 1st, for the month that has just ended, and only ever once per store and period. Every active store with usage, accruals, a card or a hand-applied paid plan in that month gets one. total = 0 → no_charge; no card → no_card (the accruals stay attached to their period and are billed once a card is on file, not rolled into a later month); a card → one off-session charge → paid (label accruals flip to billed) or failed, carrying the decline code. The statement currency is USD; a label accrued in another currency is listed under needsReview and the statement is stored with status needs_review instead of being charged, and Formahand settles it with you. A statement with a total is emailed to the store owner using the store's monthly-statement template.
GET /api/plan includes statement (the running preview of the current month); GET /api/plan?statement=YYYY-MM and get_statement { period? } return one period plus the last twelve issued.
Payment features are not on the statement
The switches under Payments — automatic tax, stronger card authentication, local currencies, instant payouts, the individual ways to pay, and the ones the provider decides for you — cost nothing on your Formahand statement (payments). Where they cost anything, your payment provider takes it out of what they pay you, at the rate shown on each switch before you turn it on. Formahand adds no markup to any of them, meters none of them and bills none of them, so switching one on never changes your plan, never needs a card on file and never moves a line on this statement. Your plan's card rate is the one all-in number, exactly as before.
6. Subscriptions and the card
A paid plan is a subscription Formahand keeps against the store's billing customer: a hosted checkout page in subscription mode, a billing portal for changes and cancellation, and events applied once per event id. `interval: "annual" picks the annual price, and a plan_discount_pct` promotion rides on the checkout as a coupon.
6a. The payment profile
The card Formahand charges is a payment profile the merchant keeps, not a prompt inside a wall: Settings → Plan & billing → Payment method (#settings/plan/payment) shows the saved card (brand, last four, expiry), the billing name and email it is issued to, when it was added, Replace card and Remove card. Nothing new is stored: the brand, last four and expiry come back when the card is saved, and the name and email are the store's own and its owner's. Merchant-facing copy never names the processor.
The profile is in one of three states — none, ready or expired — which is the one word describe_account reports and the profile screen's badge shows. A profile counts as ready when there is a billing customer, a default payment method, and an expiry that has not passed; an expiry that was never reported is treated as usable. Every decision uses that one test, so an expired card now stops a package exactly as a missing one does, everywhere: email ceilings, the extra-domain and media walls, buying labels and charging the statement.
Removing (POST /api/plan { action: "card-remove" }, owner session only) detaches the payment method and clears the card details, keeping the billing customer and every statement. It is refused with 409 while the profile is still paying for something, and the refusal names each line: a paid email package or email past the included amount, labels bought this month, extra domains in use, and media above the allowance.
7. Dashboard, API, MCP
- Settings → Plan & billing opens as a hub of tiles at
#settings/plan: Limits (only when an allowance is reached, then first;/limits), Plan (/current, with the picker at/current/change), Payment method (/payment), This month (/month) and Email package (/email); the olderplan,billing,usageandstatementland on the matching part. Across the parts: plan and status; Your rates (each effective rate; when a coupon lowered it, the list price struck through and the code that set it; never an "once earned" promise); the promotion-code box; This month (stores, domains, flows, tokens, seats, marketing, automation runs, API calls, media, assistant runs, custom code, labels); any active wall; the running statement (lines, total, status); the plan cards with a monthly/annual toggle; Manage billing. A dormant store shows a Reactivate button; an idle one a notice; an account over its store allowance a notice naming the stores that are paused (§4b). /pricing: the hero, the three plan cards, the "Every plan:" line and one link to pricing, where every number (including media and the statement rules) sits in one table with a Shopify column; the pricing FAQ is on both. Linked from the home header and the footer.- **
#activate/<feature>** (§4a): the activation flow, reachable from every wall step, from the Email card's Choose, from Email → Sending settings' allowance row and fromdescribe_account. GET /api/plan→{ plan, fees, pricing, usage, activity, features, email, plans, billing: { hasCustomer, card, profile, commitments }, activations, statement, referral };?statement=YYYY-MM;POST /api/planactionsupgrade { plan, interval? },portal,sync { sessionId },promo { code },reactivate,email-tier { tier },card-setup { returnTo? },card-remove(the last three owner-session only).- MCP:
get_plan,get_statement { period? },apply_promo_code { code },describe_walls, **describe_account** (the plan,paymentProfile.state, the statement and every activation withagentCanDo,activateHrefand anaskMerchantsentence written for that profile state;nextStepsputs the profile first whenever it blocks anything),start_upgrade { plan, interval? }(agents).
8. Idle-store hygiene
A store's activity clock moves (at most once an hour) on a dashboard sign-in, any authenticated /api/* call or MCP request, and therefore on every publish and order action; activity also turns an idle store back to active. After **90 days** without activity a store becomes idle and the owner gets one warning email; after 180 days it becomes dormant, the owner gets a second email, and the storefront answers a "This store is paused" holding page (503, noindex) instead of the shop. Nothing is deleted; products, orders, settings and domains stay. The owner reactivates from Plan & billing (POST /api/plan { action: "reactivate" }), which is instant. A dormant store is skipped by abandoned-checkout mail and by the daily usage measurement.