ToDiscord@1
Node ToDiscord@1 posts a message to a Discord channel via the Bot API (POST /channels/{id}/messages). It supports plain content, a single embed, and one file attachment sourced from a System.Reporting/FileSystemItem entity. To post into a thread, pass the thread's snowflake as channelId — threads are channels in Discord's data model. Credentials come from a centrally-managed DiscordConfiguration entity; the node looks it up by name via pipeline-scoped global configuration.
Adapter Prerequisites
- General availability: Mesh adapters.
- A
DiscordConfigurationentity must exist and be associated to the pipeline (via the standardUsesassociation). - To send attachments, the tenant must have the
System.ReportingCK package loaded (the owner ofFileSystemItem). Same constraint asCreateFileSystemUpdate@1andGenerateAndStoreReport@1.
Node Configuration
For fields targetPath, targetValueWriteMode, and targetValueKind, see Overview. Field path is not used in this node.
Configuration Options
Most user-facing fields accept either a literal value or a JSONPath ({Field} or {Field}Path). When both are set the path wins; when the path resolves to empty the literal is used.
-
serverConfiguration (required): name of the global configuration entry holding the
DiscordConfiguration(bot token + optional guild id). -
channelId / channelIdPath (one required): Discord channel snowflake ID. To target a thread, pass the thread's snowflake here — Discord treats threads as channels.
-
content / contentPath (optional): message content.
-
embedTitle / embedTitlePath, embedDescription / embedDescriptionPath, embedColor / embedColorPath (optional): a single embed.
embedColorliteral is an integer (0xRRGGBB); the path form also accepts#RRGGBBand decimal-string. -
attachmentFileSystemItemRtId / attachmentFileSystemItemRtIdPath (optional): RtId of a
System.Reporting/FileSystemItemwhose bound binary is attached to the message. The node resolves the payload via the entity'sContent.BinaryIdand picks the filename sent to Discord by the precedence below. -
attachmentFilename / attachmentFilenamePath (optional): explicit filename override. When set, trumps the FileSystemItem's own fields. Useful when the caller has a better name from domain metadata (e.g. an invoice number) that isn't reflected on the FileSystemItem itself.
Filename precedence (highest → lowest):
attachmentFilename→FileSystemItem.Name→FileSystemItem.Content.Filename. The first two capture user intent (the entry-in-a-folder label);Content.Filenameis blob metadata captured at ingest and drifts as an implementation detail if the entity is later renamed, so it's a last-resort fallback. -
mentionPolicy (optional, default
None): controls which mention syntax in the message content actually fires notifications. Discord mention syntax:<@USER_SNOWFLAKE>for a user,<@&ROLE_SNOWFLAKE>for a role, and the literal strings@everyone/@herefor the broad pings. The policy is a type whitelist over whatever syntax is already in the content — it does not look up anyone by name. Values:None— nothing fires a notification. Mentions in content still render as "@username" but no recipient is pinged. Safe default for pipelines echoing upstream data where@everyoneor stray<@id>may appear accidentally or via injection.Users— only<@id>syntax in content fires;<@&id>and@everyone/@hererender but don't ping.Roles— only<@&id>syntax fires.UsersAndRoles— user and role mentions fire;@everyone/@hereare silenced.All— everything mentioned fires; matches Discord's default whenallowed_mentionsis omitted.Custom— use allowedMentionsPath to supply a raw Discordallowed_mentionsobject. Needed when you want to ping only specific user/role snowflakes (e.g.{"parse":[],"users":["111"]}) rather than every mention of that type in content.
-
allowedMentionsPath (optional): JSONPath resolving to a raw Discord
allowed_mentionsobject. Consulted only whenmentionPolicyisCustom. The node fails fast if the path is unset or resolves to null. See Discord's Allowed Mentions reference for the full object shape. -
timeoutSeconds (optional, default
30): HTTP request timeout. -
targetPath (optional, default empty): when set, the Discord API response JSON is written to this path. Useful for capturing the message
idfor later edits; the response also carrieschannel_id,timestamp, and the full message object.
At least one of content, embed*, or attachment* must resolve to a value — Discord rejects empty messages.
Usage Examples
Post a plain message
transformations:
- type: ToDiscord@1
description: Notify deploy channel
serverConfiguration: discord-main
channelId: '123456789012345678'
content: 'Deployment finished.'
Post an embed and capture the message id
transformations:
- type: ToDiscord@1
description: Post status + capture id for later update
serverConfiguration: discord-main
channelId: '123456789012345678'
embedTitle: 'Run started'
embedDescriptionPath: '$.status.description'
embedColor: 0x64CEB9
targetPath: '$.discordMsg'
Ping the on-call user from upstream data
The pipeline has resolved an on-call user's snowflake and interpolates it into the content using Discord's <@id> syntax. Users policy lets the <@id> fire a notification while still silencing any accidental @everyone.
transformations:
- type: ToDiscord@1
description: Page the on-call
serverConfiguration: discord-main
channelId: '123456789012345678'
contentPath: '$.alert.message' # e.g. "Pager: <@111222333444555666> DB saturated"
mentionPolicy: Users
Critical alert that pings @everyone
Override the safe default to notify the whole channel. @everyone is a literal string in Discord (no angle brackets, no snowflake).
transformations:
- type: ToDiscord@1
description: Wake everyone up
serverConfiguration: discord-main
channelId: '123456789012345678'
content: '@everyone production is down'
mentionPolicy: All
Post into a thread with a file attachment
Pass the thread's snowflake as channelId — Discord treats threads as channels. GenerateAndStoreReport@1 writes a FileSystemItem RtId to the data context, which is exactly what attachmentFileSystemItemRtIdPath expects.
transformations:
- type: GenerateAndStoreReport@1
# ... produces $.reportRef.fileSystemRtId
- type: ToDiscord@1
description: Attach generated report to a thread
serverConfiguration: discord-main
channelId: '987654321098765432' # thread snowflake
content: 'Report ready.'
attachmentFileSystemItemRtIdPath: '$.reportRef.fileSystemRtId'
Attach a file with a human-readable filename override
When the FileSystemItem was stored with a GUID-style name but the pipeline knows a better one from upstream metadata, override at send time.
transformations:
- type: ToDiscord@1
description: Send invoice PDF with its issuer/invoice-number as the filename
serverConfiguration: discord-main
channelId: '123456789012345678'
content: 'New invoice flagged for review.'
attachmentFileSystemItemRtIdPath: '$.invoice.fileSystemItemRtId'
attachmentFilenamePath: '$.invoice.readableName' # e.g. "DemoEnergie-inv-20250930-abc.pdf"
Notes
- Rate limits (HTTP 429) are treated as errors; the exception includes the Discord-provided
Retry-Afterseconds. The pipeline orchestrator is responsible for retry/backoff. - The bot token never appears in log output or exception messages — only in the outbound
Authorization: Bot {token}header. - The node uses the named HttpClient
"Discord", bare (no Polly policies in v1).