Stage scope: this stage covers only what Build and Manage Wix Automations lists; do not perform anything marked "Later stages only" or any workflow that needs a guide marked "not yet published". "Stage", "Later stages only" and "not yet published" describe how this skill is being rolled out; never mention them to the user. Explain a limit in product terms: what can't be done through the API here and where the user can do it instead (for example, in the automations builder).
TL;DR
appId (GUID) + triggerKey (string). Find real ones with Resolve Triggers (installed apps only); never invent a key or reuse one from an example.description field. Choose by displayName + triggerKey + payload schema + available filters — names are ambiguous.filters array can be used. A payload field without a filter definition is NOT filterable (use a condition step instead — see Automations Conditions (not yet published)).{ id, fieldKey, filterExpression } with one of exactly two builder-readable expression shapes (§4.2). Values are always a literal array. Entity values are ids, never names.implementedMethods.getDynamicSchema: true expose more payload fields once their schema-changing filters are chosen — fetch the dynamic schema (§5) before mapping anything downstream.Site-scoped (wix-site-id header), SDK module triggerCatalog: Resolve Triggers (installed apps) · Get Trigger By App Id And Key (filters, payload schema) · Get Trigger Dynamic Schema · Get Identities Schema · Query Triggers (whole catalog, regardless of installation). Paths and request shapes: Automations API Catalog §3.
basicFieldsOnly: true (drops schemas and filters) and pages of ≤ 25; page until paging.total is reached, de-duplicating (Automations API Catalog §6).appId (returns all that app's triggers regardless of maturity; the app must be installed). You may also put appId / triggerKey in query.filter; if the filter is rejected, page and filter locally.displayName and triggerKey: the user's phrase → the domain noun ("booking", "form", "order", "member") → synonyms ("appointment"/"session", "purchase"/"order placed"). Keys usually start with the app prefix (wix_bookings-, …).payloadDataSchema titles and filters to confirm the event and that the downstream data exists. If two remain equally plausible and it matters, ask.maturity CREATED / not GA, it isn't available to sites yet (§5 of Automations Feasibility and Planning (not yet published)).Selection guidance for overlapping families:
225dd912-7dea-4738-8688-4b8c6955ffc2, key wix_form_app-form_submitted. Use the older app 14ce1214-b278-a7e4-1373-00cebd1bef7c, key wix_forms-form_submit only when the site's forms live there (check which app the form id comes from). For a named form or choice value, prefer the trigger whose filter expresses it over a generic trigger + condition.| Field | Use |
|---|---|
appId, triggerKey | Copy verbatim into configuration.trigger. |
displayName | What the user sees. Not a unique key. |
payloadDataSchema | JSON Schema of the event payload — the only trigger data you may reference. |
filters[] (≤5, each with followUpFilters[] ≤5) | The only filterable fields (§4). |
implementedMethods.getDynamicSchema | true → payload grows with filter choice (§5). |
Payload schema annotations you will meet:
format: uuid, date-time, date, email, uri, number (a numeric string — wrap it in toNumber() in numeric functions).identityType: "contact" | "member" on an id field → the aggregated payload also contains a root-level contact / member object (keys and rules: Automations Graph and Data Model §4). visitor ids stay plain fields with no enrichment.itemsSelectionConfiguration.providerKey / .tag → the field holds an entity id (service, form, label, product, …). Compare it only to ids (see Automations Entity and Provider Configuration (not yet published)).wixCustomType fixed shapes: MONEY {value: string, currency: string} · ORDER_ID/ORDER_PAYMENT_ID/RECEIPT_ID/RECEIPT_PRESET_ID uuid strings · ATTACHMENT {fileName, downloadUrl} · IMAGE_URL uri string · FIELDS array of {label, value} · RECEIPT complex object.futureDate: true on a date-time field → the trigger supports a "before the event" offset (§5 of Automations Schemas and Scheduling (not yet published)).hidden: true → not shown in pickers but still referenceable. examples show real value shapes.Values you put in the expression, by valueInput.type (anything else is dropped or rewritten when the panel opens):
ENTITY_SELECTOR: entity ids as quoted strings, of the kind named by entitySelector.id / the field's itemsSelectionConfiguration — from the vertical's public API or the user (Automations Entity and Provider Configuration (not yet published)). multiSelect: false → one id.STATIC_ITEMS: quoted strings equal to a staticValues[].value that has a displayName (not the displayName, not the item id, never bare numbers).USER_INPUT NUMBER: exactly ONE bare number within numberInputOptions.minValue/maxValue. BOOLEAN: exactly ONE bare true/false.The builder writes some filters by itself when the trigger panel opens; save them too or the automation shows an unsaved change: every USER_INPUT BOOLEAN filter (user's value, else booleanInputOptions.defaultValue, else false) and every NUMBER filter that has a numeric defaultValue (user's value, else that default).
Shape A — scalar field (staticFieldKey has no [0]):
{{contains([<values>];var("<fieldKey>"))}}
Shape B — array-backed field (staticFieldKey contains one [0], e.g. formIds[0], forms[0].data.id). [0] stands for "every item", not item zero. Split into arrayPath (before [0]) and itemPath (after [0]., may be empty):
itemPath: {{arraySome([<values>];contains(var("<arrayPath>");$_))}}{{arraySome([<values>];contains(arrayMap(var("<arrayPath>");"<itemPath>");$_))}}MUST:
id = the catalog filter id; fieldKey = staticFieldKey character for character, [0] included.
Read both from the trigger's full filters[]: Get Trigger By App Id And Key (§2 step 4), or a
Resolve Triggers result without basicFieldsOnly. A compact listing (basicFieldsOnly, a
fields projection, or your own local strip of the catalog) has no filter definitions; if your
copy lacks filters[], fetch the trigger — never invent an id or fieldKey.["x"]). Types match the field: strings quoted, numbers/booleans bare.; between arguments, double quotes only, no spaces, one non-empty expression per filter (an empty/missing filterExpression is a builder error), max 5 filters.{{…}} (values and the var path) are URI-encoded like every bracket literal (Automations Mapping Expressions §1).filters as the catalog lists them, depth-first (each filter, then its follow-ups): the builder re-appends each filter in that order on panel open and compares deep-equal.NEVER:
var("forms[0].id") — validates, but checks only the first item.contains(var("formIds");"x") (value outside an array) — the builder cannot read it back.stringEq, arrayIncludesAnyOf, not, …) in a filter — the filter panel only parses contains and arraySome.forms[0].ids[0]), a literal index (forms[1].id) or a leaf that is an object/array rather than a string/number/boolean. There is no valid expression: configure the supported filters, tell the user this one is unavailable, and offer a condition step if the data is in the payload.Updating an array-backed filter: change only the values array; keep the shape and fieldKey.
valueInput.required: true on a top-level filter → the filter MUST be saved. No user preference is not a reason to ask: pick a sensible default from the filter's own options (an "Any/All" option the trigger offers is fine); there is no wildcard expression. If it is also single-select (multiSelect: false), the trigger fires for exactly ONE chosen entity: a request for "any label/any service…" cannot be met with this trigger — offer: pick one, one automation per entity, or a different trigger. Check this during feasibility, before planning.ENTITY_SELECTOR follow-ups of ENTITY_SELECTOR parents are shown at all.entitySelector.queryFieldToFilterIdMapping ({"workflowId": "<parent-filter-id>"}): options depend on the parent's value. Choose the parent first, then fetch child ids scoped to it (workflow → stage, program → step).queryFieldToValueMapping ({"eventType": "RSVP"}): options are pre-narrowed; pick ids from that subset, nothing extra in the expression.Dependent example:
DYNAMIC_FIELD_KEY filtersThe field to filter on is itself selected (dynamicFieldKey.entitySelector, dependent on a parent such as the form). Resolve the parent first, then:
fieldKey and passes the same string to the value picker as its fieldTarget. For Wix Forms ("Option chosen on a form") that is the form field's target from the Forms API (multi_choice_5734) — not the dynamic-schema property key (field:multi_choice_5734, used only in var() paths of later steps) and not the field's uuid id.{{contains(["<value-1>"];var("<key>"))}}. The builder reads the chosen key back from the var(...) and treats the filter as required; Shape B is never used here.valueInput is an ENTITY_SELECTOR scoped to that field (form choices), use the choice option's value from the Forms API (what a submission stores, e.g. "Walter"), quoted and URI-encoded (§4.2). The value picker's own ids aren't public, so this is a best match, and Validate checks neither key nor values: tell the user to open the trigger in the builder and confirm the field and choice show by name.When implementedMethods.getDynamicSchema is true:
valueInput.reevaluateDynamicSchema: true (which form, which service).fieldKey verbatim, its string values); if no filter is saved, each reevaluateDynamicSchema filter's staticFieldKey with values: []:
payloadDataSchema and overlay dynamicSchema.properties on its properties (dynamic wins on a key clash). The dynamic schema alone usually lacks static fields such as contactId — never use it by itself.values: [] call returns. Never map or condition on a form-answer field without the form filter: use only static fields (contactId, submission time, …) or ask which form, set that filter, then fetch the dynamic schema.Later stages only: not available in stage 2; this section is published in stage 3.
appId + triggerKey came from Resolve Triggers on this site.id exists in the catalog trigger (or a follow-up); fieldKey is verbatim.BOOLEAN filter, and every NUMBER filter with a default, is saved.triggerValidationErrors.Last updated: 13 October 2026