> ## 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.

# Upload payroll lines

> Uploads a list of payroll lines to the system. The system will attempt to process each line and return a list of validation issues for any lines that fail. The successful lines will be returned in the response. The combination of employeeID and id must be unique. There's a hard limit of 100 items per request. In addition to the input data, the response contain an additional field 'payrollDate' - which corresponds to the date that will be considered for the payroll process. The payrollDate will always be populated - either with the date in the input - or with the very next yet unlocked date, in case the period for the given date is already locked. On HMRC submission, the system will use the date as reference to the period. Sending an id that matches an existing line item updates (fully replaces) that line item; if the existing line item belongs to an already locked period, the request is rejected with a 409 and no lines are written.



## OpenAPI

````yaml /api-reference/specs/pay-api.yaml post /payroll/line/{employeeId}
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: Payroll
  - name: Payroll lines
  - name: PayrollConfig
  - name: Pay Elements
  - name: Calculator
  - name: Payslip
  - name: RTI
  - name: YearEnd
  - name: Organisation
paths:
  /payroll/line/{employeeId}:
    post:
      tags:
        - Payroll lines
      summary: Upload payroll lines
      description: >-
        Uploads a list of payroll lines to the system. The system will attempt
        to process each line and return a list of validation issues for any
        lines that fail. The successful lines will be returned in the response.
        The combination of employeeID and id must be unique. There's a hard
        limit of 100 items per request. In addition to the input data, the
        response contain an additional field 'payrollDate' - which corresponds
        to the date that will be considered for the payroll process. The
        payrollDate will always be populated - either with the date in the input
        - or with the very next yet unlocked date, in case the period for the
        given date is already locked. On HMRC submission, the system will use
        the date as reference to the period. Sending an id that matches an
        existing line item updates (fully replaces) that line item; if the
        existing line item belongs to an already locked period, the request is
        rejected with a 409 and no lines are written.
      operationId: UploadPayroll
      parameters:
        - name: employeeId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/PayrollLineDto'
      responses:
        '201':
          description: Payroll Uploaded
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - $ref: '#/components/schemas/ResponseBody'
                  - properties:
                      content:
                        type: object
                        properties:
                          data:
                            $ref: '#/components/schemas/PayrollLineOutputDto'
        '207':
          description: Partial Success - Some Items Failed
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - $ref: '#/components/schemas/ResponseBody'
                  - properties:
                      content:
                        type: object
                        properties:
                          data:
                            $ref: '#/components/schemas/MultiStatusDataResponse'
        '400':
          description: Invalid payroll data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponseBody'
        '409':
          description: >-
            One or more ids reference an existing payroll line that belongs to
            an already locked period and cannot be overridden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponseBody'
