Notification Plugins
Build a notification plugin that subscribes to platform events — new orders, paid invoices, fresh tickets — and posts to Telegram, Discord, or Slack. Covers subscribable events, the Format Message and HTTP Request flow, the built-in channel scaffolding, and per-event message templates.
A notification plugin listens for things that happen in FluxBilling — a new order, a paid invoice, a fresh support ticket — and sends a message to an outside channel. You build it like any other plugin, with a connection, a configuration form and a flow. What differs is the trigger: instead of being called for a service or payment operation, a notification plugin reacts to platform events. This article covers the two places events are wired up, the events available in each, how a notification flow is shaped, the ready-made channel scaffolding, and how to write per-event message templates.
New to flows? Read Building Flows and the Node Reference first — this article builds on the Transform, Format Message and HTTP Request nodes.
How to reach it
Open Settings → Integrations → Plugins and open a Notification plugin. Its editor shows two tabs the other plugin types don't have:
- Notifications — the channel credentials, a switch and a message template for each event, a Send Test Notification button, and the delivery log.
- Subscriptions — explicit event-to-flow bindings with filters and rate limits, for cases the per-event switches don't cover.
The Notifications tab
This is the everyday screen. Fields are grouped into Connection Settings followed by Orders, Tickets, Payments, Invoices, Users and Services. Each event has a toggle and, once it is on, a Message Template box underneath. Save stays disabled until you change something.
| Group | Events |
|---|---|
| Orders | New Order, Order Paid, Order Cancelled |
| Tickets | New Ticket, Ticket Reply, Ticket Closed |
| Payments | Payment Completed, Payment Failed, Payment Refunded |
| Invoices | Invoice Created, Invoice Paid, Invoice Overdue |
| Users | New User, User Verified |
| Services | Service Provisioning, Service Activated, Deployment Failed, Service Suspended, Service Unsuspended, Service Terminated, Service Renewed |
Turning an event on is all it takes: when that event fires, the platform runs the plugin's notification flow with the event's data and the template you wrote for it. Monitoring and uptime alerts are delivered through the platform's own alerting and are not part of this list.
Rate limiting and delivery
Events routed this way are rate-limited per plugin and per event, so a burst can't flood a channel. Every attempt is written to the Delivery Log at the bottom of the tab, with columns for Event, Flow, Status, Attempt, Last Attempt, Next Retry and Error, and a filter across All, Pending, Sent, Failed and Retrying. A failed delivery is retried on a widening schedule — roughly one minute, then five, then fifteen — until it succeeds or runs out of attempts.
Send Test Notification
The Send Test Notification button asks for an Event, a Flow and a Sample Payload (JSON), then runs the flow for real against your connection. Use it to see exactly which fields arrive and to confirm the message lands where you expect.
The Subscriptions tab
A subscription is an explicit binding of one event to one flow, with two things the per-event switches don't offer: filters and per-subscription rate limits.
| Field | What it does |
|---|---|
| Event Name | The event to listen for. The dropdown shows each event with a description, and once you choose one it lists the payload fields that event carries. Cannot be changed after creation. |
| Flow | Which flow to run. Notification flows are listed first. Cannot be changed after creation. |
| Filter Conditions | Optional pairs of a payload path and an expected value. The flow fires only when every pair matches — for example status equal to paid. With no filters it fires on every occurrence. |
| Rate Limit (per minute) | How many times a minute this subscription may fire. Default 60. |
| Burst | The allowance for a short spike. Default 10. |
| Enable this subscription | Shown when editing. Turns the subscription on or off without deleting it. |
The events available here are: order.created, order.paid, order.cancelled, service.provisioning, service.activated, service.suspend, service.unsuspend, service.terminate, service.renewed, payment.processing, payment.completed, payment.failed, payment.refunded, invoice.created, invoice.paid, invoice.overdue, user.registered, user.verified, ticket.created, ticket.replied and ticket.closed.
Note: the two lists overlap but are not identical. Deployment Failed has a switch and template on the Notifications tab;
payment.processingis only available as a subscription.
How a notification flow is shaped
The seeded flow has five steps:
Start → Get Message Template (Transform) → Format Message → HTTP Request → End
- Start receives the event.
- Get Message Template is a Transform node that picks the right template for this event out of configuration, falling back to a plain line naming the event.
- Format Message turns that template into a payload shaped for your channel.
- HTTP Request posts the payload through your connection.
- End finishes the flow.
What the flow receives
| Reference | What it is |
|---|---|
input.event | The event name, such as order.created. |
input.eventKey | The same name with underscores, such as order_created — handy for looking a configuration key up. |
input.messageTemplate | The template already resolved for this event. |
input.data | The event's own fields, referenced in templates as {{data.…}}. |
input.helpers | Formatting helpers plus helpers.adminUrl and helpers.clientUrl. |
The helpers you can call from a template are formatCurrency, formatDate, truncate, capitalize, uppercase, lowercase, escapeMarkdown and nl2br. For example {{ helpers.formatCurrency(data.total, data.currency) }}, or a link built as {{ '[Invoice](' + helpers.adminUrl + '/invoices/' + data.invoiceId + ')' }}.
Message formats
| Format | Produces | Use for |
|---|---|---|
| Plain Text | The message unchanged | Simple, unstyled channels |
| Markdown | The message, labelled as Markdown | Channels that render Markdown |
| HTML | The message with special characters escaped | Channels that accept HTML |
| Slack Blocks | A block payload: header, section, divider and a timestamp context block | Slack |
| Discord Embed | An embed with description, colour, timestamp, optional title and a footer | Discord |
| Telegram | A message with an optional bold title, marked as Markdown | Telegram |
You can also pass a Title and a Color; the block and embed formats use them for the header and the accent colour.
Ready-made channel scaffolding
You don't have to build the connection and flow from nothing. The platform ships scaffolding for Telegram, Discord and Slack, and it is applied automatically based on the plugin's name. Create a Notification plugin whose name or slug contains telegram, discord or slack, and it is seeded with the matching connection already pointed at the right API, the configuration fields that channel needs, a send flow wired end to end, and a full set of per-event message templates written in that channel's markup. A plugin whose name matches none of them still gets a generic single-send flow you point at any provider.
Telegram
| Field | Type | Notes |
|---|---|---|
| Bot Token | Secret | Required. Your bot token. |
| Chat ID | Text | Required. The user, group or channel the bot posts to. |
| Parse Mode | Select | Markdown (default), Markdown V2 or HTML. |
The connection carries the bot token in its base URL and the send flow uses the Telegram format.
Discord
| Field | Type | Notes |
|---|---|---|
| Webhook URL | Secret | Required. The channel's webhook URL. |
| Bot Username | Text | Display name for the messages. Defaults to FluxBilling. |
| Avatar URL | URL | Optional avatar image. |
| Embed Color | Text | Accent colour for the embed, as a decimal integer. |
The connection's base URL is the webhook itself and the send flow uses the Discord Embed format.
Slack
| Field | Type | Notes |
|---|---|---|
| Webhook URL | Secret | Required. The incoming-webhook URL. |
| Channel Override | Text | Optional. Post somewhere other than the webhook's default channel. |
| Bot Username | Text | Display name for the messages. Defaults to FluxBilling. |
| Icon Emoji | Text | Emoji used as the avatar. Defaults to :bell:. |
The connection's base URL is the webhook itself and the send flow uses the Slack Blocks format.
For all three, the credential lives in configuration and is referenced from the connection with {{config.…}} — see Configuration Settings and Connections & Authentication.
Per-event message templates
Each event has its own template, so an order message can read differently from a ticket one. Templates are ordinary text with {{data.…}} placeholders. For example:
New order #{{data.orderNumber}} from {{data.customerName}}
Total: {{data.total}} {{data.currency}}
New ticket: "{{data.subject}}"
From: {{data.customerName}} ({{data.email}})
Priority: {{data.priority}}
Which fields exist depends on the event — an order event carries order details, a ticket event carries ticket details, a payment event carries amounts and the document it belongs to. The Subscriptions tab lists an event's payload fields when you select it, and Send Test Notification shows you exactly what arrives.
Templates are rendered by the same expression evaluator as the rest of a flow, so ternaries, + concatenation and || fallbacks all work — see Variables & Expressions. The seeded templates already cover every event with sensible wording and working links back into the panel; edit them to match your tone.
Worked example: post new orders to Slack
- Create the plugin. In Settings → Integrations → Plugins, create a new Notification plugin whose name includes Slack — for example Slack Notifications. Because the name matches a known channel, the connection, configuration fields, send flow and default templates are seeded for you.
- Add your webhook. On the Notifications tab, paste your incoming-webhook URL into Webhook URL under Connection Settings. Optionally set a channel override and username. Save.
- Turn the event on. Under Orders, switch on New Order. Its Message Template box appears with a default you can edit, for example:
:tada: New order *#{{data.orderNumber}}* from {{data.customerName}} — {{data.total}} {{data.currency}} - Check the flow. On the Flows tab, open the send flow and confirm the Format Message node's Format is Slack Blocks.
- Test it. Use Send Test Notification, pick the order-created event and the send flow, and confirm the message lands in your channel.
- Enable the plugin. Move it out of Draft with Enable on its card. From now on, every new order posts to Slack.
To announce paid invoices too, switch on Invoice Paid and give it its own template — the same send flow serves every event.
Tips
- Keep credentials in configuration, never hard-coded in a flow — reference them with
{{config.…}}. - Match the format to the channel: Telegram for Telegram, Discord Embed for Discord, Slack Blocks for Slack, and Plain Text or Markdown for a generic webhook.
- One plugin serves many events — switch on as many as you like and tailor each template.
- Use a subscription when you need to fire only on some occurrences of an event, or to hold a chatty event to a lower rate.
- Watch the Delivery Log after enabling. A run of Failed rows with the same error usually points at the credential rather than the template.
Related: Building Flows · Node Reference · Variables & Expressions · Capabilities & Flow Contracts · Connections & Authentication · Configuration Settings · Packaging, Importing & Updating
