FluxBilling
Plugins

Building Flows

How to build a plugin flow on the visual canvas: wiring nodes and branches, the flow types and when the platform runs each one, execution timeout and retry behavior, and testing a flow with sample input before you ship it.

Updated · 2026-09-04

Flows are the visual workflows that power a plugin. Instead of writing code you drag nodes onto a canvas and wire them together — each node does one job (make an HTTP request, branch on a value, map a status, format a message), and the links between them define the order things run in. A plugin can hold many flows, one for each thing it needs to do: provisioning a service, suspending it, handling an inbound webhook, fetching live status, sending a notification, and so on.

This article covers the canvas, the flow types and when each one runs, the per-flow settings, the checks the builder makes before it lets you save, the timeout and retry behaviour applied to every run, and how to test a flow before you ship it. For the catalog of nodes see the Node Reference; for the {{ }} syntax see Variables & Expressions.

How to reach it

Open SettingsIntegrationsPlugins, open your plugin, and choose the Flows tab. Each flow is listed with its type and slug, a gear for its settings, and an option to open the builder. New Flow creates one.

Creating a flow

The create dialog asks for a Name, a Flow Type (see the table below) and a Slug. Once you pick a type, the dialog suggests the slugs the platform recognises for your plugin's type — choose one of those and the flow is wired to that platform operation automatically. A custom slug works too; the platform simply won't dispatch it on its own. Flows of type Custom Action also ask for the button details. See Capabilities & Flow Contracts for the full list of recognised names.

The canvas

The builder opens full screen. The header carries the flow name, zoom out and zoom in, and three buttons: Test, History and Save. The left rail is the node palette, grouped into Flow Control, Data and Utility; drag a node from it onto the canvas. A Quick Add Snippets bar on the canvas drops in ready-made mini-patterns in one click: HTTP Request, Success/Error Branch, Transform + Output, Loop Over Array, HTTP + Response Check and Full Action Pattern.

Anything that would block the save is listed live in a red banner pinned to the top of the canvas, so you can fix problems as you go rather than discovering them when you press Save.

Select a node to open its configuration panel on the right; every node has a Label and a Description at the top, then its own fields. Connect nodes by dragging from a node's output connector to the next node's input connector. A link means “when this node finishes, continue to that one.”

A new flow starts with a single Start node already on the canvas. Execution follows the links outward from Start until it reaches an End node.

Most nodes have one output and simply pass control on. Branching nodes have more than one output connector and pick exactly one at run time:

  • HTTP Request, XML Parse and Crypto have success and error outputs.
  • Condition has true and false.
  • Switch has one output per case you define, plus a default.
  • Loop has body (once per item) and complete (after the last item).

Execution continues down whatever you wired to the emitted output. If a named branch is left unwired, that path stops there — it never falls through to a different branch. An unwired error output is a special case: the flow stops and returns the failing node's own output, so the failure is still reported rather than silently swallowed. Wire the error output explicitly whenever you want to control what the caller sees.

Flow types and when they run

Flow types offered when you create a flow
Flow typeWhen the platform runs it
ProvisionWhen a new service using this plugin is set up for a customer.
SuspendWhen a service is suspended (for example on non-payment).
UnsuspendWhen a suspended service is reactivated.
TerminateWhen a service is cancelled or removed.
Custom ActionOn demand — from the action button you define on the flow, or when the platform requests that named operation.
Webhook HandlerWhen the external system posts to one of your plugin's webhook endpoints.
Data FetchWhen the panel needs live data from the provider (current status, usage, a list of options).
NotificationWhen a subscribed platform event fires. See Notification Plugins.
ScheduledOn the interval or schedule set in the flow's settings.

The four lifecycle types are the backbone of an infrastructure plugin — the platform calls them as a service moves through its life. Custom Action flows power the buttons staff and customers press. Data Fetch flows run whenever the panel needs fresh information.

Flow settings

The gear beside a flow on the Flows tab opens Flow Settings. The dialog header repeats the flow type and slug, and carries an Enabled checkbox — an unticked flow is skipped entirely.

