Skip to main content
The Integrations API is how Flow Payroll talks to third-party providers on your behalf. Today that means NEST: you connect an employer’s NEST account once, link a pension scheme to it, and the Pensions API can then send enrolments and contribution schedules straight to NEST, approve the payment, and read back what NEST reports. Everything sent or read is recorded as an operation you can follow, retry or cancel. The service lives at /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 /providers tells 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 is nest.
  • 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 state is PendingAuth until sign-in details are saved, Callable once a test has succeeded, Invalid if the provider has since rejected them, and Deauthorised after 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-contributions and pension.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 token plus default English text. Branch on the token; show the text. The vocabulary is listed below.

What happens when something is sent

  1. A consumer, normally the Pensions API acting on your instruction, asks for a submission. An operation is created with status Pending and the request is acknowledged immediately.
  2. 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, and expectedReadyDate says when the provider expects to be done.
  3. Flow Payroll collects the result as soon as the provider has it. The operation becomes Succeeded, and for a contribution schedule providerReference carries the reference the provider assigned, which is what a later payment approval refers to.
  4. If the provider rejects the submission, or part of it, the operation becomes NeedsAttention with a token saying why, and the provider’s detailed response is kept for support to inspect.
  5. 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. attempts and nextAttemptDate show 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 NeedsAttention with provider_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}/imports asks for one or more kinds to be no older than maxStalenessMinutes (0 reads now). The response says, per kind, whether the data was already Fresh, a read was already InFlight (you are joined to it, not duplicated), a new read was Requested, or the kind is Unavailable for 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

  1. Read the catalogue with GET /providers and note the provider’s requiredCredentialFields. For NEST they are username, password and employerReference.
  2. POST /connections with providerSlug: "nest", then PUT /connections/{connectionId}/credentials with the employer’s NEST sign-in (their own or a delegate’s) and their employer reference, the EMP number.
  3. POST /connections/{connectionId}/test. On success the connection is Callable and NEST’s groups and payment sources are read in the background; GET /connections/{connectionId}/pension/setup returns them once status is ready. Set the scheme’s payment source to one of the names returned.
  4. Link the scheme: PUT /bindings/pension/pension-scheme/{schemeId} with the connectionId. From now on the scheme can be sent.
  5. If the employer already uses NEST, POST /connections/{connectionId}/sync-sessions reads what NEST holds, and GET /connections/{connectionId}/sync-sessions/latest shows progress per kind.
  6. 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 .../credentials stores them encrypted; no endpoint returns them. Test after every change.
  • Pause rather than disconnect when you want a temporary stop: PUT /connections/{connectionId} with enabled: false keeps the sign-in and the history. POST .../disconnect removes the stored sign-in and keeps the history; DELETE removes 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 while nextPaginationToken is 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 an X-Auth-Token header, and multi-organisation credentials also send X-Org-Id; see Authentication. Responses use the shared envelope described in Response format.