Subchapter 19.9
references/automations/api-catalog.mdMarkdown28 KBView on GitHub
Every call this skill needs, as a public REST endpoint (base https://www.wixapis.com) and the
matching @wix/automations SDK method. Docs live under
https://dev.wix.com/docs/api-reference/business-management/automations/ — append to any
docs URL to get raw markdown. When a field name here and the docs disagree, the docs win.
.mdSave restrictions: Before a create, update or activation, follow the complete Automations Validation and Persistence (opens in a new tab).
- Apply its §1, §3–§4 and Update restrictions. The email-specific sections still use the older stage framework; their exclusions remain authoritative here.
- Never perform an operation explicitly excluded by that procedure, including email marked “Later stages only”.
- “Stage” denotes a publication grouping; “Later stages only” excludes that operation here; “not yet published” marks an unavailable guide. These are internal rollout markers: never quote or expose them to the user. Explain restrictions in product terms.
TL;DR
appId + key and schema-defined inputs. For read-only availability, start with the compact in-code action batch in §6; report its distinct-count/total evidence and both next-step options when an action is missing.INACTIVE → Get read-back; activate only when asked. Updates need the current
revision and are live on an active automation. Procedures (create, update, activate, read-back
— builder drafts are invisible publicly): Automations Validation and Persistence (opens in a new tab) §3.A linked complete email guide can replace the builder fallback only for operations the save procedure permits. Follow that guide completely; an API introduction or method page is not a substitute, and read-only inspection never authorizes a write.
SCOPE.CRM.SETUP-AUTOMATIONS) for automation operations. Generating a new email action mapping requires Manage Email Marketing (SCOPE.DC-PROMOTE.EMAIL-MARKETING) in the public email API (opens in a new tab). This scope alone does not supply a permitted email recipe: apply the Email configuration fallback above.
Entity lookups in other verticals need that vertical’s read scope
(resolve entity ids through the owning vertical’s documented read API, or ask the user).Authorization: <token> header — an OAuth app access token (client_credentials via
Create Access Token) or an account API key the site owner generated with the needed scopes.wix-site-id: <metaSiteId> on every call (all calls
here are site-level); never together with wix-account-id. OAuth app tokens are already bound
to one site instance.import { automationsV2, triggerCatalog, actionCatalog, activations } from '@wix/automations', used through a createClient Wix client with an auth strategy.metaSiteId once and use it for every call, read-back and
link. Ask the user to confirm it before the first write only when more than one site is in
context or the request doesn’t make clear which; a site fixed by the request or session is
confirmed. If anything points at another site, stop.| Purpose | REST | SDK |
|---|---|---|
| Validate | POST https://www.wixapis.com/automations-service/v2/automations/validate | validateAutomation(automation, options) |
| Create | POST https://www.wixapis.com/automations-service/v2/automations | createAutomation(automation) |
| Get | GET https://www.wixapis.com/automations-service/v2/automations/{automationId} | getAutomation(automationId) |
| Update | PATCH https://www.wixapis.com/automations-service/v2/automations/{automation.id} | updateAutomation(_id, automation) |
| Delete | DELETE https://www.wixapis.com/automations-service/v2/automations/{automationId} | deleteAutomation(automationId) |
| Query | POST https://www.wixapis.com/automations-service/v2/automations/query | queryAutomations(query) |
{automation, validationSettings?{actionIds[], skipProviderValidations}} → {status: VALID|VALID_WITH_WARNINGS|INVALID, triggerValidationErrors[], actionValidationErrors[]}. The main oracle; send the full object.
Reading errors: Automations Validation and Persistence (opens in a new tab) §2.{automation} with name, origin: "USER", configuration{status, trigger{appId, triggerKey}, rootActionIds, actions} → created automation (has id, revision). Does NOT
validate. Always status: "INACTIVE"; don’t send settings.automation. Use for read-back after every write and before every update.
trigger.overrideSchema and appDefinedInfo.overrideOutputSchema come back only when you
request them: fields: ["OVERRIDE_SCHEMA"] (REST ?fields=OVERRIDE_SCHEMA). Without it their
absence is not data loss (Create’s response omits them too).
Request overrides before complete-object updates and status changes too, not just creation read-back.{automation} incl. id and current revision → updated automation (revision
+1). Does NOT validate. Send the complete merged name + configuration, plus origin and
settings exactly as fetched — an Update without them fails INVALID_ORIGIN_TYPE. A
fieldMask (if your client exposes one) only selects what changes — set it to
configuration,name (what the builder sends); it doesn’t exempt you from sending origin /
settings. A stale revision is rejected. Changes are LIVE when status is ACTIVE. A success
response and a revision bump do not prove the change landed — merge, conflict handling and
read-back comparison: Automations Validation and Persistence (opens in a new tab) §3.
Capture the returned id: creating a site override of a preinstalled automation can change it.
Before any Update, including a rename-only edit, read Automations Validation and Persistence (opens in a new tab) §3
and run its applicable §4 checks; this endpoint summary does not replace that procedure.{}. Irreversible; only on explicit user request.{query{filter, sort, cursorPaging{limit ≤ 500, cursor}}} → automations[],
pagingMetadata.cursors.next. Returns only automations of apps installed on the site (incl.
overridden preinstalled ones), and never unpublished builder drafts. Full objects are large —
keep only id, name, configuration.status, configuration.trigger. If a filtered query fails on
a site with many automations, page unfiltered and filter locally.Automation object fields and limits (name ≤ 100 for the builder, description ≤ 2000,
origin, settings, configuration): Automations Graph and Data Model (opens in a new tab) §1.
Create/Update accept configuration.trigger.automationConfigMapping for scheduled/custom/webhook
configuration even where the docs omit it; use Automations Trigger Configuration (opens in a new tab) / Automations Schemas and Scheduling (opens in a new tab).
Calendar and timing workflows: before configuring a schedule, a future-date offset or a site-local calendar condition (such as a birthday check), read Automations Schemas and Scheduling (opens in a new tab) §4 for time-zone source precedence, what to do when no valid zone is available, and a user-named zone that differs from the site’s; read §5 for offsets. A time zone already returned for the target site is valid input to §4 and needs no Site Properties call.
| Purpose | REST | SDK |
|---|---|---|
| Triggers on this site | POST https://www.wixapis.com/v1/triggers/resolve | resolveTriggers(options) |
| Global catalog | POST https://www.wixapis.com/v1/triggers/query | queryTriggers(query) |
| One trigger | GET https://www.wixapis.com/v1/triggers/apps/{appId}/keys/{triggerKey} | getTriggerByAppIdAndKey(identifiers, options) |
| Dynamic payload schema | POST https://www.wixapis.com/v1/triggers/dynamic_schema | getTriggerDynamicSchema(appId, options) |
| Identity enrichment | POST https://www.wixapis.com/v1/triggers/identities_schema | getIdentitiesSchema() |
{basicFieldsOnly?, appId?, query{filter, paging{limit, offset}, fields?}} →
results[], paging. Installed apps only. basicFieldsOnly: true for browsing (drops payload
schema, config schema, filters).{query{filter, …}} → results[] (filterable: appId, triggerKey,
displayName, implementedMethods.*). Includes apps NOT installed on the site — never build on
a trigger Resolve didn’t return.trigger with payloadDataSchema, filters[], automationConfigSchema,
implementedMethods. The preferred way to hydrate a shortlisted trigger.{appId, triggerKey, selectedFilterOptions[{fieldKey, values[]}] (≤ 5)} →
dynamicSchema. Only when implementedMethods.getDynamicSchema is true, and only after the
filters that drive it are chosen — no filter chosen ⇒ form answers are unknown, not absent
(request and merge: Automations Trigger Configuration (opens in a new tab) §5).{} → identitiesSchema{contact, member, …} — shape of the contact /
member objects added when payload fields carry identityType.Trigger objects have no free-text description and display names are ambiguous — decide by the payload schema (Automations Trigger Configuration (opens in a new tab) §2).
| Purpose | REST | SDK |
|---|---|---|
| Actions on this site | POST https://www.wixapis.com/v1/actions/resolve | resolveActions(options) |
| Global catalog | POST https://www.wixapis.com/v1/actions/query (and /query-latest) | queryActions(query), queryLatestActions |
| Version active on the site | GET https://www.wixapis.com/v1/actions/apps/{appId}/keys/{actionKey} | getRuntimeAction(identifiers) |
| Latest version | GET https://www.wixapis.com/v1/actions/latest/apps/{appId}/keys/{actionKey} | getLatestAction(identifiers, options) |
| Dynamic input schema | POST https://www.wixapis.com/v1/actions/dynamic-input-schema | getActionDynamicInputSchema(appId, options) |
| Dynamic output schema | POST https://www.wixapis.com/v1/actions/dynamic-output-schema | getActionDynamicOutputSchema(appId, options) |
{query{filter, paging{limit, offset}, fields?}} → actions[], paging. Offset
paging only (cursorPaging is rejected). Entries carry full inputSchema, outputSchema,
uiSchema — large. Filter by appId/actionKey. Keep direct-to-context pages ≤ 25; for read-only availability use the compact in-code batch in §6.action. Use this schema when configuring for this site. Latest version
is for reference only.{appId, actionKey, inputMapping} → {inputSchema, uiSchema}. Call when an
input property has updateSchemaOnChange: true (no public getDynamicInputSchema flag);
re-call after changing such a field.{appId, actionKey, inputMapping} → outputSchema; bulk
(bulkGetActionDynamicOutputSchemas, POST /v1/actions/bulk/dynamic-output-schema, ≤ 20 items) →
results[]{itemMetadata{success, error}, outputSchema}. Only after that action’s mapping is
final. For wix_automations-llm_call fields defined by your output configuration, read Automations Schemas and Scheduling (opens in a new tab) §3 before constructing overrideOutputSchema: that procedure defines merging with the static output, property metadata and override-aware Get read-back. Then declare the fields you chose; do not call this SPI to discover them. For other upstream actions whose configured output is needed, this is a read-only discovery call (no public flag says which are dynamic); an error does not establish additional fields — keep the static outputSchema.
Merge into the static schema. A failed bulk item = unknown schema, not empty.POST https://www.wixapis.com/v1/actions/generate-input-mapping-from-intent)
is AI-backed — don’t call it. Actions you can’t map from their schema: Automations Action Configuration (opens in a new tab) §5.1.Action objects: appId, actionKey, displayName, description, inputSchema, outputSchema,
interfaceConfiguration{type: GENERIC\|WIDGET_COMPONENT, genericOptions.uiSchema},
implementedMethods{validateConfiguration, getQuotaInfo} (public). Resolve Actions has no
basicFieldsOnly option (only Resolve Triggers does). Mapping rules: Automations Action Configuration (opens in a new tab).
POST https://www.wixapis.com/automations/v1/events/test-automation,
testAutomation(identifierType, options): {identifierType: "AUTOMATION", automationIdentifier{automationId}, payload} → activationId. Runs every action for real
(skips delays, works on INACTIVE) — explicit user authorization only; payload, consent and
reporting: Automations Validation and Persistence (opens in a new tab) §5.basicFieldsOnly: true and
pages ≤ 25. For read-only action-availability questions, start inside execution code with
resolveActions({query: {paging: {limit: 100, offset: 0}}}), then compact locally before
returning anything to the reasoning context. This bounded batch avoids offset boundaries
when the catalog fits in one response; 100 is an execution bound, not an API maximum.
appId, key, display name) and the schema fields needed
for requested available candidates. Never return the raw catalog or unrelated schemas.appId + actionKey. A single response proves completeness only when
paging.total is numeric, paging.tooManyToCount is false or absent, and the distinct
count equals that total. A large requested limit alone is not proof.fields) may be ignored; never rely on it to keep a full catalog small.appId + trigger/action key, together with each page’s offset and reported paging.total.
Cache schemas already returned by Resolve too. Count the map entries, not raw page lengths;
overlapping entries do not prove completeness. Search that same map for every requested
capability. Do not restart a scan just to count or inspect pages you already fetched, and
do not add an exact-key probe after a complete scan proves that action absent. If exhausted
pages leave the distinct count below the reported total, report incomplete evidence and
“not found” rather than claiming absence or repeatedly scanning. Dynamic schemas are the
exception to fetching schemas once: re-call after changing an updateSchemaOnChange field.{"appId": "...", "actionKey": "..."}). Full schemas only for the chosen few.appId, triggerKey/actionKey, and $in on the keys (both
Resolves); on Resolve Triggers also displayName $contains / $in (inside $or too) and
triggerKey $startsWith. Resolve Actions rejects displayName filters — search names
locally. A rejected filter → fall back to small pages.sort: [{fieldName: "id"}] fails with SORT_PARSER_ERROR on both Resolves.
Unsorted offset pages can overlap: page until paging.total, de-duplicate by appId+key,
and count distinct entries. An action or trigger is proven missing only after a complete,
de-duplicated scan (distinct count = paging.total). Report the evidence (“scanned N distinct
of paging.total N”); without that proof say it was “not found in the installed catalog”,
never that it is not installed. Either way, list the closest related entries you did find with
their returned appId + key and display name — don’t omit them, and don’t fetch their schemas
unless the user asks. A shortcut:
take the appId from a related action, then Resolve by appId.Discovery hints:
Installed-capability answers (“does my site support…?”):
Available options: give one row per requested trigger/action with availability, the returned appId + triggerKey/actionKey, display name and schema-defined required/optional inputs. Include the actual app IDs in the answer. Use existing entity keys when a schema asks for keys; do not invent them.
Schema reads: hydrate only requested available candidates whose schemas are not already cached. A similar keyword match is not another requested option. Reads needed to finish a separately requested available option remain appropriate.
Proven absent: report “scanned N distinct of total N” from the cached complete scan. Stop discovery for that action, including exact-key/runtime/schema probes. Its inputs are unknown; never fill that gap from a standalone vertical API.
Incomplete evidence: if the distinct count does not match the total, report both counts and only “not found in the installed catalog.” Stop instead of restarting scans or claiming the action is unavailable.
Next steps: offer both making the providing app/action available and letting the user choose a real installed alternative. Identify that alternative by its returned app ID, key and name. Do not guess an app name or installation procedure.
Stay site-scoped: do not query global catalogs or standalone APIs for this question. Use them only for a separately requested platform-wide discovery or standalone API workflow, clearly labeled as such.
Search by concept with a keyword ladder (“chat” → “message”). Common aliases: send a chat
message to the contact = send-message (not inbox-send-message); a note about a contact in
the site owner’s Inbox, nothing sent to the contact = inbox-send-message (“Show in Inbox”);
email to anyone, incl. the site
owner = triggered-emails (follow the numbered Email configuration procedure before resolving it; never the deprecated send-mail / "Get an email"); task =
createTask; labels = addLabelsToContact / remove_labels_to_contact; create a contact =
contacts-create_contact (for triggers whose payload has no contact, e.g. webhooks).
For Create a contact, inputMapping is for example {"contact":{"firstName":"{{var(\"firstName\")}}","email":"{{var(\"email\")}}"},"duplicationStrategy":"UPDATE_CONTACT"}. The contact field contains mapped destination keys; use only its own schema properties and values with real sources. Do not add Create a contact when the trigger already supplies that contact.
Near-duplicates exist (booking_canceled vs bookings_canceled; new Wix Forms app vs legacy
“Form submitted”). Compare payload schemas and filters; prefer the one whose entities you can
actually find on the site (resolve entity ids through the owning vertical’s documented read API, or ask the user).
Enum-like fields often list legal values only in the field description (e.g. paymentStatus
NOT_PAID / PAID). Read descriptions before mapping user words; never invent enum values.
Node N may read the trigger payload + each ancestor‘s output (under its namespace) + variables + identity enrichment. Recipe and fetch order: Automations Graph and Data Model (opens in a new tab) §4.
Entity ids (forms, labels, services, pipeline stages…): resolve them through the owning vertical’s documented public read API, or ask the user for the exact entity. Confirm ids and parent/fixed filters with successful reads. Never save a display name, invent an id or derive an endpoint from a provider key. Failed or incomplete lookups mean unknown options, not an empty site.
Not public or not available through the general Automations API:
INACTIVE; the user activates. Builder drafts are invisible.