Skip to main content
This page tracks every field in the Flow Payroll API that we have deprecated, across all services. Use it to plan your integration work: each field is listed with what to use instead and the date it is removed.
Every field on this page has a removal date, and until that date it works exactly as it does today. What removal takes away depends on the field: most are deprecated as input only and keep being returned on responses afterwards, so only what you send has to change. Check the Deprecated for column before you plan any work.

Our deprecation policy

Deprecating a field means we have stopped recommending it, not that we have stopped supporting it.
  • A deprecated field keeps working, with its existing behaviour, until its removal date. This applies wherever the field appears — a deprecated request field is still accepted and still has the same effect, and a deprecated response field is still populated with the same value. Deprecating a field never changes what it does.
  • Most deprecations are input only. We stop asking you to send a field long before we stop returning it, and often we never stop returning it: a field deprecated as input is still populated on every response after its removal date. Only the fields marked Responses stop coming back.
  • Every field gets at least 90 days between deprecation and removal. We set the removal date when we deprecate the field, and publish it here and in What’s new.
  • We announce every deprecation in What’s new as it ships, so the changelog is the one place to watch.
  • A field is only ever removed on the date published here. If we need to move a date, we move it later, never earlier.
Deprecated fields are also marked on the endpoint pages themselves, so you can see them in the context of the request or response you are building.

How to read this

Each service has its own table. Every row is one deprecated field. Where a field and its replacement can both be sent in the same request, the notes under each table say which one wins. The Flow Payroll API has 200 deprecated fields, in the Billing, Court orders, Pay API, Pensions and Reports services. Every other service in this reference has none. The earliest removal is 7 November 2026.

Billing

Why, and what to send instead
  • errors — Each entry is a copy of one validationIssues entry: field is the same, reasonText is reason, reasonId is reasonToken and reasonParameters is reasonTokenArguments. Billing writes errors on every response, as null when there are none, until the removal date.
  • metadata — A copy of content.metadata: the date formats and, on a paginated list, the cursor.
  • paginationToken and hasMorePages — The same cursor, in the place every Flow Payroll service puts it. Pass it back as the paginationToken query parameter; the rows stay where they are in content.data.
  • pageSize — Echoes the pageSize query parameter, which is not changing. A pageSize of 0 or less is refused with a 400.
  • textId — Keeps the value billing sent before, which is not always the same as token: client reads keep their old camel-case ids (clientsListedSuccessfully), and unexpected failures keep service_error_occurred. Match on token, which names each case on its own. message.text is not changing.
  • textParameters — Keeps the pairs billing sent before, such as PageSize and PaginationToken on a client list and RequestId on a failure. The request id is also on the X-Request-Id response header.
  • nextPageToken — The same cursor under the name every other list uses. Pass it back as the pageToken query parameter, which is not changing.
