Skip to main content

Node Operations

This document describes every resource and operation available in the Workflow Interaction Layer node as seen in the n8n UI.

Auto-Populated Fields​

The node automatically injects two fields on every create operation; you do not need to set them:

FieldSourceDescription
workflowIdthis.getWorkflow().idThe ID of the workflow containing this node
workflowInstanceIdthis.getExecutionId()The current execution ID

Resource: Message​

Create​

ParameterTypeRequiredDefaultDescription
Actor IDstringYes-Target actor identifier
Actor TypeoptionsYesuseruser, group, role, system, other
TitlestringYes-Message title
Bodystring (multiline)Yes-Message body text
MetadataJSONNo{}Arbitrary JSON metadata

Get Many / Get Messages by Actor ID​

Both operations support actor, workflow instance, since, and limit filters as shown in the n8n UI.

Resource: Action​

Create​

Creates a new action in the WIL API layer.

ParameterTypeRequiredDefaultDescription
Actor IDstringYes-Target actor identifier
Actor TypeoptionsYesuseruser, group, role, system, other
Action TypeoptionsYesgetapprovalgetapproval, showform, waitonevent
Action TitlestringNo-Optional title for the action
HTMLstringYes, for getapproval-HTML content shown before approval options
OptionslistYes, for getapproval-Repeatable approval option labels. At least one option is required.
CHEFS Form NamestringYes, for showform-CHEFS form name shown for the form action
CHEFS Form IDstringYes, for showform-CHEFS form ID to render
CHEFS Form API KeystringYes, for showform-CHEFS form API key used server-side
CHEFS Form Submission IDstringNo-Existing CHEFS form submission ID to prefill from prior data
Form Pre-Fill DataJSONNo{}Object of CHEFS field API names and values
Send Form Data to Callback (Skip CHEFS Submission)booleanNofalseFor showform. When on, the form data is sent to the callback URL instead of submitted to CHEFS
Callback DataoptionsNofullFor showform + skip on. Full Form Data or Selected Fields Only
Field Selection ModeoptionsNokeyValueShown for Selected Fields Only. UI Field Pairs or JSON
Fields to SendlistYes, for Selected Fields Only-Repeatable Output Key + Source Path (dot-notation) pairs
Fields to Send (JSON)JSONYes, for Selected Fields Only{}Object mapping output keys to dot-notation source paths
Missing Field BehavioroptionsNoreturnNullShown for Selected Fields Only. Return Null or Omit Field
PayloadJSONYes, for waitonevent{}Free-form wait-on-event payload, for example { "eventName": "clicked" }
Callback MethodoptionsNoPOSTnone, POST, PUT, PATCH
Callback URLstringYes (when Callback Method != None)-URL called when action completes
Callback Payload SpecJSONNo{}Template for expected callback body
Due DatestringNo-RFC 3339 timestamp
PriorityoptionsNonormalnormal or critical
Check InstringNo-RFC 3339 reminder timestamp
MetadataJSONNo{}Arbitrary JSON metadata

Action Title is sent as top-level actionTitle; it is not nested inside payload.

Payload by Action Type​

  • getapproval builds payload { "html": "...", "options": ["Yes", "No"] }.
  • showform builds payload { "formName": "...", "formId": "...", "formApiKey": "...", "submissionId": "...", "formPreFillData": {} }. When Send Form Data to Callback is enabled, "skipChefsSubmission": true is added. When Callback Data is Selected Fields Only, "callbackFieldMappings": [...] and "callbackMissingPathBehavior": "returnNull" | "omit" are also added.
  • waitonevent uses the raw Payload JSON field, matching the previous behavior.

getapproval HTML Details​

When actionType is getapproval, the node builds the payload from the HTML and Options fields:

{
"html": "<p>Do you approve this request?</p>",
"options": ["Yes", "No"]
}

HTML and at least one approval option are required. The node rejects getapproval actions with missing HTML or an empty options list because the user would otherwise have no useful prompt or no way to respond.

The external UI sanitizes the HTML before rendering it. Inline scripts, event handlers, data attributes, and arbitrary inline CSS are not allowed. This keeps approval prompts safe while still allowing structured content.

Allowed tags include:

CategoryTags
Textp, br, strong, b, em, i, u, s, span, div
Headingsh1, h2, h3, h4, h5, h6
Listsul, ol, li
Tablestable, thead, tbody, tr, th, td
Othera, img, hr, blockquote, code, pre

Allowed attributes include:

AttributeTypical use
href, target, relLinks
src, alt, width, heightImages
colspan, rowspanTable cells
class, idNon-sensitive identifiers only

The renderer applies controlled styles for headings, paragraphs, lists, blockquotes, code, links, images, and tables. Do not rely on inline CSS such as style="...", border, cellpadding, or cellspacing; those are stripped or ignored. Use normal semantic HTML and let the UI apply the approved styling.

Example: Simple Approval​

HTML field:

<h2>Approve Request</h2>
<p>Please confirm whether this request should proceed.</p>

