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

# Perform an action on several expense reports

> Performs the action given by the `action` query parameter on the expense reports listed in the request body. Every action is all or nothing: the whole batch is validated before anything happens, so a 4xx always means nothing was sent, paid, reminded or moved. The reverse does not hold, a 200 does not mean every requested report was processed - `setPaid` answers 200 with `missingBankAccountNumber` when nothing was paid, and `sendApproverReminders` answers 200 after skipping the reports that are not waiting for an approver. In both cases the response body says what actually happened, so compare it against what you requested.

`send` sends the batch to its recipient. Reports that are not in a status the recipient accepts come back in `invalidReports` with a 400. On success the batch is handed to a send job and its id is returned in `jobIds`.

`setPaid` marks the reports as paid and optionally sends a payment basis mail with a combined payment basis PDF and a payment file. Reports in a status that can not be paid come back in `invalidReports` with a 400. Report owners without a bank account number are returned in `missingBankAccountNumber` with a 200, so that the caller can show the affected owners.

`sendApproverReminders` reminds the approvers that still have these reports on their todo list. Reports that are not in `APPROVAL` or `APPROVAL_CANDIDATE` are skipped, and the ids a reminder was actually sent for come back in `expenseReportIds`.

`setStatus` changes the status of the reports and/or moves them to another recipient. It is a collection level action rather than repeated single report calls because moving several reports is not the same operation as moving one report several times: it always writes the change log, always moves the send chain step, and can move reports to another recipient without changing their status. Use `PUT /organizations/{organizationId}/reports/{reportId}?action=setStatus` for a single report.

`moveToNextStep` moves reports that are in `TRANSFER` or `TRANSFER_TO_RECIPIENT` to the next step of their send chain. Reports that can not be moved come back in `invalidReports` with a 400. Restricted to the developer role.




## OpenAPI

````yaml /openapi/findity-admin-api.json put /organizations/{organizationId}/reports
openapi: 3.1.0
info:
  title: Findity Admin API
  description: Findity Admin API
  version: 1.0.0
servers:
  - url: https://stage-api.findity.com/api/v1/admin
  - url: https://api.findity.com/api/v1/admin
security:
  - bearerAuth: []