Returned on responses from:
  • DELETE /clients/{clientId}
  • DELETE /clients/{clientId}/credit-notes/{creditNoteId}
  • DELETE /clients/{clientId}/credit-notes/{creditNoteId}/allocations/{allocationId}
  • DELETE /clients/{clientId}/credit-notes/{creditNoteId}/attachments/{attachmentId}
  • DELETE /finance/accounts/{code}
  • DELETE /finance/tax-rates/{taxType}
  • DELETE /invoices/{clientId}/{invoiceId}/attachments/{attachmentId}
  • GET /clients
  • GET /clients/provider-contacts
  • GET /clients/{clientId}
  • GET /clients/{clientId}/credit-notes
  • GET /clients/{clientId}/credit-notes/{creditNoteId}
  • GET /clients/{clientId}/credit-notes/{creditNoteId}/external-pdf
  • GET /clients/{clientId}/credit-notes/{creditNoteId}/line-items
  • GET /clients/{clientId}/finance-settings
  • GET /clients/{clientId}/invoices
  • GET /clients/{clientId}/invoices/{invoiceId}/external-pdf
  • GET /credit-notes
  • GET /finance/accounts
  • GET /finance/accounts/provider-accounts
  • GET /finance/attachment-limits
  • GET /finance/credit-note-template
  • GET /finance/finance-defaults
  • GET /finance/invoice-reference-fields
  • GET /finance/invoice-template
  • GET /finance/line-item-description-fields
  • GET /finance/pay-element-mappings
  • GET /finance/tax-rates
  • GET /finance/tax-rates/provider-rates
  • GET /invoices
  • GET /invoices/{clientId}/{invoiceId}
  • GET /invoices/{clientId}/{invoiceId}/line-items
  • PATCH /clients/{clientId}/unarchive
  • PATCH /invoices/{clientId}/{invoiceId}
  • POST /clients
  • POST /clients/import-from-provider
  • POST /clients/{clientId}/credit-notes/{creditNoteId}/allocations
  • POST /clients/{clientId}/credit-notes/{creditNoteId}/attachments
  • POST /clients/{clientId}/credit-notes/{creditNoteId}/authorise
  • POST /clients/{clientId}/credit-notes/{creditNoteId}/sync
  • POST /clients/{clientId}/credit-notes/{creditNoteId}/void
  • POST /clients/{clientId}/invoices/{invoiceId}/sync
  • POST /clients/{clientId}/sync
  • POST /credit-notes
  • POST /finance/accounts
  • POST /finance/accounts/import-from-provider
  • POST /finance/accounts/{code}/archive
  • POST /finance/accounts/{code}/unarchive
  • POST /finance/tax-rates
  • POST /finance/tax-rates/import-from-provider
  • POST /finance/tax-rates/{taxType}/archive
  • POST /finance/tax-rates/{taxType}/unarchive
  • POST /invoices/bulk-action
  • POST /invoices/{clientId}/{invoiceId}/attachments
  • POST /invoices/{clientId}/{invoiceId}/email
  • POST /invoices/{clientId}/{invoiceId}/full-credit
  • POST /invoices/{clientId}/{invoiceId}/refresh-line-item-mappings
  • POST /invoices/{clientId}/{invoiceId}/void
  • PUT /clients/{clientId}
  • PUT /clients/{clientId}/credit-notes/{creditNoteId}
  • PUT /clients/{clientId}/finance-settings
  • PUT /finance/accounts/{code}
  • PUT /finance/credit-note-template
  • PUT /finance/finance-defaults
  • PUT /finance/invoice-template
  • PUT /finance/pay-element-mappings
  • PUT /finance/tax-rates/{taxType}
  • PUT /invoices/{clientId}/{invoiceId}
See the Billing overview for the full request shapes.

Court orders

Why, and what to send instead
  • percentageRate — An alias of percentage on a deduction from earnings order (DEO), on PUT /orders/{orderId} and on the body of POST /orders for a CmsDeo. It is read only when percentage is not sent; when both are sent, percentage wins. The two are always stored equal, and details.percentageRate on a DEO response keeps being returned, matching percentage, after the removal date.
Accepted on requests to:
  • PUT /orders/{orderId}
See the Court orders overview for the full request shapes.

Pay API

Why, and what to send instead
  • grossForEmployeeNi, grossForEmployerNi, ni and employerNi — Sent on an employee’s openingBalanceDirector.{year}. Send niBandResult keyed by NI category letter instead: the scalar totals cannot express a director who paid NI under more than one letter in a year. When niBandResult is present these totals are ignored; when it is absent they are attributed to the employee’s latest effective NI letter for the year, which is lossy. They keep being returned on responses, as the sum across letters, after the removal date.
  • pension — Sent on an employee’s openingBalance.{year}. Send pensionContributionsByType at migration time so FPS year-to-date reporting splits NetPayArrangement from ReliefAtSource correctly. When that breakdown is present this field is ignored on input; it keeps being returned on responses, as the sum of the breakdown, after the removal date.
  • salary — Deprecated as input on PUT /employees/{employeeId} and PATCH /employees/{employeeId} only. POST /employees still accepts it unchanged, as the starting salary, which becomes the first salary version effective from the employee’s start date. Record every later change with PUT /employees/{employeeId}/salary, which keeps an effective-dated history the pay run pro-rates from. While it is still accepted on PUT and PATCH, a value that differs from the salary in force today updates the most recent salary version in place rather than adding a new one, so it cannot express a change from a date; null or absent leaves the history untouched. It keeps being returned on every employee response, as the annual salary in force today, after the removal date. Read the full history from salaryHistory on the employee, or from GET /employees/{employeeId}/salary.
Accepted on requests to:
  • PATCH /employees/{employeeId}
  • POST /employees
  • PUT /employees/{employeeId}
  • PUT /employees/{employeeId}/opening-balance
