55 "summary": "VERIFIED LIVE 2026-10-26: Create Submission has no notification control (only submission, additionalMetadata, captchaToken) and fires Submission Created, the trigger of the form's automations. With the site muted, an API-created entry STILL emailed the site owner: the per-form 'New submission received' automation is a transactional email that mute does not cover. With that automation and the preinstalled site-wide one set INACTIVE, no email was sent. Contact-facing notifications remain covered by site mute. The entries import pauses the form's automations first (pauseFormAutomations), best-effort: a failed pause never holds or delays the entries."
56 },
57 {
58 "code": "submitter-is-read-only",
59 "severity": "blocker",
60 "summary": "`submitter` (the oneOf memberId / visitorId / applicationId / userId) is READ-ONLY on both the request and the response — the original submitter cannot be set. A migrated submission will be attributed to the importing identity, not to the person who filled the WordPress form. The one identity field that IS settable at create is `contactId` (GUID, immutable), so submitter attribution has to be carried as a contact reference resolved through the CRM contacts crosswalk, and the loss of the true submitter identity must be ledgered rather than papered over."
61 },
62 {
63 "code": "created-date-is-ignored",
64 "severity": "warning",
65 "summary": "VERIFIED LIVE 2026-10-26: `createdDate` is accepted on Create Submission but IGNORED: an entry sent with createdDate 2023-03-15 was stored with the create time, and the field is immutable, so there is no way back. The original date is kept in the form's hidden 'Original submission date' field (target `original_submission_date`, added by createForm); createFormSubmission writes the source timestamp there. The Forms inbox shows the import date (cutover item form-entry-dates-in-hidden-field)."
70 "summary": "Every key in `submissions` must be the `target` of a field in the form's schema. A single key that is not a target is rejected as UNKNOWN_VALUE_ERROR and fails the ENTIRE submission — not just that value. WordPress submission stores keep whatever field names the form had at the time, so a form that was edited after some submissions were taken will have historical records carrying retired field names. Reconcile every record's keys against the created schema's targets before writing, and route unmatched values to a ledgered overflow (or add a hidden catch-all field) rather than letting one stale key drop a whole message."
75 "summary": "The status a submission is created with depends on the form's namespace and on whether the form collects payment; the docs say to read `status` from the response rather than assume it. LIVE-VERIFIED (upgraded from warning to blocker): for `wix.form_app.form` without payment, Create Submission's response ALWAYS reads PENDING first -- there is no immediate-CONFIRMED case for this namespace, and a codegen path that treats the create response's status as final (whether it expects CONFIRMED or treats PENDING as a stop signal) is wrong either way. An ASYNC SPAM-FILTER PASS then resolves that PENDING to one of two outcomes within 1-2 seconds: CONFIRMED (stored), or silent deletion (GET on the id then returns 404 NOT_FOUND -- confirmed within 3 seconds and stable on repeated re-checks over several minutes, so this is not eventual consistency, it is a real content-based decision). Two live-confirmed causes of deletion, both risking real data loss on a historical bulk import: (1) bot-like WORDING -- a submission whose text read like a migration self-test ('Migration test', 'confirming no notification fires...') was reliably deleted even though the exact same field shape with natural wording confirmed every time; (2) a GENUINE customer record was ALSO deleted as a false positive (real name/email/phone/message content) purely because the form's `spamFilterProtectionLevel` was 'ADVANCED' -- the same content resubmitted after PATCHing the target form's `spamFilterProtectionLevel` to 'NONE' confirmed immediately. A THIRD, unrelated class also surfaced: a large fraction of a historical dataset can turn out to be an actual automated SQL-injection scanner sweep (boolean-blind and time-based payloads sent across a several-minute burst) that the filter correctly deleted -- this is a genuine reason to exclude data, not a false positive, and should be identified independently (a tight creation-timestamp cluster proved far more reliable than matching individual payload signatures, which kept missing new variants) and excluded BEFORE attempting the write, not left for the filter to catch. Required practice for any bulk historical import through this endpoint: (a) lower the TARGET form's spamFilterProtectionLevel to NONE for the duration of the import if false positives on real content are unacceptable, (b) after every create, POLL by re-fetching the submission id (2-3 attempts, ~2s apart) and only count it as landed once status reads CONFIRMED -- a 404 on re-fetch is definitive proof of loss, not a transient error, (c) never trust the initial create response's PENDING status as either success or failure -- it is neither, it is provisional."
76 },
77 {
78 "code": "no-bulk-create",
79 "severity": "warning",
80 "summary": "There is no bulk create for submissions — the tree offers Bulk Mark Submissions As Seen and nothing else. Every historical message is one POST, so a store with thousands of Flamingo inbound messages is a long, rate-limited, one-record-at-a-time import that must be checkpointed and resumable. (Form SCHEMAS do have Bulk Create Form; submissions do not.)"
85 "summary": "Values for WIX_FILE fields are not URLs from the source site: the documented path is Get Media Upload URL, upload the file, then reference the resulting media in the submission. A WordPress attachment URL passed straight through will not resolve, so file-upload answers require the media import to run first and the submission import to consume its crosswalk."
86 },
87 {
88 "code": "seen-flag-should-be-set-on-import",
89 "severity": "info",
90 "summary": "`seen` is settable at create. Historical submissions imported from another platform were already read by the owner there; leaving `seen` false lands the whole history in the dashboard as unread and, on top of any notification behaviour, makes the migration look like a flood of new leads. Set seen:true for imported history unless the user asks otherwise."
95 "summary": "Forminator entries have no REST route: they live in Forminator's own tables `frmt_form_entry` and `frmt_form_entry_meta`, read through wix-wp-plugin-v2 (rp-source-wordpress/plugins/forminator.json). A source without the bridge plugin installed cannot migrate Forminator entries."
96 }
97 ],
98 "mappingGuidance": [
99 "Dependencies: forms/form supplies required formId and field targets; each entry waits only for its own form (per record: submission.formId is resolved through the dependency gate); crm/contact is required when contactId is crosswalked; media/media-file is required for file-upload answer IDs and stays task-complete: those IDs sit under submissions.<field target>, a key the dependency gate cannot declare as a path.",
100 "Import order is strict: forms/form (the schema) first, then contacts/members if contactId is to be populated, then media for any file-upload answers, then submissions. formId is required and is the crosswalked Wix schema id.",
101 "Build `submissions` as a map keyed by the schema field's `target` — the value shape follows that field's inputType: STRING (including date and time fields), NUMBER, BOOLEAN, ARRAY (array of selected option values), ADDRESS (address object), PAYMENT (array of product objects), SCHEDULING (appointment object). The source-field-name -> target map written by the forms/form step is the input to this.",
102 "Pass the source submission's original timestamp as `originalDate` to createFormSubmission: it is written to the hidden `original_submission_date` field (Wix ignores createdDate, see created-date-is-ignored). Flamingo inbound messages carry post_date; the CSV export carries a `Date` column produced by get_post_time('c').",
103 "Resolve `contactId` from the submission's email through the CRM contacts crosswalk where a contact exists; leave it unset otherwise. Do not attempt to set `submitter` — it is read-only.",
104 "Set `seen: true` on imported history so a migration does not present years of answered enquiries as new unread leads.",
105 "LIVE-VERIFIED 2026-09-16 (supersedes the older 'anything but CONFIRMED on create is a stop signal' guidance): Create Submission for `wix.form_app.form` ALWAYS returns PENDING first, then an async spam-filter pass resolves it to CONFIRMED (stored) or silent deletion within 1-2 seconds -- PENDING on the immediate create response is the NORMAL case, not a stop signal. Only CONFIRMED means the record is stored; do not stop on an initial PENDING, and do not treat a bare create-response read as proof either way. Poll (2-3 attempts, ~2s apart) and only count a submission as landed once a re-fetch reads CONFIRMED -- a 404 on re-fetch is definitive proof of loss. See the status-is-namespace-dependent-not-chosen pitfall below for the full mechanism, causes of false-positive deletion, and required practice.",
106 "Notifications are covered by the site mute; no throwaway-form probe or guarded first record is needed for notification reasons.",
107 "Spam-flagged source records (Flamingo's flamingo-spam post status, Akismet meta) should be filtered out before import rather than recreated. LIVE-VERIFIED 2026-09-16: this is in ADDITION to Wix's own spam filter, not instead of it -- Wix's spamFilterProtectionLevel DOES evaluate every API-created submission (see the pitfall below); the older claim that it does not re-evaluate API-created submissions was wrong and is corrected there.",
108 "Write entries with createFormSubmission, after pauseFormAutomations for that form and before restoreFormAutomations. Outcomes: created (read back CONFIRMED) | in-spam (moved to the form's spam tab; never re-sent and never restored by the import, because Report Not Spam runs the automations) | deleted | pending | unknown | failed. Only created counts as landed.",
109 "importFormEntries also lowers the form's spamFilterProtectionLevel to NONE for the import (the required practice in status-is-namespace-dependent-not-chosen: under ADVANCED a genuine record was removed as a false positive; the recreated form is on no page while the import runs, so no visitor can submit). It records the level before in execution/forms/automation-pause.json, uses a partial Update Form at the current revision (formFields untouched), and restores it afterwards. Best-effort, one attempt: a failure is a finding (form-spam-filter-not-lowered / form-spam-filter-not-restored) and the entries go ahead; a failed restore is a cutover item."
110 ],
111 "setupRequirements": [
112 "Wix Forms app installed (`wix_forms`; the Form Submission API only works with it — confirm with GetAppInstance)",
132 "note": "a key that is not a field target fails the whole submission (UNKNOWN_VALUE_ERROR); status-on-creation table; validation error shape (errorPath/errorType/errorMessage/params). No mention of notifications or emails anywhere on the page (read 2026-08-16)"
137 "note": "the Submission Created domain event fires on create — the trigger surface Wix Automations (and therefore the owner's 'new form submission' email) hangs off; the webhook page documents no way to create a submission without emitting it (read 2026-08-16)"
142 "note": "per-inputType value shapes (ADDRESS/PAYMENT/SCHEDULING objects), keys come from field targets, one rejected value fails the whole submission (read 2026-08-16)"
147 "note": "former precedent (importSafe:false for unproven notification suppression), superseded 2026-10-27: notifications are covered by the site mute"
148 },
149 {
150 "type": "live-run",
151 "path": "anonymized-live-verification",
152 "note": "Throwaway site, 2026-10-26, owner inbox watched: (A) unmuted, automations active: owner email; (B) muted, automations active: owner email, createdDate 2023-03-15 stored as the create time, seen:true kept; (C) muted, per-form and preinstalled automations INACTIVE: no email. All entries read back CONFIRMED; none went to spam."
153 }
154 ],
155 "notes": "Authored 2026-08-16 (forms vertical). The submitter CANNOT be set (read-only; contactId is the only settable identity). VERIFIED LIVE 2026-10-26: createdDate is ignored (the original date goes to a hidden field), and the per-form owner-email automation emails the owner even when the site is muted; the import pauses it."