Action node, targets, data, and return values
In 0.80.3, the editor displays Action, while exported flow JSON retains the persisted type api-call-service; the node version is 7. Actions cause external side effects in HA. This chapter therefore uses only disabled nodes and complete placeholders to explain the contracts for action, target, data, input overrides, queues, responses, and errors. It provides no real, directly executable targets.
Why this chapter matters
An Action is the boundary at which an event or query flow crosses into side effects. The Events: state and Current State nodes discussed in earlier chapters primarily read data; an Action can control devices, change helpers, send notifications, or invoke other HA functionality. A single incorrect target, an allowed payload override, or treating the reconnect queue as a reliable work queue can turn one test into multiple real operations.
Every call raises at least three distinct questions: action determines which HA operation to perform; target determines which entity, device, area, floor, or label it affects; and data carries arguments specific to that action. Putting an entity ID into arbitrary data, putting message text in the target, or assuming every action returns a payload all violate the contract.
"d": true, and its Server, action, and entity values are all PLACEHOLDER_*. Inspect it offline only. Do not Deploy it, remove its disabled flag, or connect it to a real trigger until the security review, target-owner approval, and recovery plan are complete.Action UI, persisted type, and v7 data flow
In the pinned version, the palette label is action and the NodeType key is Action, but the type in Node-RED flow JSON remains api-call-service. “Call Service” in older flows and documentation identifies the legacy name only. Do not revert the current UI terminology or manually change the JSON type to action. The v7 migration retains compatibility fields, but new designs should use the single action field rather than separate domain and service fields supplied by a message.
After parsing the action, the controller splits it at the first period into a domain and service; if either part is missing, the action format is invalid. An action taken from configuration is rendered with Mustache and then converted to lowercase. The target combines the five v7 configuration groups with an allowed msg.payload.target; data is merged according to the JSON or JSONata, context, and payload rules. The controller then calls HA WebSocket call_service.
| Layer | v7 persisted field | Responsibility | Safe default |
|---|---|---|---|
| Operation type | action | An HA action in domain.service form | PLACEHOLDER_HA_ACTION; reject input overrides |
| Target | entityId, deviceId, areaId, floorId, labelId | Select the scope of the call | One minimal placeholder; prohibit broad default scopes |
| Arguments | data/dataType | Action-specific arguments | Fixed schema and types; reject additional fields |
| Dynamic merging | mergeContext, mustacheAltTags | Context or a JSON template/JSONata | Leave blank unless needed; if used, restrict keys and data owners |
| Execution boundary | queue, blockInputOverrides | Disconnected behavior and message overrides | none, true |
| Output | outputProperties | Map sent data, results, or other values | Output only required fields, never secrets or complete attributes |
The example demonstrates this safe baseline exactly: v7, queue set to none, Block Input Overrides set to true, debugenabled set to false, placeholders as the only targets, and the entire Action disabled. Its data is a static illustrative string. This does not mean that the action accepts that argument, and importing the flow does not send it automatically.
Review an Action as a non-executable draft
- Inspect the safe example without running it.
Open 07-action.json and verify
type: "api-call-service",version: 7, andd: true. The Inject node is manual and unscheduled, but the Action must remain disabled; do not confuse “manual” with “free of side effects.” - Describe a specific but non-executable scenario.
For example: “An approved test-notification draft for one test recipient only, with the fixed content TEST_ONLY_NO_SEND.” The JSON must still contain only
PLACEHOLDER_HA_ACTIONandPLACEHOLDER_ENTITY_ID, not a real action, notification endpoint, or device. - Separate action, target, and data.
Put only a placeholder operation name in action; select only one type of minimal placeholder ID as the target; and list only fixed fields permitted by that action’s official schema in data. Reject unknown fields, template input, and the complete msg object.
- Lock down input and the queue.
Keep Block Input Overrides=true and queue=none. Document which payload keys could affect action, target, or data if the lock were removed, but do not disable it for “convenience.” On disconnection, prefer an explicit failure to deferring a control operation until an uncertain future time.
- Define the output and error contracts.
If the action has no response, retain only a sanitized correlation ID. If it does return a response, map it to a property such as
msg.actionResultand validate its shape. Catch and Status handling should record only the placeholder action, error category, and time—not data content or a real target. - Complete the risk and recovery review.
The target owner must confirm the scope, whether duplicate calls are safe, the queue and reconnect policy, rate limits, manual stop procedure, and recovery plan. The review record must precede any environment change; this chapter does not instruct you to enable, deploy, or send an Action.
{
"status": "DISABLED_NON_EXECUTED_DRAFT",
"action": "PLACEHOLDER_HA_ACTION",
"target": { "entity_id": ["PLACEHOLDER_ENTITY_ID"] },
"data": { "message": "TEST_ONLY_NO_SEND" },
"blockInputOverrides": true,
"queue": "none"
}
The block above is review documentation, not an importable flow or an executable HA request. Do not replace action and target with real values and then use it directly; whether data is valid depends entirely on the schema of the action that may later be approved.
Input overrides, data merging, and the side-effect threshold
v7 InputService can read msg.payload.action, msg.payload.target, and msg.payload.data from a message; legacy compatibility also recognizes payload domain and service fields. When Block Input Overrides=true, InputService disables these message overrides: action comes from configuration, target comes from the five configured selectors, and payload data does not participate in data merging. Every Action should retain this safe default.
If block=false, a payload action can replace the configured action, payload target is deep-merged with the configured target, and payload data has the highest precedence in data merging. Even if an upstream node intends to change only one text field, an attacker or faulty node could change the action and its target. For any HTTP, MQTT, webhook, Dashboard, Assist, or cross-flow input, type checking alone is insufficient. Establish an action allowlist, a target allowlist, and a data schema, then construct a new, clean msg object.
Data can use JSONata or JSON. JSON mode performs Mustache rendering before parsing; optional alternate tags change only the template delimiters for the data field. JSONata runs through the Node-RED evaluator. Neither one is HA Jinja or JavaScript. Never treat untrusted strings as templates, and never place tokens, headers, or credentials in data or context.
mergeContext names one context key. The node reads the global object first, overlays the flow object, and—when input overrides are allowed—finally overlays payload data; configured data has the lowest precedence. block=true removes only the payload layer, so context can still override configuration. Before enabling mergeContext, restrict who can write that flow/global key, define its object shape and retention period, and establish a clearing procedure.
Entity, device, area, floor, and label targets
The v7 editor’s Target selector supports five ID types. Configuration fields become HA target keys: floor_id, area_id, device_id, entity_id, and label_id. An empty configuration array omits that key; at runtime, a single entry may become a string while multiple entries remain a collection. Values can render environment variables or Mustache, so environment and context values also belong within the review boundary.
| Target type | Non-executable placeholder | Scope risk | Review question |
|---|---|---|---|
| entity | PLACEHOLDER_ENTITY_ID | Most precise, but renaming or replacing the ID can break it | Is this a dedicated test entity, and does it permit this action? |
| device | PLACEHOLDER_DEVICE_ID | One device can contain multiple entities and capabilities | Is the action’s actual scope on the device clear? |
| area | PLACEHOLDER_AREA_ID | Membership changes as entity and device assignments change | Could new members be included without review? |
| floor | PLACEHOLDER_FLOOR_ID | Broader than an area and may span multiple spaces | Is an entire floor truly necessary? Deny it by default. |
| label | PLACEHOLDER_LABEL_ID | Label membership can expand dynamically | Who can change the label, and are changes monitored? |
Being selectable in the UI does not mean that every action accepts every target type. The editor filters or hides the target selector according to HA service metadata, and an unknown action may lack reliable metadata. Check the action documentation and services metadata for the target HA version. Place an entity ID exactly where the action schema specifies; do not invent fields from screenshots or rely on compatibility relocation.
fields.entity_id, data does not already contain entity_id, and the merged target.entity_id is a single string, it warns and temporarily moves that value into data. This compatibility path does not move an array target. The behavior is documented for removal in 1.0; do not depend on it, and correct affected flows before upgrading.Several target types can be merged at once, potentially producing a union of scopes rather than narrowing the selection by intersection. A safe draft uses only one, most precise target type at a time. Treat areas, floors, and labels as dynamic groups and recheck their members before every call. Documentation, Debug output, and issues must show placeholders only, never real IDs.
Action-dependent data, queues, and concrete safe scenarios
The selected HA action defines the data schema; there is no guarantee of a universal message, brightness, or temperature field. The editor can display descriptions and example data from HA services metadata, but that metadata belongs to the connected environment and should not be fabricated in a UI or screenshot. Even loaded example data is only a draft: remove unnecessary fields and verify every type, range, and unit.
Keep all three concrete safety scenarios non-executable:
- Test-notification draft: action=
PLACEHOLDER_HA_ACTION, target=PLACEHOLDER_ENTITY_ID, with only the fixed valueTEST_ONLY_NO_SENDin data. Verify that the recipient scope is minimal, the content contains no state attributes, and duplicate delivery has a defined policy; keep the example node disabled. - Test device-state-change draft: use only
PLACEHOLDER_DEVICE_IDas the target and name no operable domain or entity. First prove that a duplicate call can be reversed, someone will monitor the physical site, and an independent stop path exists; do not connect a real event. - Area-maintenance draft: use only the corresponding placeholder for an area, floor, or label, and first export its membership for human review. Reject any membership beyond one test scope, and do not use a queue to deliver missed operations.
Queue settings affect messages only while HA is disconnected: none immediately raises NoConnectionError; first retains only the first message; last replaces the retained message with the latest one; and all appends every message to an in-memory array. Once the connection is ready, the controller retrieves entries with pop(), so an accumulated set is processed from the end of the array; do not assume FIFO order. The queue is not durable, has no hard limit verifiable in this chapter, and does not provide exactly-once delivery.
| Queue | While disconnected | Risk | Recommendation |
|---|---|---|---|
none | Raise an error immediately | Requires explicit failure handling | Safe default; do not defer control |
first | Retain the first message only while the queue is empty | Later intent is lost, and the retained intent may be stale at reconnection | Do not use without strict proof of timeliness |
last | Replace the retained message with the latest one | Intermediate events are lost, and the latest intent may still become stale | Requires a version or timestamp gate before evaluation |
all | Retain every message in memory | Unbounded growth, a reconnection burst, and non-FIFO processing | Prohibit for control Actions |
If the business truly requires a reliable work queue, use a dedicated architecture with persistence, ordering, deduplication, deadlines, cancellation, and a dead-letter contract. The Action node’s four queue options are not a substitute. After recovering from a disconnection, query Current State again instead of blindly replaying stale control operations.
Output properties, return_response, and errors
Response support and response shape depend on the selected action. Do not assume every action returns data or that results are always written to msg.payload. A destination property is written only when Output Properties explicitly maps a value to it.
response, the outgoing call_service sets return_response to true; without response metadata, it sets the flag to false. On older HA versions, it does not set the value. This chapter’s baseline still follows the package README prerequisite of HA 2024.3+; this conditional only explains the runtime boundary.When the call promise resolves, the controller exposes response?.response as the Output Properties source results. It also combines the domain, service, data, and target actually sent into the sentData source.
| Output value type | Contents | Possible condition | Recommended mapping |
|---|---|---|---|
sentData | domain, service, data, and target | May contain environment IDs or sensitive arguments | Do not output the complete object; extract only a sanitized correlation field |
results | The response portion of the HA call response | Action-dependent and possibly undefined | Write to msg.actionResult, then validate its shape |
msg | The input message is available for mapping | May contain external data | Preserve only necessary allowlisted fields |
| No output properties | Send the original message after success | The payload does not automatically become the result | Downstream nodes must not assume the payload is a response |
return_response is a WebSocket call flag chosen by the wrapper from action metadata, not a general-purpose argument to put in data. The HA action defines whether it supports or requires a response and what that response contains. Verify rolling behavior against the official documentation and services metadata for the target HA version.
Common errors include being disconnected with queue=none, an invalid action format, unparseable JSON, a schema-invalid input, a rejected HA call, or a connection failure during the call. None of these produces a successful output mapping. Use Catch to capture errors and Status to observe state, terminating the error branch in a bounded Debug or alerting design. Never change the target automatically and retry, or write complete data, responses, tokens, or real IDs to logs.
A retry policy must account for whether the action is idempotent. A network timeout can occur after HA has executed the action but before Node-RED receives the response, so an immediate retry may duplicate the side effect. A safe design requires a request or correlation ID, action-specific verification, a retry limit, backoff, and manual recovery—not merely checking whether output arrived.
Troubleshooting
- The palette shows Action, but the export says api-call-service: this is the expected persisted type in 0.80.3. Do not change it manually to action or rebuild the node simply because of its legacy name.
- The action format is invalid: keep the node disabled and confirm that the draft uses the complete
PLACEHOLDER_HA_ACTION; any subsequently approved value must use domain.service form. Do not guess with a real action merely to test it. - The target is broader than expected: check whether entity, device, area, floor, and label targets coexist; whether payload.target is merged when block=false; and whether area, floor, or label membership changed. Abort the change and return to one placeholder allowlist entry.
- Configured data was replaced by another value: check mergeContext. Even with Block Input Overrides=true, flow or global context can override configured data. Clear the contaminated key, inventory its writers, and enforce a fixed schema.
- msg.payload has no response after success: this can be normal. Confirm that the action metadata declares a response, then explicitly map results to the chosen property in Output Properties. Do not fabricate a result for an action with no response.
- Stale operations appear after reconnection: stop the side-effect branch immediately and check whether queue is anything other than none. first, last, and all can all retain stale intent, and all is processed with pop. Restore queue=none for control operations.
- Only a timeout is visible, so HA execution is uncertain: do not retry immediately. Verify the outcome with an action-specific read-only query, retain a sanitized correlation value, and follow the idempotency and manual recovery policy.
- Debug output or logs contain a real target or data: disable the full Debug output immediately and sanitize the sidebar, logs, exports, and issue reports. If credentials may have been exposed, follow the incident rotation procedure without reposting the value.
Pinned sources
- HA WebSocket 0.80.3 pinned commit 2cbbb69: used to verify
src/nodes/action,src/homeAssistant/Websocket.ts, the shared InputService, and persisted registration. - Official Action node documentation: user documentation for fields, inputs, outputs, and queues. If the rolling documentation differs, the pinned commit remains this chapter’s baseline.
- Official Home Assistant WebSocket API documentation: background on
call_serviceand the response protocol. - Official Home Assistant action/service development documentation: boundaries among targets, service data, and response data.
The only related download is 07-action.json. It is for offline review only: the Action node is disabled, and every environment-specific field uses a placeholder. This site provides no real action, entity, device, area, floor, label, or executable screenshot.
FAQ
Why does the UI say Action when the JSON type is not action?
api-call-service for compatibility with existing flows. The palette label and persisted registration can differ; do not edit the JSON type manually.Does Block Input Overrides=true prevent all dynamic data from affecting the node?
Can a target use entity, area, and label at the same time?
Is Queue all a reliable offline FIFO?
pop() after the connection becomes ready. It offers no exactly-once, deadline, or durability guarantee. Use queue=none for control Actions.Does every Action write its return value to msg.payload?
response?.response as the results source, which still requires explicit mapping through Output Properties. Allow for undefined when there is no response.