Returned on responses from:
  • DELETE /employees/{employeeId}
  • DELETE /employees/{employeeId}/leaver
  • DELETE /employees/{employeeId}/ni-categories/{year}/{effectiveDate}
  • DELETE /employees/{employeeId}/tax-codes/{year}/{effectiveDate}
  • GET /employees/by-ni/{nationalInsuranceNumber}
  • GET /employees/by-payroll-id/{payrollId}
  • GET /employees/{employeeId}
  • PATCH /employees/{employeeId}
  • POST /employees
  • POST /employees/{employeeId}/ni-category
  • POST /employees/{employeeId}/postgraduate-loan/end
  • POST /employees/{employeeId}/postgraduate-loan/start
  • POST /employees/{employeeId}/student-loan/end
  • POST /employees/{employeeId}/student-loan/start
  • POST /employees/{employeeId}/tax-code
  • PUT /employees/{employeeId}
  • PUT /employees/{employeeId}/leaver
  • PUT /employees/{employeeId}/nino
  • PUT /employees/{employeeId}/opening-balance
  • PUT /employees/{employeeId}/payroll-config
  • PUT /employees/{employeeId}/payroll-id
  • PUT /employees/{employeeId}/starter
See the Pay API overview for the full request shapes.

Pensions

Why, and what to send instead
  • paginationToken — The same cursor, in the place every Flow Payroll service puts it. Pass either one back as the paginationToken query parameter until the removal date, then only the new one exists. The rows stay where they are, in content.data.items.
  • errors — Each entry is a copy of one validationIssues entry: field is the same, reasonText is reason, reasonId is reasonToken and reasonParameters is reasonTokenArguments.
  • metadata — A copy of content.metadata: the date formats and, on a paginated list, the cursor.
  • autoEnrolmentPensionGroup and manualEnrolmentPensionGroup — These two fields expose how the association is stored rather than the employee’s pension. Read pensionGroup for the group in force and isAutoEnrolled for how the employee came to be enrolled. Unlike the Pay API deprecations, these stop being returned at the removal date.
  • textId — A copy of message.token. message.text is not changing.
  • textParameters — A copy of message.tokenArguments.
  • organisationId — A pension group always belongs to the organisation in your access token, so this field tells you nothing the request did not already state. Read the organisationId of the enclosing resource where one is present.
  • isSalarySacrifice on PensionGroupV2 — Derived on responses: true only when pensionType is SalarySacrifice. pensionType also distinguishes ReliefAtSource from NetPayArrangement, which this flag cannot.
  • isSalarySacrifice on SubmitPensionGroupRequest — Read only when pensionType is omitted, and it cannot express NetPayArrangement. Send pensionType on every create and update.
Accepted on requests to:
  • POST /pension-group
  • PUT /pension-group/{id}
Returned on responses from:
  • DELETE /auto-enrolment-exemption/{employeeId}
  • DELETE /employee-pension/{employeeId}
  • DELETE /employee-pension/{employeeId}/additional-voluntary-contributions/{taxYear}/{period}
  • DELETE /employee-pension/{employeeId}/contribution-overrides/{taxYear}/{period}
  • DELETE /pension-group/{id}
  • DELETE /pension-schema/{id}
  • DELETE /postponement/{employeeId}
  • GET /auto-enrolment-exemption/{employeeId}
  • GET /auto-enrolment/assessments/payrun/{payrollConfigId}/{year}/{frequency}/{period}
  • GET /auto-enrolment/complete/payrun/{payrollConfigId}/{year}/{frequency}/{period}
  • GET /auto-enrolment/enrolment-information/outstanding
  • GET /auto-enrolment/enrolment-information/sent
  • GET /auto-enrolment/not-auto-enrolments
  • GET /auto-enrolment/not-complete
  • GET /employee-pension/batch
  • GET /employee-pension/letters/jobs/{jobId}
  • GET /employee-pension/{employeeId}
  • GET /employee-pension/{employeeId}/additional-voluntary-contributions
  • GET /employee-pension/{employeeId}/additional-voluntary-contributions/{taxYear}/{period}
  • GET /employee-pension/{employeeId}/contribution-overrides
  • GET /employee-pension/{employeeId}/contribution-overrides/{taxYear}/{period}
  • GET /employee-pension/{employeeId}/membership-ends
  • GET /employee-pension/{employeeId}/opt-out-notices
  • GET /employee-pension/{employeeId}/refund-preview
  • GET /export-file-retrieval/pension-calculation/year/{year}/period/{period}/frequency/{frequency}/payroll-config/{payrollConfigId}
  • GET /organisation
  • GET /organisation/pension-membership-ends
  • GET /pension-calculation/by-year/{year}/by-month/{month}
  • GET /pension-calculation/csv/year/{year}/period/{period}/frequency/{frequency}/payroll-config/{payrollConfigId}
  • GET /pension-calculation/export/year/{year}/period/{period}/frequency/{frequency}/payroll-config/{payrollConfigId}
  • GET /pension-calculation/pension-provider/{pensionProviderId}/by-year/{year}/by-month/{month}
  • GET /pension-group/allowed-bases
  • GET /pension-group/{id}
  • GET /pension-information/{employeeId}
  • GET /pension-provider
  • GET /pension-provider/slug/{slug}
  • GET /pension-provider/{id}
  • GET /pension-schema/organisation
  • GET /pension-schema/{id}
  • GET /postponement/{employeeId}
  • GET /provider-sync/member-changes
  • GET /provider-sync/member-changes/summary
  • GET /provider-sync/reconciliation
  • GET /provider-sync/returns
  • GET /provider-sync/{payrollConfigId}/{year}/{frequency}/{period}
  • GET /provider-sync/{payrollConfigId}/{year}/{frequency}/{period}/issues
  • GET /provider-sync/{payrollConfigId}/{year}/{frequency}/{period}/sendable
  • POST /auto-enrolment/assessments/preview
  • POST /employee-pension
  • POST /employee-pension/letters/{letterType}
  • POST /employee-pension/{employeeId}/enrolment-letter
  • POST /employee-pension/{employeeId}/opt-out-notices
  • POST /pension-calculation
  • POST /pension-calculation/export
  • POST /pension-group
  • POST /pension-schema
  • POST /provider-sync/member-changes/{changeId}/acknowledge
  • POST /provider-sync/member-changes/{changeId}/apply
  • POST /provider-sync/member-changes/{changeId}/delete
  • POST /provider-sync/member-changes/{changeId}/dismiss
  • POST /provider-sync/{payrollConfigId}/{year}/{frequency}/{period}/approve-payment
  • POST /provider-sync/{payrollConfigId}/{year}/{frequency}/{period}/refresh-members
  • POST /provider-sync/{payrollConfigId}/{year}/{frequency}/{period}/send
  • PUT /auto-enrolment-exemption
  • PUT /employee-pension/{employeeId}/additional-voluntary-contributions/{taxYear}/{period}
  • PUT /employee-pension/{employeeId}/contribution-overrides/{taxYear}/{period}
  • PUT /organisation/pension-default/auto-enrolment-settings
  • PUT /organisation/pension-default/postponement-settings
  • PUT /pension-group/{id}
  • PUT /pension-schema/{id}
  • PUT /postponement
