Portal Community
Ephemeral vs DM: An ephemeral message appears in a channel but is only visible to one user — other channel members never see it. This is distinct from a DM, which creates a separate conversation. Use ephemeral messages for in-context feedback that does not need to be permanent (validation errors, help hints, moderation notices). Use DMs when the message needs to survive across sessions or be replied to.

When to Use

Configuration

Connection

FieldRequiredDescription
botTokenRequiredBot Token in xoxb-... format. Must have chat:write scope. Store in BizFirst Credentials Manager.

Operation

FieldRequiredDescription
channelRequiredThe channel where the ephemeral message will appear. The target user must be a member of this channel. Cannot be a DM channel ID — use message/send with a user ID for DMs.
targetUserIdRequiredSlack user ID (U...) of the user who will see the message. Only this user will see it.
textRequiredMessage text. Supports mrkdwn formatting. Keep the message clear and actionable since the user cannot reply to an ephemeral message to start a thread.
threadTsOptionalShow the ephemeral message in the context of a specific thread. Useful for providing in-thread guidance to a participant.
blocksJsonOptionalBlock Kit JSON for rich layout. Note that interactive components (buttons, select menus) within ephemeral messages have limited support and cannot initiate modal flows reliably.

Sample Configuration

{
  "resource": "message",
  "operation": "sendEphemeral",
  "botToken": "{{ $credentials.slackBotToken }}",
  "channel": "C04GENERALCH",
  "targetUserId": "{{ $input.userId }}",
  "text": ":warning: Your expense report submission was incomplete. Missing fields: *{{ $input.missingFields }}*.\nPlease resubmit at <https://expenses.internal/submit|expenses.internal>."
}

Validation Errors

Error CodeCause
channel_not_foundThe specified channel does not exist or is not accessible to the bot.
user_not_in_channelThe target user is not a member of the specified channel. Ephemeral messages can only be sent to channel members.
not_in_channelThe bot itself is not a member of the specified channel.
invalid_blocksThe blocksJson string is malformed.
VAL_MISSING_CHANNELThe channel field is empty or not provided.
VAL_MISSING_TARGET_USERThe targetUserId field is empty or not provided.
VAL_MISSING_TEXTThe text field is empty or not provided.

Output

Success Port

Fires when Slack confirms the ephemeral message was delivered. Note that ephemeral messages do not have a persistent messageTs — they cannot be updated, deleted, or replied to.

FieldTypeDescription
statusstring"ok" on success.
errorCodestringEmpty on success.
payloadobjectFull raw Slack API response. The Slack API returns {"ok": true, "message_type": "ephemeral"} without a message timestamp.

Error Port

Fires when the channel or user cannot be found, the bot lacks channel membership, or the API call fails.

FieldTypeDescription
statusstring"error"
errorCodestringSlack error code, e.g. user_not_in_channel, channel_not_found.
payloadobjectFull raw Slack error response.

Sample Output

{
  "status": "ok",
  "errorCode": "",
  "payload": {
    "ok": true,
    "message_type": "ephemeral"
  }
}

Expression Reference

FieldExpressionNotes
Operation status{{ $output.notifyUser.status }}"ok" on success. Use in IfCondition to confirm delivery before continuing.
Error code{{ $output.notifyUser.errorCode }}Non-empty if delivery failed — log this for user experience monitoring.
Raw response{{ $output.notifyUser.payload.ok }}Boolean true on success. The ephemeral endpoint does not return a message timestamp.
Message type{{ $output.notifyUser.payload.message_type }}Always "ephemeral" on success — useful for conditional logic that handles both regular and ephemeral send nodes.

Node Policies & GuardRails

Policy AreaRecommendation
No history retentionEphemeral messages do not persist. Do not use them for compliance-required notifications that must appear in audit logs. Use message/send to a private DM for persistent records.
Channel membership checkBoth the bot and the target user must be in the channel. If either is not a member, the send will fail. Pre-validate membership with channel/getMembers in user-variable workflows.
No reply capabilityRecipients cannot reply to ephemeral messages — they disappear on reload. If a user response is needed, follow up with a message/sendAndWait DM.
Rate limitschat.postEphemeral is Tier 3 (50+ req/min). In loops processing many users, add a short delay to avoid burst throttling.
Sensitive informationWhile ephemeral messages are invisible to others in the channel, they are not end-to-end encrypted. Do not send passwords, API keys, or highly sensitive PII even in ephemeral messages.
Credential storageAlways reference the bot token via {{ $credentials.slackBotToken }}. Never hard-code xoxb- tokens in node configuration.

Examples

Form Validation Error Feedback

{
  "resource": "message",
  "operation": "sendEphemeral",
  "botToken": "{{ $credentials.slackBotToken }}",
  "channel": "C04HRFORMSVC",
  "targetUserId": "{{ $input.submitterUserId }}",
  "text": ":x: Your time-off request could not be processed.\n\n*Validation errors:*\n• Start date must be a future date\n• Reason field is required\n\nPlease <https://forms.internal/time-off|resubmit the form> with the corrections."
}

After a form validation node detects errors in a time-off request, this ephemeral message is shown only to the submitter in the HR forms channel. No other HR team members see the error, preserving the submitter's privacy.

Admin Diagnostics in Shared Channel

{
  "resource": "message",
  "operation": "sendEphemeral",
  "botToken": "{{ $credentials.slackBotToken }}",
  "channel": "C04DEPLOYCHAN",
  "targetUserId": "{{ $input.triggerUserId }}",
  "text": ":mag: *Deploy Diagnostics (visible to you only)*\nBuild ID: `{{ $input.buildId }}`\nArtifact hash: `{{ $input.artifactHash }}`\nDeploy target: `{{ $input.targetEnv }}`\nLogs: <{{ $input.logUrl }}|View full logs>"
}

A deployment workflow posts verbose diagnostic details (build IDs, artifact hashes, log URLs) only to the engineer who triggered the deploy, in the shared #deploys channel. Other channel members see only the standard deploy notification posted via message/send.

Onboarding Welcome Tip

{
  "resource": "message",
  "operation": "sendEphemeral",
  "botToken": "{{ $credentials.slackBotToken }}",
  "channel": "C04GENERAL01",
  "targetUserId": "{{ $input.newMemberUserId }}",
  "text": ":wave: Welcome to *#general*, {{ $input.displayName }}!\n\n*Quick tips:*\n• Keep posts relevant to company-wide announcements\n• Use <#C04WATERCOOL|#water-cooler> for casual chat\n• Reach the admin team at <@U04ADMINTEAM>\n\nThis message is only visible to you."
}

An onboarding workflow triggers when a new member joins #general and shows them a contextual welcome tip. Because it is ephemeral, the channel is not cluttered with a welcome for each new member, and other members are not interrupted.