What shipped
The Fluxa payment state machine is locked in. Every transaction passes through four primary states, with two terminal states for failure and refund paths.
- PAYMENT_RECEIVED
- The cardholder has authorised the transaction. Funds are not yet captured by Fluxa. This is the brief window between the cardholder’s issuer approving the authorisation and Fluxa moving the transaction into the capture pipeline.
- CAPTURED
- Fluxa has captured the funds via the payments partner. The merchant’s liability for delivering goods or services has started; the cardholder’s issuer has been instructed to settle the funds onward.
- SETTLING
- The funds are in flight from the payments partner to the merchant’s nominated UK bank account. The scheduled settlement date is visible on every transaction in this state.
- SETTLED
- The funds have arrived in the merchant’s bank account. The settlement reference is logged against the transaction; the transaction is closed for the happy path.
Plus two terminal states: FAILED (the transaction did not capture; the reason is logged from the payments partner’s response) and REFUNDED (the transaction was refunded to the cardholder, either in full or partial, with the original capture reversed on a per-line basis). Every state transition is visible in the merchant dashboard, in the API and on every webhook payload.
Why it matters
Most card processors hide the payment lifecycle behind a single status (most commonly “completed” or “successful”) or expose a generic processing state with no clear next-step indication. The merchant cannot tell from the dashboard whether a transaction is captured but not yet settling, or settling but not yet settled, or whether it has failed silently somewhere upstream.
Fluxa exposes the lifecycle as primary data. The merchant knows whether a transaction is captured (their liability for delivering goods has started), settling (the money is coming, on a known date), or settled (the money is in the bank). The state machine is the same on the dashboard, the API, the webhook payload and the double-entry ledger. There is no privileged view available only to Fluxa staff.
The detail
The state machine is enforced at the database layer. The architecture choices that matter:
- Atomic transitions
- State changes use database WHERE-clause guards:
UPDATE payments SET state = 'SETTLING' WHERE id = $1 AND state = 'CAPTURED'. The update only succeeds if the current state matches the expected previous state. Race conditions on parallel handlers cannot put a payment into an inconsistent state.
- Independent ledger
- The double-entry ledger records movements in parallel with the state machine. If the state machine and the ledger disagree on the balance of any account, the ledger is the source of truth and the state machine is reconciled to match. Discrepancies fire a P1 alert to the operations inbox.
- Webhook signalling
- Every state transition fires a webhook (
payment.captured, payment.settling, payment.settled, payment.failed, payment.refunded) with the full payment object, the previous state, the new state, the transition timestamp and the HMAC-SHA256 signature for verification.
- Append-only history
- State changes are recorded in an append-only history table with the actor (system / merchant / operator), the timestamp, the previous state, the new state and the reason code. The history is queryable from the dashboard and exportable as CSV; it cannot be rewritten.
- PFaaS compliance
- The state model is reviewed against the payments partner’s PFaaS programme requirements and against the Payment Card Industry Data Security Standard v4.0 SAQ-A scope. The lifecycle is documented under the developer docs.
What follows
The recurring billing state machine (subscription lifecycle: trial, active, past-due, cancelled, paused) is built on top of the payment state machine. Same architectural pattern, same atomic transitions, same webhook signalling per transition. It lands in v5.7 alongside the smart triage in the dashboard.
The state model is locked because changing it post-launch will break every merchant’s webhook handler. Any future changes are additive (new states, never renamed states) and announced ninety days in advance with a deprecation path for the previous state. The states above are the public API contract.
State-model questions: support@fluxapay.co.uk. The full lifecycle diagram is on the developer docs under “Payment lifecycle”.