Flow Settings fields
FieldWhat it does
Name / DescriptionHow the flow is labelled and what it does.
Timeout (ms)How long the whole run may take. Accepted range 1000–300000; the platform's own ceiling is five minutes and a flow that sets nothing runs with a 30-second budget.
Max RetriesTotal attempts when retry is on. Range 0–10; disabled until you tick the retry box.
Retry the whole flow on failure (exponential backoff)Turns retrying on.
OperationOptional. The platform operation this flow implements. When set, it is matched before the slug, which is the unambiguous way to bind a flow to an operation whose name differs from its slug.
Schedule Type (Scheduled flows)Every N minutes with an Interval (minutes), or Cron expression with a five-field Cron Expression at minute resolution.
Action Name, Button Label, Button Icon (Custom Action flows)The operation name the platform routes to this flow, and how its button is labelled and iconed.
Input Schema (JSON)Describes the flow's input. It also pre-fills the Test panel, so an example here saves retyping sample data.
Output Schema (JSON)Describes what the flow returns.

What the builder checks before saving

Pressing Save validates the canvas. Some problems block the save because the flow could not run:

  • no Start node, or more than one;
  • a link pointing at a node you deleted;
  • an HTTP Request node with no connection selected, or no path;
  • a Condition node with no conditions;
  • a Loop node with no source;
  • a Switch node with no field;
  • a Crypto node using an HMAC or AES operation with no key;
  • an End node whose status code isn't a real HTTP status between 100 and 599.

Other findings are warnings and still let you save: a node nothing links to, a Crypto node with no data expression, or a flow with more than 100 nodes.

Execution behaviour

Execution timeout

Every run is bounded — 30 seconds by default, with a hard ceiling of five minutes. If the flow is still running when the budget elapses it is stopped and recorded as a failure. The timeout covers the whole run, not any single node, so a flow that makes several slow external calls can hit it even when no individual node misbehaves.

Retry on failure

With retry enabled, the whole flow is re-run up to Max Retries attempts in total (three when left at the default), with a growing delay plus a little random jitter between attempts, capped at about 30 seconds. Each retry starts clean: variables set during the previous attempt are discarded and the flow begins again from its original input. The retry history is kept in the run's trace.

Retry suits operations that are safe to repeat. If repeating could cause a duplicate side effect — charging a card, creating a resource twice, sending a one-time code again — leave it off, or design the flow so a repeat is harmless.

Runaway protection

A run that executes more than 1000 nodes is stopped with a clear error. In practice that only happens when links form a cycle. Loop nodes have their own safety cap on how many items they process.

Testing a flow

You don't have to enable a plugin to see whether a flow works. Test opens a Test Flow dialog with a Test Input Data (JSON) box, pre-filled from the flow's input schema example or from the payload you last used. Load from previous execution pulls the input from the most recent run. The JSON is checked as you type and the run button stays disabled until it parses.

The result appears in a right-hand pane: the outcome (completed or failed), the error if there was one, an Execution Trace listing the nodes that ran with their durations, and the flow's Output. Re-run re-opens the input dialog.

Warning: a test uses your real plugin configuration and connections, so an HTTP Request node really calls your provider. Use sample values that are safe to send.

Execution History

Every run — a test, a lifecycle event, a webhook, a schedule — is recorded under History. The table shows when it started, what triggered it (Manual, Webhook, Scheduled, Event, API), its status (Running, Completed, Failed, Cancelled), how long it took, and the error message if any. Expanding a row shows the trigger reference, the input, the output and the step-by-step trace, which makes it the first place to look when something misbehaves.

Traces are trimmed for safety and size: values whose field name looks like a password, secret, token, key or auth are replaced with a redaction marker, long strings are truncated and long arrays are shortened. History is kept for a short rolling window and then pruned automatically, so the view stays focused on recent activity.

Worked example: a status-fetch flow

A small Data Fetch flow that asks a provider for a service's current state and maps the provider's wording onto a clean status:

Start → HTTP Request → Status Map → End

  1. Start — the entry point. It passes the incoming input (which identifies the service) straight through.
  2. HTTP Request — calls the provider's status endpoint through your connection with method GET. On success it emits success; otherwise error.
  3. Status Map — wired to success. It reads the provider's status field out of the response and maps each provider value onto your own (runningactive, stoppedsuspended), with a default of unknown.
  4. End — returns the mapped result.

Wire the HTTP Request's error output to a second End node that returns a clear failure, so the panel knows the fetch didn't succeed.

That's the whole pattern: a Start to receive input, working nodes in the middle, branches wired for both the happy path and the error path, and an End to return the result. Wire it, test it with sample input, confirm the run in History, and the flow is ready.


Related: Variables & Expressions · Node Reference · Capabilities & Flow Contracts · Connections & Authentication · Configuration Settings