> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowpayroll.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Export the employees a search matches as a CSV

> Needs permission employee:export.

The file is written in the background: this answers at once with the export, and `GET /employees/exports/{exportId}` gives a link to the file once it is completed. Choose the columns and their headings; each must be a field your role can read, and the file holds only those, led by `Employee ID` unless you placed `id` yourself, so the file can be read back to update the same employees. Rows are the employees the search matches, in its order, with dated values as on `asAt`. A list's values are separated by `; `, a map's written `key=value`.



## OpenAPI

````yaml /api-reference/specs/pay-api.yaml post /employees/exports
openapi: 3.0.3
info:
  title: FlowPayroll API
  description: >-
    API for payroll management, including payroll upload, lock, HMRC submission,
    employee management
  version: 0.1.0
servers:
  - url: https://api.sandbox.flowpayroll.ai/v1
security:
  - XAuthToken: []
    XOrgId: []
tags:
  - name: Employees
    description: >-
      Create, retrieve, update, and delete employee records, and look them up by
      NI number or payroll ID.
  - name: Starters & leavers
    description: Set and clear starter and leaver details, individually or in bulk.
  - name: Tax codes
    description: >-
      Manage employee tax codes and query the effective tax code and NI category
      on a given date.
  - name: NI & identifiers
    description: Manage NI categories, National Insurance numbers, and payroll IDs.
  - name: Student loans
    description: Start and end student and postgraduate loans.
  - name: Payroll setup
    description: Assign an employee's payroll config and set opening balances.
  - name: Salary
    description: >-
      The employee's effective-dated annual salary history: read it, add or
      correct a version from a date, and remove one. The Salary API pro-rates
      this history onto each pay run.
  - name: Payroll
  - name: Payroll lines
  - name: PayrollConfig
  - name: Pay Elements
  - name: Calculator
  - name: Payslip
  - name: RTI
  - name: YearEnd
  - name: Organisation