See the Pensions overview for the full request shapes.

Reports

Why, and what to send instead
  • webhookUrl — Sent in delivery when creating a schedule. Subscribe a Webhooks API endpoint to report_export.completed (and report_export.failed) instead: every export run sends one, scheduled or queued through POST /exports, carrying the runId and scheduleId to route on, and the webhooks service signs, retries and logs it like every other event. The event links to GET /exports/{runId} rather than carrying a download link. Until the removal date a schedule created with a webhookUrl still receives the legacy X-Flow-Signature POST exactly as before; after it the field is ignored on input and no longer returned on schedules.
  • webhookSecret — Only ever returned once, on creating a schedule with a webhookUrl, to verify the legacy X-Flow-Signature header. An endpoint created through the Webhooks API carries its own signing secrets, with rotation. Stops being returned when webhookUrl is removed.
Accepted on requests to:
  • POST /report-definitions/{definitionId}/schedules
Returned on responses from:
  • GET /report-definitions/{definitionId}/schedules
  • POST /report-definitions/{definitionId}/schedules
See the Reports overview for the full request shapes.

Deprecated request shapes

The tables above list fields. One deprecation is a whole request body shape rather than a field, so it is tracked here by hand. Until the removal date the bare object is read as finalSubmissionDetails with no late reason and behaves exactly as it did before. Nothing in the response changes.

Migrating away from a deprecated field

1

Work back from the earliest removal date

Take the earliest date in the tables above and check what your integration does with those fields. Anything you send is a code change; anything you read is a parsing change.
2

Switch what you send

For the fields marked Input only or Input and responses, send the replacement in the Use instead column instead. Then stop sending the deprecated field alongside it — sending both is supported until removal, but the notes above define which value the API uses, and dropping the old field removes the ambiguity.
3

Leave your response parsing alone unless the field says Responses

A field marked still returned keeps coming back after its removal date, so there is nothing to change in what you read. Only the fields marked Responses or Input and responses stop being populated — for those, read the replacement and make sure your parsing tolerates the old field being missing rather than failing on it.
4

Subscribe to the changelog

Every deprecation and every removal date is announced in What’s new. Subscribe to its RSS feed so a new date reaches you without checking this page.
Need more time than a removal date allows? Email us before the date — we would rather move it than break your integration.

Support

Unsure how a deprecation affects your integration, or need longer to migrate? Email hello@flowpayroll.ai.