57 "summary": "Create Offline Order documents no member-notification behavior and has no suppress flag (request: planId, memberId, paid, startDate, couponCode, submissionId); the sibling Mark As Paid documents that offline payments 'trigger events and emails'. A 2026-08-16 probe on a muted site observed no email. Covered by site mute: when getSiteMuteState reads muted:true, this is not a reason to block, skip, delay or warn about the entity."
58 },
59 {
60 "code": "notification-proof-requirements",
61 "severity": "info",
62 "summary": "No notification proof is required for import (site mute is trusted). Never unmute a migration target to test notifications."
67 "summary": "status, endDate, pausePeriods, cancellation, and lastPaymentStatus are all read-only on the Order object; the only writable create inputs are startDate, paid, couponCode, submissionId. A source PAUSED contract needs a post-create Pause Order call (only ACTIVE orders can be paused); CANCELED/ENDED source contracts cannot be recreated in that state natively - keep them as CMS-only history."
68 },
69 {
70 "code": "past-start-date-accepted",
71 "severity": "info",
72 "summary": "RESOLVED — VERIFIED LIVE 2026-08-16 (this pitfall was 'past-start-date-undocumented'; the probe answered it). A backdated startDate IS accepted and preserved: a weekly plan ordered with startDate 2025-06-01 came back status ACTIVE with startDate 2025-06-01 and a server-computed currentCycle { index: 64, startedDate, endedDate } — Wix replays the cycle schedule forward from the backdated start rather than clamping to now. So the original signup date AND the billing anniversary can both be preserved in one field, and the next-payment-date trade-off described in next-payment-date-not-settable is real but resolvable: pick startDate = the source signup date and the derived anniversary follows automatically. Note the cycle index is exposed, so a source contract's cycle count can be cross-checked after import."
73 },
74 {
75 "code": "paid-flag-settles-asynchronously",
76 "severity": "warning",
77 "summary": "VERIFIED LIVE 2026-08-16: with paid:true at create, the CREATE RESPONSE returned lastPaymentStatus: 'UNPAID' and a GET moments later returned 'PAID'. The payment state settles asynchronously behind the create call. An importer that asserts lastPaymentStatus off the create response will record a false negative for every contract; re-read the order (or accept eventual consistency) before writing the crosswalk or the verification artifact."
78 },
79 {
80 "code": "status-settles-from-draft",
81 "severity": "warning",
82 "summary": "VERIFIED LIVE 2026-10-27: the Create Offline Order reply carries status DRAFT (with lastPaymentStatus UNPAID) even for a backdated, paid order; Get Order moments later returns ACTIVE (or PENDING for a future start) and PAID. Pause Order needs ACTIVE, so a pause sent straight after create finds a DRAFT order. ensurePlanOrder re-reads the order until it leaves DRAFT before pausing and before judging the read-back."
83 },
84 {
85 "code": "next-payment-date-not-settable",
86 "severity": "warning",
87 "summary": "There is no next-payment-date input; Wix derives the payment schedule from startDate plus the plan's billingCycle. The source contract's next_payment_date can only be honored by choosing startDate so the cycles align - which trades off against preserving the original start date."
88 },
89 {
90 "code": "business-address-precondition",
91 "severity": "warning",
92 "summary": "Create Offline Order is documented to fail with 428 MISSING_BUSINESS_ADDRESS_STATE / MISSING_BUSINESS_ADDRESS_COUNTRY when the site business address is incomplete; configure it during setup, not at import time. NOT REPRODUCED 2026-08-16: an anonymized verification environment's GET /site-properties/v4/properties returned no businessAddress at all (only locale/currency/timezone) and the offline order still created successfully — so the precondition either depends on the plan's tax configuration or is not enforced on every path. Keep the setup step (it is cheap and the documented error is specific), but do not treat a missing business address as a hard preflight blocker without reproducing the 428."
97 "summary": "VERIFIED LIVE 2026-08-16: the order snapshots planName and planDescription at creation, but planDescription came back as a COPY OF THE PLAN NAME, not the plan's actual description — the plan itself retained its real description. This matters because the accepted trade-off for the severed Stores-product linkage is 'the source product name survives in the plan title/description': that provenance survives on the PLAN, not on the order record. Do not read source provenance out of order.planDescription."
102 "summary": "VERIFIED LIVE 2026-08-16: there is no delete for a pricing-plan order. POST /pricing-plans/v2/orders/{id}/cancel with { effectiveAt: 'IMMEDIATELY' } → 200 and the order moves to status CANCELED with endDate = the cancel instant, but the record and its subscriptionId persist forever. A faulty contract import cannot be rolled back to a clean slate the way imported eCom orders can (Bulk Delete Imported Orders has no counterpart here) — which is a second, independent reason to keep this write behind an explicit approval gate."
103 }
104 ],
105 "mappingGuidance": [
106 "Per active subscriber: create/crosswalk the plan first (pricing-plans/plan), resolve memberId via the member-import crosswalk (400 MEMBER_DOESNT_EXIST is the hard dependency - members import must run first), then POST the offline order; planId + memberId are the only required fields.",
107 "Set paid:true for contracts whose current cycle is already collected on the source (lastPaymentStatus becomes PAID); leave paid:false only when the source cycle is genuinely unpaid. For free plans lastPaymentStatus is NOT_APPLICABLE regardless.",
108 "Recurring BILLING never migrates - payment tokens do not carry and an offline order has no charge method attached; collection restarts on Wix (owner collects off-platform and marks paid, or subscribers re-purchase online). Required migration policy.",
109 "The Stores-product linkage is severed: the contract is recreated as a Pricing Plans membership and the source product name survives only in the plan title/description - required migration trade-off.",
110 "Status mapping: source active -> startDate now or past (ACTIVE); source pending-start -> future startDate (PENDING); source paused -> ensurePlanOrder({ paused: true }) creates ACTIVE then calls Pause Order; source cancelled/expired -> do not recreate natively, land the historical record in CMS and report it as a cutover item.",
111 "Plan purchase limits are ignored for offline orders (documented), so per-member limits on the recreated plan cannot block the import.",
112 "Persist the returned order.id and subscriptionId against the source subscription id in the crosswalk at create time; the order also snapshots planName/planPrice at creation (but NOT a usable planDescription — see order-snapshot-mislabels-plan-description).",
113 "Observed live 2026-08-16: the created order also carries buyer.contactId, a wixPayOrderId, and onEcom: true — plan orders now surface through the eCom stack, so a plan-order import is visible to eCom-side views even though it is not an eCom order. Factor that into any post-import reconciliation that counts orders.",
114 "Writer: ensurePlanOrder({ planId, memberId, startDate, paid, paused, knownOrderId }). startDate is required (the source start date) and is the duplicate-check identity: crosswalk read-back first, then List Orders for that member and plan matched on startDate, then Create Offline Order. couponCode and submissionId are never sent. After an unknown outcome the writer lists once and adopts a match; otherwise it returns plan-order-unknown-outcome and must not be retried automatically (orders cannot be deleted). Any returned orderId goes to the crosswalk whatever the outcome."
115 ],
116 "setupRequirements": [
117 "Wix Pricing Plans app installed — appDefId 1522827f-c56c-a5c9-2ac9-00f9e6ae12d3, installable via the App Installation API (see pricing-plans/plan). Observed live 2026-08-16: the actual pre-install failure on Plans V3 is 428 APP_NOT_INSTALLED carrying that appId, not the documented PRICING_PLANS_NOT_INSTALLED — match on the HTTP 428 and the appId, not the application-code string.",
118 "Site business address configured (documented 428 MISSING_BUSINESS_ADDRESS_STATE/COUNTRY — not reproduced 2026-08-16, see business-address-precondition)",
119 "Members import completed (memberId is required; 400 MEMBER_DOESNT_EXIST)",
136 "note": "'Subsequent offline payments do trigger events and emails' - the documented email trigger on this surface; also: an offline order cannot be marked paid twice (read 2026-08-16)"
141 "note": "only ACTIVE orders can be paused; pausing extends endDate; Cancel Order supports IMMEDIATELY or NEXT_PAYMENT_DATE; Postpone End Date requires a later endDate and cannot target PAUSED orders (read 2026-08-16)"
146 "note": "commerce.subscription-contracts uses the Pricing Plans recreation path described by this entity."
147 },
148 {
149 "type": "live-run",
150 "path": "anonymized-live-verification",
151 "note": "Verified live on a muted site: Create Offline Order accepted paid:true with a backdated startDate, preserved the start date, derived the current cycle, returned the expected offline-order identifiers, and changed lastPaymentStatus from UNPAID on create to PAID on readback. Notification behavior was not observed (muted site, undeliverable address); notifications are covered by the site mute. Orders can be cancelled but not deleted; probe records were cleaned up accordingly."
152 },
153 {
154 "type": "live-run",
155 "path": "anonymized-live-verification",
156 "note": "2026-10-27, new throwaway site, muted: ensurePlanOrder wrote one active (backdated, paid), one pending (future start) and one paused order; all read back with the expected status and PAID. Re-runs adopted the same order by List Orders (buyerIds + planIds, matched on startDate) and by crosswalk read-back; exactly one order per member and plan. First run showed the create reply is DRAFT, so an immediate pause is refused (status-settles-from-draft); fixed and re-run clean."
157 }
158 ],
159 "notes": "WooCommerce active-subscription records migrate by recreation as Pricing Plans memberships using Plans V3 Create Plan and Create Offline Order per subscriber. Live verification established the end-to-end write mechanics and preservation of backdated start dates and billing anniversaries. preferredWrite.verification remains docs. importSafe is true: member notifications are covered by the site mute."