/v1/integrations relative to the gateway base URLs on the API reference introduction, for example https://api.sandbox.flowpayroll.ai/v1/integrations in sandbox.
The Integrations API holds the connection and the record of what happened. The submissions themselves are made through the Pensions API, which knows what a pay run contains. Read this page for how connections, freshness and reliability work; read that page for how to send a pay run.
Key concepts
- Provider: an entry in the catalogue of services Flow Payroll can send to.
GET /providerstells you how each one is signed in to, which sign-in details it needs, what it can do and which kinds of data it can be read for. NEST’s slug isnest. - Connection: one employer’s account with a provider. It holds the sign-in details (stored encrypted, never returned), the employer reference the provider knows the employer by, and the connection’s health. Its
stateisPendingAuthuntil sign-in details are saved,Callableonce a test has succeeded,Invalidif the provider has since rejected them, andDeauthorisedafter a disconnect. - Scheme link (a binding): the record that a pension scheme sends through a connection. Linking is the opt-in. A scheme that is not linked keeps delivering by export file, and nothing is ever sent for it.
- Operation: one thing sent to a provider or read from it: a batch of enrolments, a contribution schedule, a payment approval, or a read of opt-outs, stopped contributions, refunds, schedules or setup data. Every operation has a status, a count of attempts, and the provider’s own reference once it has one.
- Provider data (an import): data Flow Payroll reads from the provider rather than sends to it, one kind at a time:
pension.setup(groups and payment sources),pension.schedules,pension.opt-outs,pension.stopped-contributionsandpension.refunds. Each kind records when it was last read and the date it is synced through. - Initial import (a sync session): a one-off read of everything the provider already holds for the employer, so an employer moving to Flow Payroll starts from the provider.
- Message token: every failure carries a stable, provider-agnostic
tokenplus default English text. Branch on the token; show the text. The vocabulary is listed below.
What happens when something is sent
- A consumer, normally the Pensions API acting on your instruction, asks for a submission. An operation is created with status
Pendingand the request is acknowledged immediately. - The submission is sent to the provider. NEST processes submissions asynchronously: it acknowledges the request, then finishes it minutes or hours later. While that happens the operation is
AwaitingProvider, andexpectedReadyDatesays when the provider expects to be done. - Flow Payroll collects the result as soon as the provider has it. The operation becomes
Succeeded, and for a contribution scheduleproviderReferencecarries the reference the provider assigned, which is what a later payment approval refers to. - If the provider rejects the submission, or part of it, the operation becomes
NeedsAttentionwith a token saying why, and the provider’s detailed response is kept for support to inspect. - The consumer is told the outcome, so the Pensions API’s own record of the pay run is updated without you polling this service.
GET /operations lists everything in this cycle, newest first, and GET /operations/{operationId} follows one item.
Operation statuses
Reliability
The guarantees below are the same for every provider and every kind of operation.- Nothing is lost. An operation that cannot be completed is parked as
NeedsAttention, never discarded. It stays in the activity list with its reason until it is retried or cancelled. - Temporary failures retry themselves. If the provider cannot be reached or answers with a temporary error, the operation is retried automatically: up to five attempts spread over roughly eight hours, with the gaps growing from about half a minute to six hours. If the provider says how long to wait, that is honoured instead.
attemptsandnextAttemptDateshow where an operation is in that cycle. Only when the last attempt fails does it park. - Failures a retry cannot fix park at once. The provider rejecting the sign-in details (
provider_authentication_failed), locking the account (provider_account_locked) or rejecting the content of a submission (provider_validation_failed) are not retried, because repeating them cannot help and repeated sign-in failures can lock the account on the provider’s side. They park immediately with the reason, and you retry them once the cause is fixed. - Partial acceptance is never reported as success. If the provider accepts some members and rejects others, the operation is
NeedsAttentionwithprovider_partial_failure. - Repeated failures pause the connection, briefly. After five failures in a row on one connection, sending through it pauses for ten minutes (
connection_circuit_open) and resumes on its own. If the provider is failing for everyone, sending pauses for all connections to it until it recovers (provider_circuit_open). Paused work is not lost; it waits. - A provider that goes quiet is flagged. If the provider acknowledged a submission but has not returned a result within two days, the operation parks as
provider_result_overdue, for you to check with the provider and then retry or cancel. - Sending twice is safe. Every submission carries an idempotency key. Sending the same request again returns the original operation rather than creating a second one, so a retried call or a duplicated message cannot submit twice. The Pensions API derives its key from the pay run and the content it sends, so an unchanged run is not re-sent and a corrected one is.
- Calls are paced. Requests to a provider are kept within a conservative budget per connection (for NEST, 30 a minute and 2,000 a day, published on the provider entry). If the provider asks Flow Payroll to slow down (
provider_rate_limited), the operation waits and continues automatically. - We are alerted too. A parked operation, a paused connection and a provider that stops answering all raise alerts on our side, so support sees them without being told.
Keeping provider data fresh
Some of what decides a pay run lives with the provider: a member who opts out or stops contributions tells NEST, not Flow Payroll. Flow Payroll therefore reads that data from the provider and applies it, on three triggers:- Ahead of a pay run. The Pensions API asks for opt-outs and stopped contributions to be no older than six hours when a pay run is opened, and reads them again at the moment the run is locked, so the deductions are decided on what the provider knows at that moment.
- On a schedule. Opt-outs and stopped contributions are read at least daily. Setup data, schedules and refunds are read at least weekly, and again after every successful submission, because a submission is what changes them.
- On demand.
POST /connections/{connectionId}/importsasks for one or more kinds to be no older thanmaxStalenessMinutes(0reads now). The response says, per kind, whether the data was alreadyFresh, a read was alreadyInFlight(you are joined to it, not duplicated), a new read wasRequested, or the kind isUnavailablefor that provider.
GET /connections/{connectionId}/imports shows the state per kind: lastSuccessDate, the date the data is syncedThroughDate, whether a read is in flight, nextDueDate, and consecutiveFailures with lastErrorToken if reads are failing. Each read starts from a few days before the last successful one, so a change reported by the provider between two reads is never missed, and the synced-through date only moves forward when a read succeeds.
Reading never changes anything by itself. What is read is handed to the consumer that asked for it, and the consumer decides. For pensions, a reported opt-out is queued on GET /provider-sync/member-changes until somebody applies it, because it changes what a member is paid and carries a refund duty; applying it is what ends their Flow Payroll membership, on the date the provider gives. The Pensions API’s reconciliation endpoint shows how many were reported, applied and unmatched.
Message tokens
Every failure and every “cannot do that yet” carries a token and default English. The token is stable across releases; the text may be reworded. Treat an unrecognised token as a generic failure, because the list grows.Typical workflow
- Read the catalogue with
GET /providersand note the provider’srequiredCredentialFields. For NEST they areusername,passwordandemployerReference. POST /connectionswithproviderSlug: "nest", thenPUT /connections/{connectionId}/credentialswith the employer’s NEST sign-in (their own or a delegate’s) and their employer reference, theEMPnumber.POST /connections/{connectionId}/test. On success the connection isCallableand NEST’s groups and payment sources are read in the background;GET /connections/{connectionId}/pension/setupreturns them oncestatusisready. Set the scheme’s payment source to one of the names returned.- Link the scheme:
PUT /bindings/pension/pension-scheme/{schemeId}with theconnectionId. From now on the scheme can be sent. - If the employer already uses NEST,
POST /connections/{connectionId}/sync-sessionsreads what NEST holds, andGET /connections/{connectionId}/sync-sessions/latestshows progress per kind. - Complete a pay run, then send it through the Pensions API. Follow the resulting operations here with
GET /operations?connectionId=..., and retry or cancel from here if needed.
Notes and best practices
- Nothing sends on its own. Completing a pay run produces the export files and stops. A submission only happens when the Pensions API is asked for one, and payment approval is a separate, explicit call.
- The export files never go away. A linked scheme still produces its provider files on every pay run, so the manual route stays available as a fallback.
- Sign-in details are write-only.
PUT .../credentialsstores them encrypted; no endpoint returns them. Test after every change. - Pause rather than disconnect when you want a temporary stop:
PUT /connections/{connectionId}withenabled: falsekeeps the sign-in and the history.POST .../disconnectremoves the stored sign-in and keeps the history;DELETEremoves the connection for good, and both refuse while a scheme is still linked (connection_has_bindings). - Follow the pagination token on
GET /operations: keep going whilenextPaginationTokenis non-null, even when a page comes back empty. - Key your handling off tokens, never off message text, and expect new tokens to appear.
Authentication
Every request needs anX-Auth-Token header, and multi-organisation credentials also send X-Org-Id; see Authentication. Responses use the shared envelope described in Response format.