Options:

Approve
Reject

Generated payload:

{
"html": "<h2>Approve Request</h2><p>Please confirm whether this request should proceed.</p>",
"options": ["Approve", "Reject"]
}

HTML field:

<h2>Consent to Share Income Information</h2>

<p>
By selecting <b>Yes</b>, you authorize us to collect and share your income information with authorized organizations
to determine your eligibility and process your request.
</p>

<table>
<tr>
<th colspan="2">Consent Summary</th>
</tr>
<tr>
<td><b>Purpose</b></td>
<td>Determine eligibility and process your request.</td>
</tr>
<tr>
<td><b>Information</b></td>
<td>Income information provided by you or authorized sources.</td>
</tr>
<tr>
<td><b>If you choose No</b></td>
<td>We may not be able to complete your eligibility assessment.</td>
</tr>
</table>

<blockquote>Your information will be used only for this purpose and handled securely.</blockquote>

Options:

Yes
No

Generated payload:

{
"html": "<h2>Consent to Share Income Information</h2><p>By selecting <b>Yes</b>, you authorize us to collect and share your income information with authorized organizations to determine your eligibility and process your request.</p><table><tr><th colspan=\"2\">Consent Summary</th></tr><tr><td><b>Purpose</b></td><td>Determine eligibility and process your request.</td></tr><tr><td><b>Information</b></td><td>Income information provided by you or authorized sources.</td></tr><tr><td><b>If you choose No</b></td><td>We may not be able to complete your eligibility assessment.</td></tr></table><blockquote>Your information will be used only for this purpose and handled securely.</blockquote>",
"options": ["Yes", "No"]
}
Example: Review Checklist​

HTML field:

<h3>Review Required</h3>
<p>Confirm that the following checks are complete before approving:</p>

<ul>
<li>Applicant identity has been verified.</li>
<li>Required documents have been reviewed.</li>
<li>No duplicate request is active.</li>
</ul>

<hr />

<p><b>Decision:</b> choose one option below.</p>

Options:

Approve
Needs Changes
Reject

Generated payload:

{
"html": "<h3>Review Required</h3><p>Confirm that the following checks are complete before approving:</p><ul><li>Applicant identity has been verified.</li><li>Required documents have been reviewed.</li><li>No duplicate request is active.</li></ul><hr><p><b>Decision:</b> choose one option below.</p>",
"options": ["Approve", "Needs Changes", "Reject"]
}

showform Details​

FieldTypeRequiredDescription
formNamestringYesCHEFS form name shown for the form action
formIdstringYesCHEFS form ID to render
formApiKeystringYesCHEFS form API key used server-side. The backend strips it before returning actions to the UI.
submissionIdstringNoExisting CHEFS form submission ID used to prefill the form from prior submission data
formPreFillDataobjectNoKey-value pairs matching CHEFS form field API names
skipChefsSubmissionbooleanNoSet to true by the Send Form Data to Callback toggle. Only present in the payload when enabled.

If submissionId is provided, it takes full priority: the form loads the existing submission data and formPreFillData is ignored.

Send Form Data to Callback (Skip CHEFS Submission)​

By default a showform action submits the completed form to CHEFS, which stores a submission record. The UI then sends the resulting submission ID to the callback URL, and the workflow typically fetches the submission data from CHEFS afterwards.

Enable Send Form Data to Callback when you want the workflow to receive the raw form data directly, without CHEFS storing a submission. The form is still rendered and validated by CHEFS — only the final storage step is skipped.

ToggleCHEFS submission created?Callback body sent to Callback URL
Off (default)Yes{ "formId": "...", "submission_id": "..." }
OnNo{ "formId": "...", "formData": { ...all form fields } }

In both cases the user sees the same "Form submitted successfully" confirmation after completion.

When the toggle is on, your callback/webhook node must read formData instead of submission_id. Because no submission is stored in CHEFS, the formData object is the only record of the response — persist it in the workflow if you need it later.

Example payload (toggle on):

{
"formName": "Income Verification",
"formId": "11111111-1111-1111-1111-111111111111",
"formApiKey": "...",
"skipChefsSubmission": true
}

Example callback body received by the workflow (toggle on):

{
"formId": "11111111-1111-1111-1111-111111111111",
"formData": {
"firstName": "Nicholas",
"lastName": "Cognito",
"annualIncome": 52000
}
}
Callback Data: Full Form Data vs Selected Fields Only​

When Send Form Data to Callback is on, a Callback Data option appears:

  • Full Form Data (default) — the entire form response is sent as formData, exactly as shown above.
  • Selected Fields Only — you define which fields to send. Only those fields ever leave the user's browser, and the workflow receives a smaller, predictable payload. This uses the same dot-notation mapping style as the CHEFS Submission Extractor node, but applied in the browser before the callback fires.

With Selected Fields Only you provide a set of mappings, each with:

FieldDescription
outputKeyThe key name the workflow receives in formData
sourcePathDot-notation path into the submitted form data, e.g. firstName or address.city

