Skip to main content

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 DiscordConfiguration entity must exist and be associated to the pipeline (via the standard Uses association).
  • To send attachments, the tenant must have the System.Reporting CK package loaded (the owner of FileSystemItem). Same constraint as CreateFileSystemUpdate@1 and GenerateAndStoreReport@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. embedColor literal is an integer (0xRRGGBB); the path form also accepts #RRGGBB and decimal-string.

  • attachmentFileSystemItemRtId / attachmentFileSystemItemRtIdPath (optional): RtId of a System.Reporting/FileSystemItem whose bound binary is attached to the message. The node resolves the payload via the entity's Content.BinaryId and 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): attachmentFilenameFileSystemItem.NameFileSystemItem.Content.Filename. The first two capture user intent (the entry-in-a-folder label); Content.Filename is 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 / @here for 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 @everyone or stray <@id> may appear accidentally or via injection.
    • Users — only <@id> syntax in content fires; <@&id> and @everyone/@here render but don't ping.
    • Roles — only <@&id> syntax fires.
    • UsersAndRoles — user and role mentions fire; @everyone/@here are silenced.
    • All — everything mentioned fires; matches Discord's default when allowed_mentions is omitted.
    • Custom — use allowedMentionsPath to supply a raw Discord allowed_mentions object. 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_mentions object. Consulted only when mentionPolicy is Custom. 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 id for later edits; the response also carries channel_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-After seconds. 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).