paths:
  /organizations/{organizationId}/reports:
    put:
      tags:
        - Expense Reports
      summary: Perform an action on several expense reports
      description: >
        Performs the action given by the `action` query parameter on the expense
        reports listed in the request body. Every action is all or nothing: the
        whole batch is validated before anything happens, so a 4xx always means
        nothing was sent, paid, reminded or moved. The reverse does not hold, a
        200 does not mean every requested report was processed - `setPaid`
        answers 200 with `missingBankAccountNumber` when nothing was paid, and
        `sendApproverReminders` answers 200 after skipping the reports that are
        not waiting for an approver. In both cases the response body says what
        actually happened, so compare it against what you requested.


        `send` sends the batch to its recipient. Reports that are not in a
        status the recipient accepts come back in `invalidReports` with a 400.
        On success the batch is handed to a send job and its id is returned in
        `jobIds`.


        `setPaid` marks the reports as paid and optionally sends a payment basis
        mail with a combined payment basis PDF and a payment file. Reports in a
        status that can not be paid come back in `invalidReports` with a 400.
        Report owners without a bank account number are returned in
        `missingBankAccountNumber` with a 200, so that the caller can show the
        affected owners.


        `sendApproverReminders` reminds the approvers that still have these
        reports on their todo list. Reports that are not in `APPROVAL` or
        `APPROVAL_CANDIDATE` are skipped, and the ids a reminder was actually
        sent for come back in `expenseReportIds`.


        `setStatus` changes the status of the reports and/or moves them to
        another recipient. It is a collection level action rather than repeated
        single report calls because moving several reports is not the same
        operation as moving one report several times: it always writes the
        change log, always moves the send chain step, and can move reports to
        another recipient without changing their status. Use `PUT
        /organizations/{organizationId}/reports/{reportId}?action=setStatus` for
        a single report.


        `moveToNextStep` moves reports that are in `TRANSFER` or
        `TRANSFER_TO_RECIPIENT` to the next step of their send chain. Reports
        that can not be moved come back in `invalidReports` with a 400.
        Restricted to the developer role.
      operationId: updateOrganizationExpenseReports
      parameters:
        - name: organizationId
          in: path
          required: true
          description: >-
            The unique identifier of the organization. String, UUID format
            (32-character hexadecimal). Required.
          schema:
            $ref: '#/components/schemas/Uuid'
            example: 05b8daba9ba14a49846fe77883248cf0
        - $ref: '#/components/parameters/expenseReportsAction'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              anyOf:
                - $ref: '#/components/schemas/SendExpenseReports'
                - $ref: '#/components/schemas/SetExpenseReportsPaid'
                - $ref: '#/components/schemas/SendApproverReminders'
                - $ref: '#/components/schemas/UpdateExpenseReports'
                - $ref: '#/components/schemas/ExpenseReportIds'
            examples:
              send:
                value:
                  expenseReportIds:
                    - 05b8daba9ba14a49846fe77883248cf0
                    - 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                  date: 2026-08-05T00:00:00+0200
                  recipientId: 3f2b1a0c9d8e7f6a5b4c3d2e1f0a9b8c
              setPaid:
                value:
                  expenseReportIds:
                    - 05b8daba9ba14a49846fe77883248cf0
                    - 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                  email: finance@example.com
                  generateFile: true
                  paymentDate: '260801'
                  bankCode: '9900'
                  customerNumber: '123456'
              sendApproverReminders:
                value:
                  expenseReportIds:
                    - 05b8daba9ba14a49846fe77883248cf0
                    - 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                  message: Please review these reports before the end of the month
              setStatus:
                summary: >-
                  Move the reports to a status, and to another recipient at the
                  same time
                value:
                  expenseReportIds:
                    - 05b8daba9ba14a49846fe77883248cf0
                    - 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                  status: READY_TO_SEND
                  recipientId: 3f2b1a0c9d8e7f6a5b4c3d2e1f0a9b8c
              setStatusRecipientOnly:
                summary: >-
                  Move the reports to another recipient and keep their current
                  status
                value:
                  expenseReportIds:
                    - 05b8daba9ba14a49846fe77883248cf0
                    - 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                  recipientId: 3f2b1a0c9d8e7f6a5b4c3d2e1f0a9b8c
              moveToNextStep:
                summary: Advance the reports to the next step of their send chain
                value:
                  expenseReportIds:
                    - 05b8daba9ba14a49846fe77883248cf0
                    - 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
      responses:
        '200':
          description: >
            The action was carried out, with two documented exceptions. A
            `setPaid` where a report owner has no bank account number answers
            200 with `missingBankAccountNumber` filled in and nothing was paid,
            mirroring the legacy setpaid endpoint where only `invalidReports`
            turns the response into a 400. A `sendApproverReminders` answers 200
            with only the ids a reminder was actually sent for, the reports that
            were not waiting for an approver are left out.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/SendExpenseReportsResult'
                  - $ref: '#/components/schemas/SetExpenseReportsPaidResult'
                  - $ref: '#/components/schemas/SendApproverRemindersResult'
                  - $ref: '#/components/schemas/MoveExpenseReportsResult'
                  - type: object
                    properties:
                      result:
                        type: string
                        description: '"success" when the reports were moved.'
                      description:
                        type: string
                        description: Human readable confirmation message.
              examples:
                sent:
                  summary: The batch was handed to a send job
                  value:
                    reports:
                      - id: 05b8daba9ba14a49846fe77883248cf0
                        name: Trip to Berlin
                        status: BULK_TRANSFER
                      - id: 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                        name: Trip to Oslo
                        status: BULK_TRANSFER
                    invalidReports: []
                    jobIds:
                      - a1b2c3d4e5f60718293a4b5c6d7e8f90
                paid:
                  summary: The reports were marked as paid
                  value:
                    reports:
                      - id: 05b8daba9ba14a49846fe77883248cf0
                        name: Trip to Berlin
                        status: SENT
                    invalidReports: []
                    missingBankAccountNumber: []
                missingBankAccountNumber:
                  summary: >-
                    The reports were marked as paid, but an owner has no bank
                    account number
                  value:
                    reports:
                      - id: 05b8daba9ba14a49846fe77883248cf0
                        name: Trip to Berlin
                        status: SENT
                    invalidReports: []
                    missingBankAccountNumber:
                      - employee@example.com
                remindersSent:
                  summary: >-
                    A reminder was sent for the reports that are waiting for an
                    approver
                  value:
                    expenseReportIds:
                      - 05b8daba9ba14a49846fe77883248cf0
                statusChanged:
                  summary: The reports were moved
                  value:
                    result: success
                    description: reports were moved
                movedToNextStep:
                  summary: >-
                    The reports were advanced to the next step of their send
                    chain
                  value:
                    reports:
                      - id: 05b8daba9ba14a49846fe77883248cf0
                        name: Trip to Berlin
                        status: READY_TO_SEND
                    invalidReports: []
        '400':
          description: >-
            Nothing happened — invalid action, invalid parameters, or reports
            the action can not be applied to
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/SendExpenseReportsResult'
                  - $ref: '#/components/schemas/SetExpenseReportsPaidResult'
                  - $ref: '#/components/schemas/MoveExpenseReportsResult'
                  - $ref: '#/components/schemas/400Error'
              examples:
                invalidReportsForSend:
                  summary: >-
                    One report is not in a status the recipient accepts, so
                    nothing was sent
                  value:
                    reports: []
                    invalidReports:
                      - id: 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                        name: Trip to Oslo
                        status: NORMAL
                invalidReportsForSetPaid:
                  summary: >
                    One report of the batch can not be paid, so nothing was
                    paid. reports lists every requested report, invalidReports
                    the offending subset.
                  value:
                    reports:
                      - id: 05b8daba9ba14a49846fe77883248cf0
                        name: Trip to Berlin
                        status: SENT
                      - id: 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                        name: Trip to Oslo
                        status: NORMAL
                    invalidReports:
                      - id: 7c1f0a3b9d2e4f5a8b6c0d1e2f3a4b5c
                        name: Trip to Oslo
                        status: NORMAL
                    missingBankAccountNumber: []
                invalidAction:
                  value:
                    result: error
                    code: INVALID_ACTION
                    description: Invalid action specified, was 'transmit'
                missingParameter:
                  value:
                    result: error
                    code: MISSING_PARAMETER
                    description: expenseReportIds is required for action 'send'
                invalidParameter:
                  value:
                    result: error
                    code: INVALID_PARAMETER
                    description: A maximum of 100 reports can be handled at once, got 101
                invalidStatus:
                  summary: setStatus was given a status this action does not handle
                  value:
                    result: error
                    code: INVALID_PARAMETER
                    description: >-
                      Invalid status specified, was 'NORMAL'. Allowed statuses
                      are READY_TO_SEND, SENT, PAID
                missingStatusAndRecipient:
                  summary: setStatus with neither a status nor a recipientId
                  value:
                    result: error
                    code: MISSING_PARAMETER
                    description: status or recipientId is required for action 'setStatus'
                invalidReportsForMoveToNextStep:
                  summary: >-
                    One report is not in a status that can be advanced, so
                    nothing was moved
                  value:
                    reports: []
                    invalidReports:
                      - id: 05b8daba9ba14a49846fe77883248cf0
                        name: Trip to Berlin
                        status: NORMAL
        '403':
          description: >
            The caller may not perform the action. `send` and `setPaid` require
            the organization to have the report sending function,
            `moveToNextStep` requires the developer role,
            `sendApproverReminders` and `setStatus` only require access to the
            organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/403Error'
              examples:
                missingSendFunction:
                  value:
                    result: error
                    description: Insufficient rights
                noAccess:
                  value:
                    result: error
                    description: Not allowed
        '404':
          description: The organization or one of the expense reports was not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/404Error'
              examples:
                organizationNotFound:
                  value:
                    result: error
                    code: ORGANIZATION_NOT_FOUND
                    description: Organization not found
                expenseReportNotFound:
                  value:
                    result: error
                    code: EXPENSE_REPORT_NOT_FOUND
                    description: Expense report not found