Mappings can be entered as UI Field Pairs or as a JSON object ({ "city": "address.city" }). At least one field is required — the node rejects the action at configuration time if none are provided.

Missing Field Behavior controls what happens when a sourcePath is not present in the submitted data:

  • Return Null (default) — the outputKey is included with a null value.
  • Omit Field — the outputKey is left out of formData entirely.

Example payload (Selected Fields Only):

{
"formName": "Income Verification",
"formId": "11111111-1111-1111-1111-111111111111",
"formApiKey": "...",
"skipChefsSubmission": true,
"callbackFieldMappings": [
{ "outputKey": "firstName", "sourcePath": "firstName" },
{ "outputKey": "city", "sourcePath": "address.city" }
],
"callbackMissingPathBehavior": "returnNull"
}

Example callback body received by the workflow (Selected Fields Only):

{
"formId": "11111111-1111-1111-1111-111111111111",
"formData": {
"firstName": "Nicholas",
"city": "Victoria"
}
}

The user still sees the same "Form submitted successfully" confirmation. Field selection happens entirely in the browser, so fields you do not map are never transmitted to the callback.

Create, Wait and Get Data​

Creates an action exactly like Create (same Action Type, Actor, form/approval/wait-on-event fields, Due Date, Priority, Check In, Metadata), then pauses the workflow execution until the actor completes it, and outputs the data WIL sends back on completion.

ParameterTypeRequiredDefaultDescription
(all Create fields above, except Callback Method / Callback URL / Callback Payload Spec)
Limit Wait TimebooleanNofalseWhether to resume automatically after a limit if the actor never responds
Limit TypeoptionsNoafterTimeIntervalShown when Limit Wait Time is on. After Time Interval or At Specified Time.
AmountnumberNo1Shown when Limit Type is After Time Interval. The amount of time to wait.
UnitoptionsNohoursShown when Limit Type is After Time Interval. seconds, minutes, hours, or days.
Max Date and TimedateTimeYes, when Limit Type is At Specified Time-Shown when Limit Type is At Specified Time. The exact date/time to resume at.

Callback URL and Callback Method are not configurable for this operation. They are set automatically to POST against this execution's resume URL ($execution.resumeUrl), so the WIL backend calls back into this node when the actor completes the action.

For showform, the same Send Form Data to Callback (Skip CHEFS Submission) and Callback Data (Full Form Data / Selected Fields Only) options from Create are available, with identical behavior:

  • Skip off (default): the actor's response arrives as { "formId": "...", "submission_id": "..." }. The workflow is responsible for fetching the full submission from CHEFS afterward if needed (for example with the CHEFS Submission Extractor node).
  • Skip on: the actor's response arrives as { "formId": "...", "formData": { ... } } (or a subset of fields, if Callback Data is set to Selected Fields Only) — no separate CHEFS submission is created.

Detecting a timeout — use $execution.customData, not this node's output​

On a real timeout, this node's output cannot be used to detect that a timeout happened. n8n does not re-run node code when a local wait time limit elapses — it simply resumes downstream nodes using this node's input data (the same items that fed into it), not any value the node's own code returned before pausing. This matches n8n's native Wait node's own behavior for time-based resumes. Concretely: on a real actor completion, $json contains the actor's response (see above); on a timeout, $json contains whatever this node's input was — not a status field, not the action ID.

To reliably detect a timeout and get the action ID afterward, this operation stashes both in execution-scoped customData instead, which survives regardless of how the execution resumes:

KeySet toWhen
wilActionIdthe created action's IDAlways, right after the action is created (before the wait starts)
wilActionStatuswaitingRight after the action is created (before the wait starts)
wilActionStatuscompletedWhen the actor actually completes the action (the callback arrives)

There is no expired value written by this node — n8n has no hook that runs at the exact moment a wait time limit elapses, so nothing can flip the status then. If wilActionStatus is still waiting after this node resumes, that is the timeout signal.

Read customData from a Code node, not a plain expression field. $execution.customData.get(...) has been confirmed to resolve reliably inside a Code node's JS, but not consistently inside a plain ={{ ... }} expression on an arbitrary downstream node's parameter (an n8n-platform quirk, not something this node controls). Bridge the values into regular $json fields first:

Create, Wait and Get Data
→ Code node:
for (const item of $input.all()) {
item.json.actionId = $execution.customData.get("wilActionId");
item.json.actionStatus = $execution.customData.get("wilActionStatus");
}
return $input.all();
→ IF {{ $json.actionStatus }} != "completed"
→ Action: Update (Action ID = {{ $json.actionId }}, Status = Expired)

Note: this operation pauses the entire n8n execution (not just this node) until resumed, so it only supports a single item at a time — if multiple items reach this node, only the first is processed.

Other Action Operations​

  • Get retrieves a single action by ID.
  • Get Many lists actions with optional actor, workflow instance, since, and limit filters.
  • Update updates action status. To delete an action, update status to deleted.