paths:
  /employees/exports:
    post:
      tags:
        - Employees
      summary: Export the employees a search matches as a CSV
      description: >-
        Needs permission employee:export.


        The file is written in the background: this answers at once with the
        export, and `GET /employees/exports/{exportId}` gives a link to the file
        once it is completed. Choose the columns and their headings; each must
        be a field your role can read, and the file holds only those, led by
        `Employee ID` unless you placed `id` yourself, so the file can be read
        back to update the same employees. Rows are the employees the search
        matches, in its order, with dated values as on `asAt`. A list's values
        are separated by `; `, a map's written `key=value`.
      operationId: StartEmployeeExport
      parameters:
        - $ref: '#/components/parameters/Request-Id'
      requestBody:
        description: The columns, and which employees to export
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EmployeeExportRequestDto'
      responses:
        '202':
          description: Export started
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - $ref: '#/components/schemas/ResponseBody'
                  - properties:
                      content:
                        type: object
                        properties:
                          data:
                            $ref: '#/components/schemas/EmployeeExportDto'
        '400':
          description: The export cannot be made as sent; the message says why
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponseBody'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponseBody'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponseBody'
        '500':
          description: An internal server error occurred
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponseBody'
        '503':
          description: >-
            The search could not catch up with your own write; retry after the
            Retry-After seconds
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponseBody'
components:
  parameters:
    Request-Id:
      name: Request-Id
      in: header
      required: false
      description: >-
        Optional. Your id for this request: it is carried into every log line
        about it, so quote it when you contact support.
      schema:
        type: string
  schemas:
    EmployeeExportRequestDto:
      type: object
      description: A CSV of the employees a search matches, written in the background.
      required:
        - columns
      properties:
        columns:
          type: array
          items:
            $ref: '#/components/schemas/EmployeeExportColumnDto'
          description: >-
            The file's columns, in order, each a field your role can read, or an
            import column whose fields your role can read.
        search:
          $ref: '#/components/schemas/EmployeeSearchRequestDto'
          nullable: true
          description: >-
            Which employees and in what order, as `POST /employees/search` takes
            it; every employee when omitted. Its `fields`, `limit` and `offset`
            are not used: the columns choose the fields and every match is
            written.
    ResponseBody:
      type: object
      required:
        - message
      properties:
        message:
          $ref: '#/components/schemas/MessageWithTokenResponse'
          description: >-
            A readable message about the outcome and a stable token a client can
            branch on.
        content:
          type: object
          required:
            - metadata
          properties:
            data:
              description: >-
                The resource or list the request asked for; left out when there
                is none.
            metadata:
              type: object
              required:
                - dateFormat
                - dateTimeFormat
              properties:
                dateFormat:
                  type: string
                  description: The format of the dates in this response, yyyy-MM-dd.
                dateTimeFormat:
                  type: string
                  description: >-
                    The format of the timestamps in this response,
                    yyyy-MM-ddTHH:mm:ss.fffZ in UTC.
                paginationToken:
                  type: string
                  nullable: true
                  description: >-
                    Send this value back as the paginationToken query parameter
                    to get the next page; absent when there are no more pages.
              description: >-
                The date formats the response uses and, on a paged list, the
                token for the next page.
          description: >-
            The data the request returns with its metadata; left out on a
            response that carries no data, such as most errors.
        validationIssues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          nullable: true
          description: >-
            Each field the request was refused for and why; left out when the
            request was not refused for its fields.
    EmployeeExportDto:
      type: object
      description: >-
        An employee export of the organisation. Everybody who can export
        employees there sees it; the file goes to whoever started it, or to
        somebody whose role reads every column it holds.
      required:
        - exportId
        - status
        - requestedAt
      properties:
        exportId:
          type: string
          description: The export.
          example: 01JD8Y7Q3N4M5P6R7S8T9V0W1X
        status:
          type: string
          enum:
            - Queued
            - Running
            - Completed
            - Failed
          description: Where it stands.
          example: Completed
        rowCount:
          type: integer
          format: int64
          nullable: true
          description: How many employees the file holds, once completed.
          example: 6000
        downloadUrl:
          type: string
          nullable: true
          description: >-
            A link to the file, once completed. It works for 12 hours; ask again
            for a fresh one.
          example: https://files.flowpayroll.ai/files/report/exports/...
        expiresAt:
          type: string
          format: date-time
          nullable: true
          description: When the link stops working.
          example: '2026-11-06T22:00:00Z'
        error:
          type: string
          nullable: true
          description: Why it failed.
          example: niDetails.nationalInsuranceNumber is not a field this caller reads.
        requestedAt:
          type: string
          format: date-time
          description: When it was asked for.
          example: '2026-11-06T10:00:00Z'
        completedAt:
          type: string
          format: date-time
          nullable: true
          description: When it finished.
          example: '2026-11-06T10:00:12Z'
        requestedBy:
          type: string
          nullable: true
          description: >-
            Who started it: a person's or an API token's principal id, the id
            the users and API tokens routes take.
          example: USER#01JD8Y7Q3N4M5P6R7S8T9V0W1Y
        downloadUnavailable:
          type: string
          nullable: true
          description: >-
            Why there is no `downloadUrl` for you although the file is ready: it
            holds columns your role cannot read.
          example: >-
            This file has columns your role can't see. Ask whoever exported it,
            or export the columns you can see.
    EmployeeExportColumnDto:
      type: object
      description: One column of the file.
      required:
        - field
      properties:
        field:
          type: string
          description: >-
            An employee field as `GET /employee-fields` lists it, or a column of
            the app's "Existing employees" import by its key (`firstName`,
            `payrollConfigName`, `taxCode`, `ytdGross`), written as that import
            reads it back so the file imports there and into `POST
            /employees/imports` as it stands.
          example: department
        header:
          type: string
          nullable: true
          description: >-
            The column's heading; when omitted, the import's heading for an
            import key, else the field's path.
          example: Team
    EmployeeSearchRequestDto:
      type: object
      description: >-
        Employees of the organisation matching every filter, a page at a time,
        with how many match in all.
      properties:
        asAt:
          type: string
          nullable: true
          format: date
          description: >-
            The date dated values and where each employee stands are read for,
            yyyy-MM-dd; today when omitted.
          example: '2026-11-05'
        status:
          type: string
          enum:
            - All
            - Active
            - Leaver
            - FutureLeaver
          description: >-
            `Leaver`: marked a leaver or left before the date. `FutureLeaver`:
            active with a leaving date on or after it. `All` when omitted.
          example: Active
        search:
          type: string
          nullable: true
          description: Name, email, employee code or payroll ID containing this, any case.
          example: jane
        filters:
          type: array
          items:
            $ref: '#/components/schemas/EmployeeSearchFilterDto'
          nullable: true
          description: Every one must hold.
        sort:
          type: array
          items:
            $ref: '#/components/schemas/EmployeeSearchSortDto'
          nullable: true
          description: Then by last name and first name.
        fields:
          type: array
          items:
            type: string
          nullable: true
          description: >-
            The fields to answer; a group such as `address` answers all of it.
            Everything your role can read when omitted.
          example:
            - name
            - department
            - taxCode
        limit:
          type: integer
          format: int32
          description: At most this many, from 1 to 500.
          example: 100
        offset:
          type: integer
          format: int32
          description: How many matches to skip.
          example: 0
        consistentWith:
          type: array
          items:
            $ref: '#/components/schemas/EmployeeWrittenVersionDto'
          nullable: true
          description: >-
            Employees you have just written: the answer waits until it reflects
            them, or answers 503 with Retry-After when it cannot within ten
            seconds.
    MessageWithTokenResponse:
      type: object
      required:
        - text
        - token
      properties:
        text:
          type: string
          description: The message in English, ready to show to a user.
        token:
          type: string
          description: >-
            A stable snake_case key for the message, so a client can show its
            own wording or a translation instead of text.
        tokenArguments:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssueArgument'
          nullable: true
          description: >-
            Values to fill into the client's own wording for token, such as the
            request id; absent when the message has none.
    ValidationIssue:
      type: object
      description: >-
        Field validation item. `reasonToken` is a stable snake_case key for i18n
        or custom client messages; `reason` is the default English text from the
        API.
      required:
        - field
        - reason
        - reasonToken
      properties:
        field:
          type: string
          description: Dot-path of the field (e.g. name.firstName, address.line1).
        reason:
          type: string
          description: Default human-readable message.
        reasonToken:
          type: string
          description: Machine-readable error identifier (snake_case).
        reasonTokenArguments:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssueArgument'
          nullable: true
          description: >-
            Values to fill into the client's own wording for reasonToken; absent
            when the reason has none.
    EmployeeSearchFilterDto:
      type: object
      description: A condition on one employee field.
      required:
        - field
        - operator
      properties:
        field:
          type: string
          description: >-
            The field's path as `GET /employee-fields` lists it: dots between
            objects, `[]` for a list, `{}` for a map (`tags[].value`), or a
            dated value (`taxCode`, `niCategory`, `salary`, `director`,
            `studentLoan`, `postgraduateLoan`) read for `asAt`.
          example: department
        operator:
          type: string
          enum:
            - Equals
            - NotEquals
            - In
            - NotIn
            - Contains
            - StartsWith
            - GreaterThan
            - GreaterThanOrEqual
            - LessThan
            - LessThanOrEqual
            - Between
            - IsEmpty
            - IsNotEmpty
            - ContainsAll
          description: >-
            How the field is compared. `ContainsAll` is for a field with several
            values; `Contains` and `StartsWith` for text; `GreaterThan`,
            `LessThan` and `Between` for numbers and dates.
          example: In
        values:
          type: array
          items:
            type: string
          nullable: true
          description: >-
            The values compared with; dates are yyyy-MM-dd. None for `IsEmpty`
            and `IsNotEmpty`, two for `Between`.
          example:
            - Engineering
            - Sales
    EmployeeSearchSortDto:
      type: object
      description: An order to list employees in.
      required:
        - field
      properties:
        field:
          type: string
          description: A field that holds one value.
          example: starterDetails.startDate
        descending:
          type: boolean
          description: Largest or latest first.
          example: true
    EmployeeWrittenVersionDto:
      type: object
      description: An employee you have just written, so the answer reflects the write.
      required:
        - employeeId
      properties:
        employeeId:
          type: string
          description: The employee.
          example: 01JD8Y7Q3N4M5P6R7S8T9V0W1X
        updatedDate:
          type: string
          nullable: true
          description: >-
            The `updatedDate` your write returned; null when it deleted the
            employee.
          example: '2026-11-05T10:00:00.000Z'
    ValidationIssueArgument:
      type: object
      required:
        - name
        - value
      properties:
        name:
          type: string
          description: The name of the value, as a client's wording refers to it.
        value:
          description: The value itself, as a string, number or other JSON value.
  securitySchemes:
    XAuthToken:
      type: apiKey
      in: header
      name: X-Auth-Token
      description: Access token obtained from OAuth2 client credentials flow
    XOrgId:
      type: apiKey
      in: header
      name: X-Org-Id
      description: >-
        Organisation to scope the request to. Required when the principal can
        access more than one organisation; optional for single-organisation
        principals (the authorizer resolves it automatically).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.