components:
  schemas:
    PayrollLineDto:
      type: object
      required:
        - date
        - unitName
        - units
        - payRate
        - payElementId
      properties:
        id:
          type: string
          description: Optional unique identifier for the payroll line
        clientId:
          type: string
        poNumber:
          type: string
          nullable: true
          description: Purchase order number for billing purposes
          example: PO-2025-001
        date:
          type: string
        description:
          type: string
        unitName:
          type: string
          enum:
            - Hour
            - Day
            - Week
            - Month
            - Year
            - Fixed
            - Informational
            - Percentage
        unitType:
          type: string
          enum:
            - Amount
            - Percentage
          default: Amount
          description: >-
            The unit type for calculation. Amount uses payRate * units,
            Percentage uses payRate * (units / 100)
        units:
          type: number
        payRate:
          type: number
        chargeRate:
          type: number
        chargeUnits:
          type: number
          example: 1
        chargeValue:
          type: number
          format: decimal
          nullable: true
          description: The charge value times the charge units
          example: 100
        chargeDescription:
          type: string
          nullable: true
          description: >-
            Charge description for billing; when not provided and clientId is
            set, defaults to the pay description.
        payElementId:
          type: string
          description: The ID of the pay element associated with this payroll line.
        tags:
          type: array
          items:
            $ref: '#/components/schemas/TagDto'
        eligibility:
          $ref: '#/components/schemas/EligibilityDto'
          nullable: true
          description: >-
            Eligibility flags for this payroll line (court orders, pensions,
            etc.)
        paymentDetails:
          $ref: '#/components/schemas/PaymentDetailsDto'
          nullable: true
          description: >-
            Payment details (BACS information) that can override default
            employee bank account
        attachments:
          type: array
          items:
            $ref: '#/components/schemas/CreateAttachmentRequestDto'
          nullable: true
          description: >-
            Attachment metadata to include when creating the payroll line item
            (optional, only used during batch upload)
        attachmentUploadUrls:
          type: array
          items:
            $ref: '#/components/schemas/AttachmentUploadResponseDto'
          description: >-
            Pre-signed S3 URLs for uploading attachments (only present when
            attachments were provided in the request)
        invoiceId:
          type: string
          nullable: true
          description: The ID of the invoice associated with the payroll line item
          example: INV-001
        billingStatus:
          type: string
          nullable: true
          description: The billing status of the payroll line item
          example: None
          enum:
            - None
            - Accrued
            - Invoiced
        paymentAfterLeavingPattern:
          type: string
          nullable: true
          enum:
            - Irregular
            - Regular
          description: >-
            Which National Insurance earnings period this payment takes when it
            is made after the employment has ended. Only read on a payment after
            leaving, and ignored entirely for anyone who has not left. Irregular
            (accrued holiday, an unexpected bonus, arrears after a backdated pay
            award, a late commission or service charge) is charged on weekly
            thresholds; Regular (a payment they were expecting on their usual
            cycle, such as an expected bonus) keeps the employee's usual
            earnings period. Per CWG2 section 1.14 and NIM08400/NIM08410.
            Omitting it means Irregular, which is the safe default because the
            other direction understates NI. National Insurance is charged once
            per payslip, so a single Irregular payment puts the whole payslip on
            weekly thresholds.
          example: Irregular
    ResponseBody:
      type: object
      properties:
        message:
          $ref: '#/components/schemas/MessageWithTokenResponse'
        content:
          type: object
          properties:
            data:
              type: object
              nullable: true
            metadata:
              type: object
              nullable: true
              properties:
                dateFormat:
                  type: string
                  default: yyyy-MM-dd
                dateTimeFormat:
                  type: string
                  default: yyyy-MM-ddTHH:mm:ss.fffZ
                paginationToken:
                  type: string
                  nullable: true
        validationIssues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
        messageToken:
          type: string
    PayrollLineOutputDto:
      type: object
      properties:
        id:
          type: string
          example: PAYLINE-001
        clientId:
          type: string
          example: CLIENT-001
          nullable: true
        employeeId:
          type: string
          example: EMPLOYEE-001
        date:
          type: string
          example: '2024-05-20'
        payrollDate:
          type: string
          example: '2024-07-06'
        originalValue:
          type: number
          format: decimal
          nullable: true
          description: The original deduction amount before protected earnings adjustment
        canEdit:
          type: boolean
          description: >-
            Indicates whether this line item can be edited. Court order line
            items are not editable, for example, because they are automatically
            generated.
          example: true
        description:
          type: string
          example: Morning shift
        unitName:
          type: string
          enum:
            - Hour
            - Day
            - Week
            - Month
            - Year
            - Fixed
            - Informational
            - Percentage
        unitType:
          type: string
          enum:
            - Amount
            - Percentage
          default: Amount
          description: >-
            The unit type for calculation. Amount uses payRate * units,
            Percentage uses payRate * (units / 100)
        units:
          type: number
          example: 8
        payRate:
          type: number
          example: 10.5
        chargeRate:
          type: number
          example: 15.5
        chargeUnits:
          type: number
          example: 1
        chargeDescription:
          type: string
          nullable: true
          description: >-
            Charge description for billing; when not provided and clientId is
            set, defaults to the pay description.
        payElementId:
          type: string
          example: PAYELEM-001
        taxType:
          type: string
          enum:
            - Taxable
            - NonTaxable
        niType:
          type: string
          enum:
            - Niable
            - NotNiable
            - EmployerOnly
        payType:
          type: string
          enum:
            - Payable
            - Deductable
            - Informational
        eligibility:
          $ref: '#/components/schemas/EligibilityDto'
          nullable: true
          description: >-
            Eligibility flags for this payroll line (court orders, pensions,
            etc.)
        paymentDetails:
          $ref: '#/components/schemas/PaymentDetailsDto'
          nullable: true
          description: >-
            Payment details (BACS information) that can override default
            employee bank account
        lineItemMetadata:
          $ref: '#/components/schemas/LineItemMetadataDto'
          nullable: true
          description: Metadata for this line item
        statutoryType:
          type: string
          enum:
            - None
            - StatutorySickPay
            - StatutoryMaternityPay
            - StatutoryPaternityPay
            - StatutoryAdoptionPay
            - StatutorySharedParentalPay
            - StatutoryParentalBereavementPay
          nullable: true
          description: The statutory type for this payroll line
        isPensionable:
          type: boolean
          description: Whether the payroll line is pensionable
          example: true
        tags:
          type: array
          items:
            $ref: '#/components/schemas/TagDto'
        attachments:
          type: array
          items:
            $ref: '#/components/schemas/AttachmentResponseDto'
          description: >-
            List of attachments with download URLs (only present when
            attachments exist)
        attachmentUploadUrls:
          type: array
          items:
            $ref: '#/components/schemas/AttachmentUploadResponseDto'
          description: >-
            Pre-signed S3 URLs for uploading attachments (only present during
            batch upload when attachments metadata was provided)
        invoiceId:
          type: string
          nullable: true
          description: The ID of the invoice associated with the payroll line item
          example: INV-001
        creditNoteId:
          type: string
          nullable: true
          description: The ID of the credit note associated with the payroll line item
          example: CN-001
        billingStatus:
          type: string
          nullable: true
          description: The billing status of the payroll line item
          example: None
          enum:
            - None
            - Accrued
            - Invoiced
        poNumber:
          type: string
          example: PO-12345
        paymentAfterLeavingPattern:
          type: string
          nullable: true
          enum:
            - Irregular
            - Regular
          description: >-
            Which National Insurance earnings period this payment takes when it
            is made after the employment has ended. Only read on a payment after
            leaving, and ignored entirely for anyone who has not left. Irregular
            (accrued holiday, an unexpected bonus, arrears after a backdated pay
            award, a late commission or service charge) is charged on weekly
            thresholds; Regular (a payment they were expecting on their usual
            cycle, such as an expected bonus) keeps the employee's usual
            earnings period. Per CWG2 section 1.14 and NIM08400/NIM08410.
            Omitting it means Irregular, which is the safe default because the
            other direction understates NI. National Insurance is charged once
            per payslip, so a single Irregular payment puts the whole payslip on
            weekly thresholds.
          example: Irregular
    MultiStatusDataResponse:
      type: object
      properties:
        totalItems:
          type: integer
          description: Total number of items attempted to process
        totalFailed:
          type: integer
          description: Number of items that failed to process
        failedItems:
          type: array
          items:
            $ref: '#/components/schemas/PayrollLineOutputDto'
          description: List of items that failed to process
        successfulItems:
          type: array
          items:
            $ref: '#/components/schemas/PayrollLineOutputDto'
          description: List of items that were successfully processed
    TagDto:
      type: object
      required:
        - name
        - group
        - value
      properties:
        name:
          type: string
          example: FullTime
        group:
          type: string
          example: EmploymentType
        value:
          type: string
          example: FullTime
    EligibilityDto:
      type: object
      description: Eligibility flags for different types (court orders, pensions, etc.)
      properties:
        courtOrders:
          $ref: '#/components/schemas/CourtOrderEligibilityDto'
          nullable: true
          description: Court order eligibility flags for this pay element
      example:
        courtOrders:
          cmsDeo: true
          dea: true
          aeoPriority: false
          aeoNonPriority: false
          ctaeo: false
          ea: false
          mcaeo: false
    PaymentDetailsDto:
      type: object
      description: >-
        Payment details (BACS information) that can override default employee
        bank account
      properties:
        accountName:
          type: string
          nullable: true
          description: Account name
          example: CMS Central Account
        accountNumber:
          type: string
          nullable: true
          description: Account number
          example: '12345678'
        sortCode:
          type: string
          nullable: true
          description: Sort code
          example: 12-34-56
        paymentReference:
          type: string
          nullable: true
          description: >-
            Payment reference to include with BACS payment (e.g., court order
            remittance reference)
          example: CMS-2025-UK01
        paymentCategory:
          type: string
          nullable: true
          description: Payment category for categorizing payment details
          enum:
            - CourtOrders
          example: CourtOrders
    CreateAttachmentRequestDto:
      type: object
      required:
        - filename
        - contentType
        - fileSize
      properties:
        filename:
          type: string
          description: The original filename of the attachment
          example: invoice.pdf
        contentType:
          type: string
          description: The MIME type of the file (e.g., application/pdf, image/jpeg)
          example: application/pdf
        fileSize:
          type: integer
          format: int64
          description: The size of the file in bytes
          example: 102400
    AttachmentUploadResponseDto:
      type: object
      properties:
        attachmentId:
          type: string
          description: The unique identifier for the attachment
        filename:
          type: string
          description: The original filename of the attachment
        uploadUrl:
          type: string
          format: uri
          description: Pre-signed PUT URL for uploading the file to S3
        expiresAt:
          type: string
          format: date-time
          description: The expiration date/time of the upload URL (ISO 8601 format)
    MessageWithTokenResponse:
      type: object
      properties:
        text:
          type: string
        token:
          type: string
        tokenArguments:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssueArgument'
    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.
      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
          nullable: true
          items:
            $ref: '#/components/schemas/ValidationIssueArgument'
    LineItemMetadataDto:
      type: object
      description: DTO for line item metadata stored with payroll line items
      properties:
        courtOrders:
          $ref: '#/components/schemas/CourtOrderMetadataSectionDto'
          nullable: true
          description: Court order metadata for this line item
      example:
        courtOrders:
          protectedEarningsAmount: 100
          shortfallCarryForward: 0
          rateType: StandardTable
          adminFeeApplied: true
          tableType: A
          remittanceReference: REF123
          remittanceDeadline: 5 days
          jurisdiction: ENGLAND
          aeoCategory: Priority
    AttachmentResponseDto:
      type: object
      properties:
        id:
          type: string
          description: The unique identifier for the attachment
        lineItemId:
          type: string
          description: The unique identifier of the associated payroll line item
        filename:
          type: string
          description: The original filename of the attachment
        contentType:
          type: string
          description: The MIME type of the file
        fileSize:
          type: integer
          format: int64
          description: The size of the file in bytes
        uploadedDate:
          type: string
          format: date-time
          description: The date and time the file was uploaded (ISO 8601 format)
        uploadedBy:
          type: string
          description: The identifier of the user who uploaded the file
        downloadUrl:
          type: string
          format: uri
          description: Pre-signed URL for downloading the file (expires after 60 minutes)
        downloadUrlExpiresAt:
          type: string
          format: date-time
          description: The expiration date/time of the download URL (ISO 8601 format)
    CourtOrderEligibilityDto:
      type: object
      description: Court order eligibility flags for each order type
      properties:
        cmsDeo:
          type: boolean
          description: >-
            Eligible for CMS DEO (Child Maintenance Service Deduction from
            Earnings Order)
          example: true
        dea:
          type: boolean
          description: Eligible for DEA (Direct Earnings Attachment)
          example: true
        aeoPriority:
          type: boolean
          description: Eligible for AEO Priority (Attachment of Earnings Order - Priority)
          example: true
        aeoNonPriority:
          type: boolean
          description: >-
            Eligible for AEO Non-Priority (Attachment of Earnings Order -
            Non-Priority)
          example: true
        ctaeo:
          type: boolean
          description: Eligible for CTAEO (Council Tax Attachment of Earnings Order)
          example: true
        ea:
          type: boolean
          description: Eligible for EA (Earnings Attachment)
          example: false
        mcaeo:
          type: boolean
          description: >-
            Eligible for MCAEO (Maintenance Calculation Attachment of Earnings
            Order)
          example: false
    ValidationIssueArgument:
      type: object
      properties:
        name:
          type: string
        value:
          type: string
    CourtOrderMetadataSectionDto:
      type: object
      description: DTO for court order metadata
      properties:
        protectedEarningsAmount:
          type: number
          format: decimal
          nullable: true
          description: Protected earnings amount (for AEO with court-specified PER)
          example: 100
        shortfallCarryForward:
          type: number
          format: decimal
          nullable: true
          description: Shortfall carry-forward amount (for CMS DEO only)
          example: 0
        rateType:
          type: string
          nullable: true
          description: DEA rate type (StandardTable, HigherRateTable, or FixedAmount)
          example: StandardTable
        adminFeeApplied:
          type: boolean
          nullable: true
          description: Whether admin fee is applied (optional £1 per order per pay period)
          example: true
        tableType:
          type: string
          nullable: true
          description: >-
            Table type for table-based deductions (e.g., "A", "B", "MONTHLY",
            "WEEKLY")
          example: A
        remittanceReference:
          type: string
          nullable: true
          description: Remittance reference as instructed on the order
          example: REF123
        remittanceDeadline:
          type: string
          nullable: true
          description: Remittance deadline (e.g., "5 days", "19th following month")
          example: 5 days
        jurisdiction:
          type: string
          nullable: true
          description: Jurisdiction for CTAEO orders (e.g., "ENGLAND", "WALES")
          example: ENGLAND
        aeoCategory:
          type: string
          nullable: true
          description: AEO category
          example: Priority
  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).

````