Capabilities & Flow Contracts
Declare capability flags and name your plugin flows the way FluxBilling expects so the platform wires provisioning, payments, authentication, and AI operations automatically. The authoritative slug and flow-type list for every plugin type.
This article is the contract between your plugin and the platform. You never tell the platform “call this flow when a service is provisioned.” Instead you do two things: you declare capabilities that advertise what your plugin can do, and you give each flow a type and a name the platform recognises. At run time, when the platform needs to provision a service, take a payment or sign a user in, it looks through your plugin's flows for the expected name and runs the first match. Get the names right and the plugin works; this article lists the exact names for every plugin type.
If you haven't built a flow yet, start with Building Flows and Creating a Plugin. This article assumes you know what a flow, a flow type and a slug are.
How a flow is matched
Three things identify a flow, and they are tried in this order:
- Operation — the optional field in Flow Settings. When it matches, nothing else is considered. This is the unambiguous way to bind a flow to a platform operation, and it is worth setting whenever your flow's slug doesn't already spell the operation exactly.
- Slug — the short lowercase hyphenated name you gave the flow, such as
create-paymentorget-user-profile. The create-flow dialog suggests the recognised slugs for your plugin's type. - Name — last resort: a flow whose name contains the operation word. This is why a flow called “Restart Server” still answers a restart request.
The four service-lifecycle operations are the exception: they are matched by flow type alone, so a plugin has one Provision flow, one Suspend flow, and so on.
A useful consequence: for several plugin types a capability is inferred from whether the matching flow exists. Add a refund-payment flow to a payment gateway and refunds light up; you don't have to flip a separate switch as well.
Tip: a flow whose Enabled box is unticked is invisible to this matching, which is a clean way to take one operation out of service without deleting it.
Declaring capabilities
Capabilities live on the plugin's Overview, in the capabilities editor. Infrastructure Provider and Payment Gateway plugins get a checklist of named flags plus a few numeric settings and structured sub-editors; the other types edit their capabilities as a small block of JSON. The platform reads these to decide which buttons and options to show, so set them honestly.
Infrastructure Provider
Infrastructure Provider plugins provision and manage customer services on an external control panel.
Capability flags
| Flag | Advertises that your plugin can… |
|---|---|
| Provision | Create a new service |
| Suspend | Suspend an active service |
| Unsuspend | Reactivate a suspended service |
| Terminate | Permanently remove a service |
| Reboot | Restart a running service |
| Start | Power a stopped service on |
| Stop | Power a running service off |
| Console | Open a remote console or terminal |
| Stats | Return usage statistics |
| Status | Report the current power state |
| Reinstall | Reinstall the operating system or image |
| Backup | Take a backup |
| Restore | Restore from a backup |
| Snapshot | Take a snapshot |
| Resize | Change the resource plan or specs |
Two structured sub-editors sit alongside the checklist: Stats Display, which controls how each usage figure is presented (as usage or as an allocation), and Expected Options, which declares the product options the plugin expects to be configured against it.
Lifecycle flows (matched by flow type)
| Operation | Flow type | Slug | What the flow receives |
|---|---|---|---|
| Provision a service | Provision | provision | hostname, plan, location, os, password, specs, user, product (including the product's plugin settings), orderData and the chosen product options as options |
| Suspend a service | Suspend | suspend | serviceId, reason and the service's stored data |
| Unsuspend a service | Unsuspend | unsuspend | serviceId and the service's stored data |
| Terminate a service | Terminate | terminate | serviceId, deleteData and the service's stored data |
What a provision flow should return
On success the platform activates the service and stores what the End node returns. Three fields are read by name:
serverId— the provider's own identifier for the new service. Every later action depends on it, so always return it.serverIp— the address recorded on the service and shown to the customer.credentials— an object of login details. If you omit it, the password the platform generated for the order is stored instead.
Anything else you return under providerData is kept with the service and is available to later flows. If the flow fails, the service stays pending so the operation can be retried, and the error is recorded against it.
Note: provision flows for the same plugin are run one at a time. Many panels assign a shared resource such as the next free address at create time, and serialising the calls keeps concurrent orders from colliding.
Service actions (Custom Action flows)
| Operation | Flow type | Slug | Notes |
|---|---|---|---|
| Start | Custom Action | start | |
| Stop | Custom Action | stop | |
| Restart / reboot | Custom Action | restart | The create-flow dialog also suggests reboot. Either set the flow's Operation to restart or include the word restart in its name, so the platform's restart control routes to it. |
| Reinstall | Custom Action | reinstall | Receives the chosen template as params.osTemplate and params.templateId |
| Resize / change plan | Custom Action | resize | Receives the new specs |
| Console access | Custom Action or Data Fetch | console | Return the console URL or connection details |
| Reset password | Custom Action | password-reset | Receives the requested password in params |
| Create snapshot | Custom Action | snapshot-create | snapshots-create and create-snapshot also match |
| Restore snapshot | Custom Action | snapshot-restore | Receives the snapshot id. snapshots-restore and restore-snapshot also match |
| Delete snapshot | Custom Action | snapshot-delete | Receives the snapshot id. snapshots-delete and delete-snapshot also match |
Every action flow receives serviceId, the service's stored data, and a params object holding whatever the caller supplied. Keep slugs lowercase and hyphenate compound names.
Tip: the backup controls on a service are served by the same snapshot flows — a plugin that ships
snapshot-list,snapshot-create,snapshot-restoreandsnapshot-deletegets the backup buttons for free, with no separate backup flows to write.
Lookups (Data Fetch flows)
| Operation | Flow type | Slug | Notes |
|---|---|---|---|
| Get status | Data Fetch | get-status | The platform finds this flow by its name containing the word “status”, so call it something like Get Status. It reads a status (or powerStatus) value from your output; anything else you return is passed along. |
| Get stats | Data Fetch | stats | Matched on the word stats, so get-stats with the name Get Stats works too. When there is no stats flow the status flow is used instead, since some providers report usage on the same endpoint. |
| List OS templates | Data Fetch | os-templates | Return the installable images for the reinstall picker under templates or images. os-images and reinstall-os also match. |
| List snapshots | Data Fetch | snapshot-list | Return them under snapshots. snapshots-list and list-snapshots also match. |
When a flow for an operation is absent, the platform simply reports that the operation isn't supported. Add only the flows your provider's API can really perform, and keep the capability checklist consistent with them.
Worked example: a restart action
- Tick Reboot (and Start / Stop as appropriate) in the capabilities checklist.
- Create a Custom Action flow named Restart Server with the slug
restart, and set its Button Label and Button Icon in Flow Settings. - Wire it: Start → HTTP Request (call the provider's restart endpoint, using the service identifier from
{{ input.serviceData.serverId }}) → Condition (check the response) → End, with the request's error output wired to a second End that returns a clear failure.
The platform now shows a restart control on services backed by your plugin and runs this flow when it is pressed.
Payment Gateway
Capability flags, limits and identity
| Flag | Meaning |
|---|---|
| Refunds | Full refunds are available |
| Partial Refunds | Refunds for part of a payment |
| Recurring | The gateway can charge on a recurring schedule |
| Saved Methods | Customers can store a payment method for later charges |
| Multi-currency | More than one currency is accepted |
| Manual Capture | Authorise now, capture later |
| Webhook Required | The gateway confirms payments by posting back |
| Manual Settlement | Settlement happens out of band and a person confirms it |
Three numbers sit beside the flags: Minimum Amount, Maximum Amount and Settlement Window (hours), which is how long a payment may sit pending before it is treated as stale rather than still settling.
A Gateway Identity sub-editor sets how the gateway appears at checkout — its id, icon, a type of card, wallet, bank or crypto, and a priority that orders it in the payment list. Further sub-editors cover token lifecycle events, gateway-managed subscription events, and the phrases used to classify a declined charge into buckets such as system, terminal, expired card, authentication required, insufficient funds and hard decline.
Several flags are inferred from your flows. A refund-payment flow means refunds (full and partial) are supported; a charge-saved-method flow means stored methods can actually be charged off-session; a handle-webhook flow means webhooks are required. Setting the flags too is harmless, but adding the flow is what enables the behaviour.
Flows the platform calls
| Operation | Slug(s) — first match wins | Notes |
|---|---|---|
| Create a payment | create-checkout-session, create-payment, payment | Required. Receives the amount, currency, description, return and cancel URLs, the webhook URL, the invoice or proforma reference, the customer, the brand name, a savePaymentMethod flag and any metadata. Return a redirect URL for hosted checkout, or the data the platform needs to finish the charge. |
| Capture an authorised payment | capture-payment | For authorise-then-capture gateways. Omit it if you charge immediately. |
| Refund a payment | refund-payment | Receives the transaction, an amount for a partial refund, and a reason. |
| Get payment status | get-payment-status | Look up the current state of a transaction. |
| Poll payment status | poll-payment-status | Used when the platform re-checks a pending payment rather than waiting for the webhook. get-payment-status and verify-payment are accepted as fallbacks. |
| Start saving a payment method | setup-save-method, create-billing-agreement, setup-payment-method | Begins the save-card or mandate setup. |
| Finish saving a payment method | complete-save-method, execute-billing-agreement, confirm-payment-method | Completes the setup started above. |
| Charge a saved method | charge-saved-method, charge-billing-agreement, reference-transaction | Charges a stored method off-session. |
| Remove a saved method | remove-saved-method, cancel-billing-agreement, delete-payment-method | Optional. Without it, removal succeeds locally. |
| Cancel a subscription | cancel-subscription, cancel-billing-agreement | For gateways that manage the recurring schedule themselves. |
| Handle a webhook | handle-webhook | Flow type Webhook Handler. Return the event type, the transaction reference and the resulting status. |
| Test the connection | test-connection | Optional. Used by the gateway's readiness check and its Test button. |
A gateway that only does one-off hosted checkout needs just a payment-creation flow and, usually, a handle-webhook flow.
Receiving and verifying a webhook
Verifying an inbound webhook is a supported, first-class part of a gateway plugin, and it is configured rather than coded. On the plugin's Webhooks tab, add an endpoint:
| Field | What it does |
|---|---|
| Name | A label for the endpoint. |
| Slug | The last part of the endpoint's address. The dialog shows the full URL prefix beside the box — that is what you paste into the provider's dashboard. |
| HTTP Method | POST, GET, PUT, PATCH or DELETE. |
| Verification Type | How the delivery is authenticated (see below). |
| Execute Flow | Which of your Webhook Handler flows to run. Only flows of that type are listed. |
| Enable this webhook endpoint | Turns the endpoint on. A disabled endpoint refuses deliveries rather than accepting them unverified. |
Verification types:
- None — no verification. Not recommended.
- HMAC-SHA256 / HMAC-SHA1 — a shared secret, the header carrying the signature, and an optional signature prefix such as
sha256=. A Regenerate button mints a fresh random secret for you. - HMAC Body Field — for providers that put the signature inside the JSON body: you name the field holding it, the secret, the algorithm, the body encoding, and any fields excluded from the signed payload.
- HMAC Header (raw body) — a header signature computed over the exact bytes received.
- Timestamped HMAC v1 — the widely used
t=<timestamp>,v1=<signature>scheme, with a replay window. You name the configuration field holding the signing secret, the signature header, and the four punctuation and key settings that describe the header's shape (pair separator, signed-payload join, timestamp key and signature key). Tolerance (seconds) sets how old a signature may be, defaulting to 300. - Bearer Token — an expected token in the Authorization header.
- Query Token — an expected token in a named query parameter.
- IP Whitelist — one address or CIDR range per line.
Verification runs before your flow does. A delivery that fails it is rejected and recorded as a failed delivery, so an admin sees “deliveries failing” rather than silence. A verified delivery reaches your flow as input.webhook, carrying body, headers, rawBody and method. Your End node should return the normalised eventType, transactionId and status.
Worked example: a minimal redirect gateway
- Create a connection to your processor's API (see Connections & Authentication).
- Create a Custom Action flow with the slug
create-payment: Start → HTTP Request (create a checkout session) → Transform (pull out the redirect URL and the transaction id) → End. The platform sends the customer to that URL. - Create a Webhook Handler flow with the slug
handle-webhook: Start → Switch (branch on the event type) → End per branch, each returning the normalised event type, transaction reference and status. - On the Webhooks tab, add an endpoint pointing at that flow and set its verification type and secret; paste the URL the dialog shows into the provider's dashboard.
- Optionally add
refund-paymentto enable refunds, andget-payment-statusso pending payments can be re-checked.
Authentication
| Operation | Slug(s) | Notes |
|---|---|---|
| Build the sign-in URL | get-auth-url, authorize, auth-url | Receives state, redirectUri and scopes; returns the provider's authorization URL. |
| Exchange the code for a token | exchange-token, token-exchange, get-token | Receives code, redirectUri and state; returns the access token. |
| Fetch the user's profile | get-user-profile, user-profile, get-user-info | Receives accessToken and tokenType; returns the identity details. |
Provide all three for a complete sign-in. The look of the sign-in button — its label and its colours — comes from the provider block in the plugin's capabilities.
AI Provider
| Operation | Slug(s) | Notes |
|---|---|---|
| Generate a completion | generate-completion, completion, chat | The core call. Return the text as text, completion, content or message, plus token counts and the model used. |
| Stream a completion | stream-completion, stream-chat | Optional. Return chunks under chunks. Without it the platform falls back to the completion flow and returns the result in one piece. |
| Generate an image | generate-image | Return url or data. |
| Create embeddings | embed, embed-text | Return the vector as embedding or vector. |
| Count tokens | count-tokens | Return tokens or count. |
| List models | list-models | Optional. Without it the platform uses the model list declared on the plugin. |
Every one of these receives the same input shape: prompt, model, maxTokens, temperature, topP, systemPrompt, stopSequences, messages, responseFormat, callbackUrl and metadata. A working AI plugin needs at least the completion flow.
Email Transport
| Operation | Slug(s) | Notes |
|---|---|---|
| Send an email | send-email, send-message, send | Required. Any slug containing send is accepted as a fallback. |
| Verify the connection | test-connection, verify, health-check | Confirms the credentials work. |
| Fetch bounces | get-bounces, bounce-list | Optional. |
| Look up delivery status | get-delivery-status, message-status | Optional. |
| Receive inbound mail | handle-inbound, process-webhook, inbound | Flow type Webhook Handler. |
2FA Delivery
A 2FA Delivery plugin has exactly one job: transmit a code the platform has already generated. The code is created and checked by the platform, so the flow never sees a secret to compare — it only sends what it is handed.
| Operation | Slug(s) | Notes |
|---|---|---|
| Send the code | send-code, send-otp, deliver, send | Any slug containing send is accepted as a fallback. |
The flow receives: input.code (the code to transmit), input.expiresInMinutes, input.company, and input.user with the recipient's id, email, first and last name and phone number.
The flow must show that it actually sent something. Any one of these counts:
- a
maskedTarget(ormasked_target, ortarget) in the output — a masked recipient such as+44 ****789, which the sign-in screen then shows the user; delivered: truein the output;- a successful HTTP response from a request node reaching the End node, which is what a plain passthrough End node returns.
A flow that finishes without any of those is treated as not having delivered, and the platform falls back to emailing the code. So wire an actual request node, and leave the request's error output unwired (or wired to an End that reports failure) so a rejected send fails rather than looking successful.
Two further rules apply to this flow specifically: it is never retried — re-sending a one-time code over a metered channel is worse than failing — and it must finish within ten seconds, because a person is waiting on the sign-in screen. Its execution log stores the code and the recipient's contact details masked.
Domain Registrar
A Domain Registrar plugin is an Infrastructure Provider whose service type is domains, so the lifecycle rules above apply unchanged: register through the Provision flow, and use the Suspend, Unsuspend and Terminate flow types. Its other operations are Custom Action and Data Fetch flows named for what they do:
| Operation | Flow type | Slug |
|---|---|---|
| Renew a domain | Custom Action | domain-renew |
| Domain status | Data Fetch | get-status |
| Check availability | Data Fetch | check-availability |
| Read nameservers | Data Fetch | nameservers-get |
| Change nameservers | Custom Action | nameservers-update |
| Lock against transfer | Custom Action | registrar-lock |
| Unlock for transfer | Custom Action | registrar-unlock |
| Enable WHOIS privacy | Custom Action | enable-whois-privacy |
| Fetch the transfer auth code | Custom Action | get-epp-code |
Notification, Automation and Custom
Notification plugins don't use the fixed names above. They subscribe to platform events and run a flow when each one fires; see Notification Plugins.
Automation and Custom plugins are free-form. There is no fixed set of expected names — you define flows and decide how they run: on a schedule with a Scheduled flow, from a button with a Custom Action flow, or from an inbound call with a Webhook Handler flow and an endpoint on the Webhooks tab. Use these when your integration doesn't fit one of the typed roles and you want full control over what runs and when.
Naming checklist
- Slugs are lowercase and hyphenated (
get-payment-status, notgetPaymentStatus). - Use the flow type for the four infrastructure lifecycle operations; use the slug — or the Operation field — for everything else.
- Set Operation whenever the slug you want to use doesn't exactly spell the platform operation. It is checked first.
- When several slugs are accepted, you only need one. Pick the clearest.
- Create only the flows your external service can really perform, and keep the capability checklist consistent with them.
Related: Building Flows · Node Reference · Variables & Expressions · Connections & Authentication · Configuration Settings · Notification Plugins