components:
  schemas:
    Uuid:
      type: string
      pattern: ^[0-9a-fA-F]{32}$
      description: UUID without dashes (32-character hex string)
    SendExpenseReports:
      type: object
      description: >
        Request body for the `send` action on the reports collection. Sends the
        listed reports as one batch: every report is validated first, nothing is
        sent unless all of them can be sent, and the batch becomes a single send
        job.
      required:
        - expenseReportIds
      properties:
        expenseReportIds:
          type: array
          description: >-
            The expense reports to send. Array of strings, UUID format
            (32-character hexadecimal), 1-100 items. Required.
          minItems: 1
          maxItems: 100
          items:
            $ref: '#/components/schemas/Uuid'
        date:
          type: string
          description: >
            Booking date for the batch. String, format yyyy-MM-dd'T'HH:mm:ssZ.
            Optional, defaults to the time the request is handled.
        recipientId:
          type: string
          description: >
            Recipient the batch is sent to. String, UUID format (32-character
            hexadecimal). Optional, but the pre-check that every report is in a
            status the recipient accepts only runs when it is given.
    SetExpenseReportsPaid:
      type: object
      description: >
        Request body for the `setPaid` action. Marks the listed expense reports
        as paid. This is a batch operation: one payment basis mail with one
        combined PDF and one payment file is produced for the whole batch. If
        any of the reports can not be paid, none of them is paid.
      required:
        - expenseReportIds
      properties:
        expenseReportIds:
          type: array
          description: >-
            The expense reports to mark as paid. Array of strings, UUID format
            (32-character hexadecimal), 1-100 items. Required.
          minItems: 1
          maxItems: 100
          items:
            $ref: '#/components/schemas/Uuid'
        email:
          type: string
          format: email
          description: >-
            Recipient of the payment basis mail. When omitted no mail is sent.
            String, email format. Optional.
        noPdf:
          type: boolean
          description: >-
            Set to true to leave the payment basis PDF out of the payment basis
            mail. Boolean. Optional, defaults to false.
        generateFile:
          type: boolean
          description: >
            Set to true when a payment file is wanted. On its own it only turns
            on the bank account number check: if any report owner is missing
            one, nothing is paid and the affected owners are returned in
            `missingBankAccountNumber` with a 200. The file itself is attached
            only when `email`, `paymentDate`, `bankCode` and `customerNumber`
            are all provided as well. Boolean. Optional, defaults to false.
        paymentDate:
          type: string
          description: >
            Payment date written into the payment file. String, format yyMMdd.
            The payment file is a fixed width format that holds the date in six
            characters, which is why this is not the ISO-8601 datetime the
            `send` action uses for its `date`. Optional, but a payment file is
            only generated when `paymentDate`, `bankCode` and `customerNumber`
            are all provided.
        bankCode:
          type: string
          description: >-
            Bank code written into the payment file header. String, maximum 10
            characters. Optional.
        customerNumber:
          type: string
          description: >-
            Customer number written into the payment file header. String,
            maximum 6 characters. Optional.
    SendApproverReminders:
      type: object
      description: >
        Request body for the `sendApproverReminders` action. Reminds the
        approvers that still have the listed reports on their todo list.
      required:
        - expenseReportIds
      properties:
        expenseReportIds:
          type: array
          description: >-
            The expense reports to remind the approvers of. Array of strings,
            UUID format (32-character hexadecimal), 1-100 items. Required.
          minItems: 1
          maxItems: 100
          items:
            $ref: '#/components/schemas/Uuid'
        message:
          type: string
          description: >
            Message included in the reminder mail. String. Optional, the mail is
            sent without a message when omitted.
    UpdateExpenseReports:
      type: object
      description: >
        Bulk status change for several expense reports of an organization,
        optionally also moving them to another recipient. Used with
        action=setStatus on the reports collection.
      required:
        - expenseReportIds
      properties:
        expenseReportIds:
          type: array
          minItems: 1
          maxItems: 100
          description: >
            Ids of the expense reports to move. Array of strings, required, at
            least 1 and at most 100 entries. Every report must belong to the
            organization in the path.
          items:
            allOf:
              - $ref: '#/components/schemas/Uuid'
            description: Id of an expense report. String, UUID format (32-character hex).
        status:
          type: string
          description: >
            Target lifecycle status for all listed reports, case insensitive.
            String. Optional, but at least one of status and recipientId must be
            given: supply recipientId without status to move the reports to
            another recipient while keeping their status. The request is
            rejected with 400 when both are missing. Accepted values are
            READY_TO_SEND, SENT and PAID; any other value, known lifecycle
            status or not, is rejected with 400 INVALID_PARAMETER. Returning
            reports to their owner is a single report operation, so NEW and
            NORMAL are not accepted here. The transition itself is not validated
            - the reports are moved to the given status whatever their current
            one is. Unlike the single report action, this operation does not
            write the booking, sent to booking or paid dates.
        recipientId:
          allOf:
            - $ref: '#/components/schemas/Uuid'
          description: >
            Recipient to move the reports' send chain step to. String, UUID
            format (32-character hex). Optional. When omitted, every step of the
            send chain is marked as sent.
      example:
        expenseReportIds:
          - 05b8daba9ba14a49846fe77883248cf0
          - 15b8daba9ba14a49846fe77883248cf1
        status: READY_TO_SEND
        recipientId: 25b8daba9ba14a49846fe77883248cf2
    ExpenseReportIds:
      type: object
      description: The expense reports a collection level action should be applied to.
      required:
        - expenseReportIds
      properties:
        expenseReportIds:
          type: array
          description: >-
            The expense reports to act on. Array of strings, UUID format
            (32-character hexadecimal), 1-100 items. Required.
          minItems: 1
          maxItems: 100
          items:
            $ref: '#/components/schemas/Uuid'
    SendExpenseReportsResult:
      type: object
      description: >
        Result of the batch `send` action. Nothing is sent when `invalidReports`
        is non-empty, and the response status is 400 in that case.
      properties:
        reports:
          type: array
          description: >-
            The reports that were handed to the send job. Empty when nothing was
            sent.
          items:
            type: object
            properties:
              id:
                $ref: '#/components/schemas/Uuid'
              name:
                type: string
                description: The display name of the expense report. String.
              status:
                type: string
                description: The status the report was moved to, BULK_TRANSFER. String.
        invalidReports:
          type: array
          description: >-
            Reports that are not in a status the recipient accepts, which is why
            nothing was sent.
          items:
            type: object
            properties:
              id:
                $ref: '#/components/schemas/Uuid'
              name:
                type: string
                description: The display name of the expense report. String.
              status:
                type: string
                description: The status that prevents the report from being sent. String.
        jobIds:
          type: array
          description: >
            Identifiers of the send jobs the batch became, for following their
            progress. Normally one, but a recipient configured to take each
            report separately turns the batch into one job per report. Array of
            strings, empty when nothing was sent.
          items:
            type: string
    SetExpenseReportsPaidResult:
      type: object
      description: >
        Result of the `setPaid` action. Nothing is paid when `invalidReports` or
        `missingBankAccountNumber` is non-empty; `invalidReports` comes with a
        400, `missingBankAccountNumber` with a 200.
      properties:
        reports:
          type: array
          description: The reports the action was applied to. Array of objects.
          items:
            type: object
            properties:
              id:
                $ref: '#/components/schemas/Uuid'
              name:
                type: string
                description: The display name of the expense report. String.
              status:
                type: string
                description: The status of the expense report before the action. String.
        invalidReports:
          type: array
          description: >-
            Reports that are in a status that can not be paid. Array of objects,
            empty when the batch was paid.
          items:
            type: object
            properties:
              id:
                $ref: '#/components/schemas/Uuid'
              name:
                type: string
                description: The display name of the expense report. String.
              status:
                type: string
                description: The status that prevents the report from being paid. String.
        missingBankAccountNumber:
          type: array
          description: >
            Email addresses of report owners without a bank account number. Only
            filled in when `generateFile` is true. Array of strings, empty when
            the batch was paid.
          items:
            type: string
    SendApproverRemindersResult:
      type: object
      description: Result of the `sendApproverReminders` action.
      properties:
        expenseReportIds:
          type: array
          description: >
            The reports a reminder was sent for. Requested reports that are not
            in `APPROVAL` or `APPROVAL_CANDIDATE` are left out, since their
            approvers have nothing left to approve. Array of strings, UUID
            format (32-character hexadecimal).
          items:
            $ref: '#/components/schemas/Uuid'
    MoveExpenseReportsResult:
      type: object
      description: >
        Result of the `moveToNextStep` action. Nothing is moved when
        `invalidReports` is non-empty, and the response status is 400 in that
        case.
      properties:
        reports:
          type: array
          description: >-
            The reports that were moved, with the status they ended up in. Empty
            when nothing was moved.
          items:
            type: object
            properties:
              id:
                $ref: '#/components/schemas/Uuid'
              name:
                type: string
                description: The display name of the expense report. String.
              status:
                type: string
                description: >-
                  The status the report was moved to, READY_TO_SEND or SENT.
                  String.
        invalidReports:
          type: array
          description: >
            Reports that could not be moved, because they do not exist in the
            organization, are not in TRANSFER or TRANSFER_TO_RECIPIENT, or have
            no next recipient in their send chain.
          items:
            type: object
            properties:
              id:
                $ref: '#/components/schemas/Uuid'
              name:
                type: string
                description: >-
                  The display name of the expense report, null when the report
                  does not exist. String.
              status:
                type: string
                description: >-
                  The status that prevents the report from being moved, null
                  when the report does not exist. String.
    400Error:
      type: object
      properties:
        result:
          type: string
        code:
          type: string
        description:
          type: string
    403Error:
      type: object
      properties:
        result:
          type: string
        description:
          type: string
      example:
        result: error
        description: Not allowed
    404Error:
      type: object
      properties:
        result:
          type: string
        code:
          type: string
        description:
          type: string
      example:
        result: error
        code: ORGANIZATION_NOT_FOUND
        description: 'Failed to get organization for id: {orgId}'
  parameters:
    expenseReportsAction:
      in: query
      name: action
      required: true
      description: >
        Action to perform on the expense reports listed in the request body.
        String, enum. Required. Accepted values: send, setPaid,
        sendApproverReminders, setStatus, moveToNextStep. `moveToNextStep` is
        restricted to the developer role.
      schema:
        type: string
        enum:
          - send
          - setPaid
          - sendApproverReminders
          - setStatus
          - moveToNextStep
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````