openapi: 3.0.0
info:
  title: Partner API
  version: 0.0.1
  description: >-
    API for payroll providers to integrate with Aslan. This API enables payroll
    providers to manage company registrations and employee onboarding for Aslan
    services.
tags:
  - name: Companies
    description: Manage company registrations and details for Aslan enrollment
  - name: Users
    description: Manage employee records and their eligibility for earned wage access
  - name: Reports
    description: Access spend reports and transaction data for payroll deductions
servers:
  - url: https://uat.partner.aslan.io/api/v1
  - url: https://partner.aslan.io/api/v1
paths:
  /companies:
    get:
      summary: Retrieve all companies
      description: >-
        Returns a paginated list of all companies registered with Aslan. This
        endpoint provides an overview of all employer clients in the system with
        support for filtering and sorting.
      operationId: getAllCompanies
      tags:
        - Companies
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: params
          in: query
          required: false
          style: deepObject
          explode: true
          schema:
            $ref: '#/components/schemas/CompanyQueryParams'
      responses:
        '200':
          description: Successfully retrieved paginated list of companies
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyPageResponse'
        '400':
          description: Bad request - invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /companies/{companyId}:
    get:
      summary: Retrieve company details
      description: >-
        Returns detailed information for a specific company, including
        registration status, company information, and audit trail.
      operationId: getCompanyById
      tags:
        - Companies
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: companyId
          in: path
          description: The unique identifier for the company
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Successfully retrieved company details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Company not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      summary: Update company information
      description: >-
        Updates company details such as name and address. This endpoint is
        typically used when company information changes in the payroll system.
      operationId: updateCompanyById
      tags:
        - Companies
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: companyId
          in: path
          description: The unique identifier for the company
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCompanyRequest'
      responses:
        '200':
          description: Company successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyResponse'
        '400':
          description: Bad request - invalid data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Company not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /companies/{companyId}/users:
    get:
      summary: Retrieve all employees for a company
      description: >-
        Returns a paginated, summarized list of all employees registered under a
        specific company with Aslan. This endpoint provides essential employee
        information without sensitive or detailed fields. Supports filtering by
        status, role, and date ranges, plus sorting capabilities.
      operationId: getAllUsers
      tags:
        - Users
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: companyId
          in: path
          description: The unique identifier for the company
          required: true
          schema:
            type: string
            format: uuid
        - name: params
          in: query
          required: false
          style: deepObject
          explode: true
          schema:
            $ref: '#/components/schemas/UserQueryParams'
      responses:
        '200':
          description: Successfully retrieved paginated list of employees
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSummaryPageResponse'
        '400':
          description: Bad request - invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Company not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: Create new employee
      description: >-
        Creates a new employee record in the system. This endpoint does NOT
        automatically send an invitation. To send an invitation, use the send
        invitation endpoint after creating the employee. Only employees with the
        EMPLOYEE role can be created through this endpoint.
      operationId: createUser
      tags:
        - Users
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: companyId
          in: path
          description: The unique identifier for the company
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: Employee successfully created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '400':
          description: Bad request - invalid data or validation errors
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Company not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Conflict - employee with this email already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /companies/{companyId}/users/{userId}:
    get:
      summary: Retrieve complete employee details
      description: >-
        Returns comprehensive information for a specific employee, including
        employment status, salary information, allowances, verification status,
        salary history, and audit trail. This endpoint provides the full
        employee record.
      operationId: getUserById
      tags:
        - Users
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: companyId
          in: path
          description: The unique identifier for the company
          required: true
          schema:
            type: string
            format: uuid
        - name: userId
          in: path
          description: The unique identifier for the employee
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Successfully retrieved complete employee details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Employee or company not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      summary: Update employee information
      description: >-
        Updates employee details including status, contact information, role,
        salary, and employment dates. Used to synchronize employee data from the
        payroll system with Aslan.
      operationId: updateUserById
      tags:
        - Users
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: companyId
          in: path
          description: The unique identifier for the company
          required: true
          schema:
            type: string
            format: uuid
        - name: userId
          in: path
          description: The unique identifier for the employee
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: Employee successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '400':
          description: Bad request - invalid data or validation errors
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Employee or company not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /companies/{companyId}/users/invite:
    post:
      summary: Send invitations to employees
      description: >-
        Sends invitation emails to one or more employees to join Aslan. This
        endpoint can be called multiple times - if an employee has already been
        invited, it will resend the invitation. Can be used for employees in
        CREATED or INVITED status. Supports batch invitations for multiple
        employees.
      operationId: sendInvitations
      tags:
        - Users
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: companyId
          in: path
          description: The unique identifier for the company
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendInvitationsRequest'
      responses:
        '200':
          description: Invitation request accepted and will be processed asynchronously
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendInvitationsResponse'
        '400':
          description: Bad request - invalid request format or empty user list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Employee not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /deductions/reports/company/{reportId}:
    get:
      summary: Retrieve company deductions report summary
      description: >-
        Returns a summary of all employee deductions for a specific company
        report. This report includes deduction amounts for all employees within
        the specified date range, providing an overview for payroll processing.
      operationId: getCompanyDeductionsReport
      tags:
        - Reports
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: reportId
          in: path
          description: The unique identifier for the company report
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Successfully retrieved company deductions report summary
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyDeductionsReportResponse'
        '400':
          description: Bad request - invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Report not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /deductions/reports/employee/{reportId}:
    get:
      summary: Retrieve employee deduction details
      description: >-
        Returns detailed deduction information for a specific employee report.
        This includes the deduction amount, report period, and employee
        identifier for individual payroll processing.
      operationId: getEmployeeDeductionsReport
      tags:
        - Reports
      security:
        - partnerAdminAuth: []
      parameters:
        - $ref: '#/components/parameters/X-Aslan-Timestamp'
        - name: reportId
          in: path
          description: The unique identifier for the employee report
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Successfully retrieved employee deduction details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeDeductionReportResponse'
        '400':
          description: Bad request - invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Report not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    partnerAdminAuth:
      type: http
      scheme: bearer
      bearerFormat: token:signature
      description: >
        Partner admin authentication using Bearer token with HMAC signature.


        Format: `Bearer <token>:<signature>`


        The token and signature are separated by a colon. The signature is
        generated using HMAC-SHA256

        based on the request details including the timestamp provided in the
        X-Aslan-Timestamp header.
  parameters:
    X-Aslan-Timestamp:
      name: X-Aslan-Timestamp
      in: header
      required: true
      description: Unix epoch timestamp of the request in seconds.
      schema:
        type: integer
        format: int64
      example: 1730000000
  schemas:
    CompanyResponse:
      type: object
      required:
        - id
        - status
        - name
        - companyNumber
        - friendlyId
        - createdAt
        - createdBy
      properties:
        id:
          type: string
          format: uuid
          description: Unique system identifier for the company
          example: a3f2e1d0-5c4b-4a3e-9f8e-7d6c5b4a3e2f
        status:
          $ref: '#/components/schemas/CompanyStatus'
        name:
          type: string
          description: Registered legal name of the company
          example: TechFlow Solutions Ltd
        companyNumber:
          type: string
          description: >-
            Official company registration number (e.g., Companies House number
            in the UK)
          example: '09876543'
        address:
          $ref: '#/components/schemas/AddressPayload'
        friendlyId:
          type: string
          maxLength: 10
          description: >-
            Human-readable alphanumeric identifier for the company (max 10
            characters)
          example: A3F2E1D05C
        createdAt:
          type: string
          format: date-time
          description: Timestamp when the company was initially registered in the system
          example: '2024-03-15T10:30:00Z'
        createdBy:
          type: string
          format: uuid
          description: >-
            System identifier of the user or service that created this company
            record
          example: b2c3d4e5-6f7a-4b5c-8d9e-0f1a2b3c4d5e
        updatedAt:
          type: string
          format: date-time
          description: Timestamp of the most recent update to the company record
          example: '2024-09-20T14:22:15Z'
        updatedBy:
          type: string
          format: uuid
          description: >-
            System identifier of the user or service that last updated this
            company record
          example: c3d4e5f6-7a8b-5c6d-9e0f-1a2b3c4d5e6f
        deletedAt:
          type: string
          format: date-time
          description: Timestamp when the company was soft-deleted from the system
          example: '2024-12-01T09:00:00Z'
        deletedBy:
          type: string
          format: uuid
          description: >-
            System identifier of the user or service that deleted this company
            record
          example: d4e5f6a7-8b9c-6d7e-0f1a-2b3c4d5e6f7a
    CompanyPageResponse:
      type: object
      required:
        - content
        - page
        - size
        - totalElements
        - totalPages
      properties:
        content:
          type: array
          description: List of companies in the current page
          items:
            $ref: '#/components/schemas/CompanyResponse'
        page:
          type: integer
          description: Current page number (zero-based)
          example: 0
        size:
          type: integer
          description: Number of items per page
          example: 20
        totalElements:
          type: integer
          description: Total number of companies across all pages
          example: 156
        totalPages:
          type: integer
          description: Total number of pages
          example: 8
    AddressPayload:
      type: object
      required:
        - addressLine1
        - city
        - postCode
        - countryCode
      properties:
        addressLine1:
          type: string
          minLength: 1
          maxLength: 50
          description: Primary street address or building name
          example: Floor 3, 45 Commercial Road
        addressLine2:
          type: string
          minLength: 1
          maxLength: 50
          description: Secondary address information (e.g., building number, suite)
          example: Innovation Quarter
        addressLine3:
          type: string
          minLength: 1
          maxLength: 50
          description: Additional address information (e.g., district, neighborhood)
          example: Shoreditch
        postCode:
          type: string
          minLength: 1
          maxLength: 9
          description: Postal or ZIP code
          example: E1 6BH
        city:
          type: string
          minLength: 1
          maxLength: 50
          description: City or town name
          example: London
        countryCode:
          $ref: '#/components/schemas/CountryCode'
    CompanyStatus:
      type: string
      enum:
        - VERIFIED
        - DELETED
      description: |
        Current registration status of the company with Aslan:
        * `VERIFIED` - Company is verified and active on the platform
        * `DELETED` - Company has been removed from the platform (soft delete)
      example: VERIFIED
    CountryCode:
      type: string
      pattern: ^[A-Z]{2}$
      description: Two-letter ISO 3166-1 alpha-2 country code
      example: GB
    UpdateCompanyRequest:
      type: object
      anyOf:
        - required:
            - name
        - required:
            - companyNumber
        - required:
            - address
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
          description: Updated legal name of the company
          example: TechFlow Solutions Limited
        companyNumber:
          type: string
          minLength: 1
          maxLength: 20
          description: >-
            Updated official company registration number (e.g., Companies House
            number in the UK)
          example: '09876543'
        address:
          $ref: '#/components/schemas/AddressPayload'
    UserSummaryResponse:
      type: object
      required:
        - id
        - status
        - firstName
        - lastName
        - email
        - role
        - companyId
        - friendlyId
      properties:
        id:
          type: string
          format: uuid
          description: Unique system identifier for the employee
          example: f7e6d5c4-b3a2-4918-8e7d-6c5b4a3f2e1d
        status:
          $ref: '#/components/schemas/IndividualStatus'
        firstName:
          type: string
          description: Employee's legal first name
          example: Sarah
        lastName:
          type: string
          description: Employee's legal last name
          example: Johnson
        email:
          type: string
          format: email
          description: Primary work email address for the employee
          example: sarah.johnson@techflow.com
        phoneNumber:
          type: string
          description: Contact phone number in international format
          example: +44 7123 456789
        role:
          $ref: '#/components/schemas/UserRole'
        companyId:
          type: string
          format: uuid
          description: Unique identifier of the company this employee belongs to
          example: a3f2e1d0-5c4b-4a3e-9f8e-7d6c5b4a3e2f
        friendlyId:
          type: string
          maxLength: 10
          description: >-
            Human-readable alphanumeric identifier for the employee (max 10
            characters)
          example: F7E6D5C4B3
        externalPayrollId:
          type: string
          description: >-
            Employee identifier from the external payroll system for
            reconciliation purposes
          example: PAY-2024-00847
        startDate:
          type: string
          format: date
          description: Employee's start date with the company
          example: '2024-01-15'
    UserSummaryPageResponse:
      type: object
      required:
        - content
        - page
        - size
        - totalElements
        - totalPages
      properties:
        content:
          type: array
          description: List of employee summaries in the current page
          items:
            $ref: '#/components/schemas/UserSummaryResponse'
        page:
          type: integer
          description: Current page number (zero-based)
          example: 0
        size:
          type: integer
          description: Number of items per page
          example: 20
        totalElements:
          type: integer
          description: Total number of employees across all pages
          example: 543
        totalPages:
          type: integer
          description: Total number of pages
          example: 28
    UserResponse:
      type: object
      required:
        - id
        - status
        - firstName
        - lastName
        - email
        - role
        - companyId
        - friendlyId
        - emailVerified
        - phoneNumberVerified
        - salaried
        - onUnpaidLeave
        - createdAt
        - createdBy
      properties:
        id:
          type: string
          format: uuid
          description: Unique system identifier for the employee
          example: f7e6d5c4-b3a2-4918-8e7d-6c5b4a3f2e1d
        status:
          $ref: '#/components/schemas/IndividualStatus'
        firstName:
          type: string
          description: Employee's legal first name
          example: Sarah
        lastName:
          type: string
          description: Employee's legal last name
          example: Johnson
        email:
          type: string
          format: email
          description: Primary work email address for the employee
          example: sarah.johnson@techflow.com
        additionalEmail:
          type: string
          format: email
          description: >-
            Secondary or personal email address for account recovery and
            notifications
          example: sarah.j.personal@gmail.com
        role:
          $ref: '#/components/schemas/UserRole'
        companyId:
          type: string
          format: uuid
          description: Unique identifier of the company this employee belongs to
          example: a3f2e1d0-5c4b-4a3e-9f8e-7d6c5b4a3e2f
        phoneNumber:
          type: string
          description: Contact phone number in international format
          example: +44 7123 456789
        externalPayrollId:
          type: string
          description: >-
            Employee identifier from the external payroll system for
            reconciliation purposes
          example: PAY-2024-00847
        annualGrossSalary:
          type: number
          format: decimal
          description: >-
            Employee's annual gross salary in GBP, used for eligibility
            calculations
          example: 45000
        globalAllowancePercentage:
          type: integer
          description: Global allowance percentage for wage access eligibility
          example: 50
        odpAllowancePercentage:
          type: integer
          description: On-demand pay allowance percentage for wage access eligibility
          example: 25
        salaryHistory:
          type: array
          description: Historical record of salary changes for the employee
          items:
            $ref: '#/components/schemas/SalaryHistoryPayload'
        invitedAt:
          type: string
          format: date-time
          description: Date and time when the employee was invited to join Aslan
          example: '2024-04-09T09:00:00+00:00'
        joinDate:
          type: string
          format: date-time
          description: >-
            Date and time when the employee completed registration and joined
            Aslan
          example: '2024-04-10T11:45:00+00:00'
        startDate:
          type: string
          format: date
          description: Employee's employment start date with the company
          example: '2024-01-15'
        terminationDate:
          type: string
          format: date
          description: Employee's employment termination date, if applicable
          example: '2025-03-31'
        payCalendarId:
          type: string
          format: uuid
          description: Reference to the pay calendar schedule this employee follows
          example: c5d6e7f8-9a0b-4c5d-8e9f-0a1b2c3d4e5f
        friendlyId:
          type: string
          maxLength: 10
          description: >-
            Human-readable alphanumeric identifier for the employee (max 10
            characters)
          example: F7E6D5C4B3
        onUnpaidLeave:
          type: boolean
          description: Indicates whether the employee is currently on unpaid leave
          example: false
        emailVerified:
          type: boolean
          description: Indicates whether the employee's email address has been verified
          example: true
        phoneNumberVerified:
          type: boolean
          description: Indicates whether the employee's phone number has been verified
          example: true
        suspicious:
          type: boolean
          description: >-
            Flag indicating if the account has been marked for suspicious
            activity review
          example: false
        salaried:
          type: boolean
          description: Indicates whether the employee is on a salaried payment structure
          example: true
        createdAt:
          type: string
          format: date-time
          description: Timestamp when the employee was initially registered in the system
          example: '2024-04-08T10:30:00Z'
        createdBy:
          type: string
          format: uuid
          description: >-
            System identifier of the user or service that created this employee
            record
          example: b2c3d4e5-6f7a-4b5c-8d9e-0f1a2b3c4d5e
        updatedAt:
          type: string
          format: date-time
          description: Timestamp of the most recent update to the employee record
          example: '2024-10-05T11:30:45Z'
        updatedBy:
          type: string
          format: uuid
          description: >-
            System identifier of the user or service that last updated this
            employee record
          example: c3d4e5f6-7a8b-5c6d-9e0f-1a2b3c4d5e6f
        deletedAt:
          type: string
          format: date-time
          description: Timestamp when the employee was soft-deleted from the system
          example: '2024-12-01T16:20:00Z'
        deletedBy:
          type: string
          format: uuid
          description: >-
            System identifier of the user or service that deleted this employee
            record
          example: d4e5f6a7-8b9c-6d7e-0f1a-2b3c4d5e6f7a
    CreateUserRequest:
      type: object
      required:
        - firstName
        - lastName
        - email
        - salaried
      properties:
        firstName:
          type: string
          minLength: 1
          maxLength: 100
          description: Employee's legal first name
          example: Sarah
        lastName:
          type: string
          minLength: 1
          maxLength: 100
          description: Employee's legal last name
          example: Johnson
        email:
          type: string
          format: email
          maxLength: 255
          description: Primary work email address for the employee
          example: sarah.johnson@techflow.com
        additionalEmail:
          type: string
          format: email
          maxLength: 255
          description: >-
            Secondary or personal email address for account recovery and
            notifications
          example: sarah.j.personal@gmail.com
        phoneNumber:
          type: string
          pattern: ^\+?[1-9]\d{1,14}$
          description: Contact phone number in international E.164 format
          example: '+447123456789'
        externalPayrollId:
          type: string
          minLength: 1
          maxLength: 50
          description: >-
            Employee identifier from the external payroll system for
            reconciliation purposes
          example: PAY-2024-00847
        annualGrossSalary:
          type: number
          format: decimal
          minimum: 0.01
          description: Employee's annual gross salary in GBP (must be greater than 0)
          example: 45000
        startDate:
          type: string
          format: date
          description: Employee's employment start date with the company
          example: '2024-01-15'
        payCalendarId:
          type: string
          format: uuid
          description: Reference to the pay calendar schedule this employee follows
          example: c5d6e7f8-9a0b-4c5d-8e9f-0a1b2c3d4e5f
        salaried:
          type: boolean
          description: Indicates whether the employee is on a salaried payment structure
          default: true
          example: true
    SalaryHistoryPayload:
      type: object
      required:
        - annualGrossSalary
        - appliesDate
      properties:
        annualGrossSalary:
          type: number
          format: decimal
          description: Annual gross salary amount in GBP for this period
          example: 42000
        appliesDate:
          type: string
          format: date
          description: Date when this salary amount applies from
          example: '2024-01-01'
    UpdateUserRequest:
      type: object
      properties:
        firstName:
          type: string
          minLength: 1
          maxLength: 100
          description: Updated legal first name of the employee
          example: Sarah
        lastName:
          type: string
          minLength: 1
          maxLength: 100
          description: Updated legal last name of the employee
          example: Johnson-Smith
        email:
          type: string
          format: email
          maxLength: 255
          description: Updated primary work email address
          example: sarah.johnson-smith@techflow.com
        additionalEmail:
          type: string
          format: email
          maxLength: 255
          description: Updated secondary or personal email address
          example: sarah.js.new@gmail.com
        phoneNumber:
          type: string
          pattern: ^\+?[1-9]\d{1,14}$
          description: Updated contact phone number in international E.164 format
          example: '+447987654321'
        externalPayrollId:
          type: string
          minLength: 1
          maxLength: 50
          description: Updated employee identifier from the payroll system
          example: PAY-2024-00847
        annualGrossSalary:
          type: number
          format: decimal
          minimum: 0.01
          description: Updated annual gross salary in GBP (must be greater than 0)
          example: 48000
        startDate:
          type: string
          format: date
          description: Updated employment start date
          example: '2024-01-15'
        payCalendarId:
          type: string
          format: uuid
          description: Updated pay calendar reference
          example: c5d6e7f8-9a0b-4c5d-8e9f-0a1b2c3d4e5f
    SendInvitationsRequest:
      type: object
      required:
        - userIds
      properties:
        userIds:
          type: array
          description: List of employee UUIDs to send invitations to
          minItems: 1
          maxItems: 100
          items:
            type: string
            format: uuid
          example:
            - f7e6d5c4-b3a2-4918-8e7d-6c5b4a3f2e1d
            - a1b2c3d4-e5f6-7890-abcd-ef1234567890
    SendInvitationsResponse:
      type: object
      required:
        - message
        - requestedCount
      properties:
        message:
          type: string
          description: Confirmation message
          default: Invitation request accepted for processing
          example: Invitation request accepted for processing
        requestedCount:
          type: integer
          description: Number of users requested for invitation
          example: 2
    CompanyDeductionsReportResponse:
      type: object
      required:
        - companyId
        - reportId
        - employeeDeductionsReports
      properties:
        companyId:
          type: string
          format: uuid
          description: Unique identifier of the company
          example: a3f2e1d0-5c4b-4a3e-9f8e-7d6c5b4a3e2f
        reportId:
          type: string
          format: uuid
          description: Unique identifier for the report
          example: a1b2c3d4-e5f6-4a8b-9c0d-e1f2a3b4c5d6
        employeeDeductionsReports:
          type: array
          description: List of employee deductions within this report period
          items:
            $ref: '#/components/schemas/EmployeeDeductionReportResponse'
    EmployeeDeductionReportResponse:
      type: object
      required:
        - employeeId
        - reportId
        - from
        - to
        - deductionAmount
      properties:
        employeeId:
          type: string
          format: uuid
          description: Unique identifier of the employee
          example: f7e6d5c4-b3a2-4918-8e7d-6c5b4a3f2e1d
        reportId:
          type: string
          format: uuid
          description: Unique identifier for the report
          example: a1b2c3d4-e5f6-4a8b-9c0d-e1f2a3b4c5d6
        from:
          type: string
          format: date
          description: Start date of the deduction period
          example: '2024-10-01'
        to:
          type: string
          format: date
          description: End date of the deduction period
          example: '2024-10-31'
        deductionAmount:
          type: number
          format: decimal
          description: Total deduction amount in GBP to be processed through payroll
          example: 862.75
    CompanyQueryParams:
      type: object
      properties:
        page:
          type: integer
          minimum: 0
          default: 0
          description: Page number for pagination (zero-based)
          example: 0
        size:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
          description: Number of items per page
          example: 20
        sortBy:
          type: string
          description: Sort order field (e.g., name). Single sort parameters supported.
          example: name
        sort:
          type: string
          description: >-
            Sort order direction (asc or desc). Single sort parameters
            supported.
          example: asc
        status:
          $ref: '#/components/schemas/CompanyStatus'
        query:
          type: string
          description: >-
            Filter by company name, company number or friendlyId (partial match,
            case-insensitive)
          example: tech
    UserQueryParams:
      type: object
      properties:
        page:
          type: integer
          minimum: 0
          default: 0
          description: Page number for pagination (zero-based)
          example: 0
        size:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
          description: Number of items per page
          example: 20
        sortBy:
          type: string
          description: Sort order field (e.g., lastName). Single sort parameters supported.
          example: lastName
        sort:
          type: string
          description: >-
            Sort order direction (asc or desc). Single sort parameters
            supported.
          example: asc
        status:
          $ref: '#/components/schemas/IndividualStatus'
        role:
          $ref: '#/components/schemas/UserRole'
        search:
          type: string
          description: Search by employee name or email (partial match, case-insensitive)
          example: sarah
    IndividualStatus:
      type: string
      enum:
        - CREATED
        - INVITED
        - ACTIVE
        - DELETED
        - PAUSED
        - LEFT
      description: >
        Current status of the employee with Aslan:

        * `CREATED` - Employee record created but invitation not yet sent

        * `INVITED` - Invitation to join Aslan has been sent to the employee

        * `ACTIVE` - Employee is actively enrolled and can access earned wage
        access benefits

        * `DELETED` - Employee record has been removed from the system

        * `PAUSED` - Employee's access to benefits is temporarily suspended

        * `LEFT` - Employee has left the company and is no longer eligible
      example: ACTIVE
    UserRole:
      type: string
      enum:
        - EMPLOYEE
        - MANAGER
        - ADMIN
        - SUPER_ADMIN
      description: >
        Employee's role within the company and their permission level in Aslan:

        * `EMPLOYEE` - Standard employee with access to personal wage access
        features

        * `MANAGER` - Manager with additional reporting and team oversight
        capabilities

        * `ADMIN` - Company administrator with full company management
        capabilities

        * `SUPER_ADMIN` - Super administrator with extended system-level
        permissions
      example: EMPLOYEE
    ErrorResponse:
      type: object
      required:
        - timestamp
        - status
        - error
        - message
        - path
      properties:
        timestamp:
          type: string
          format: date-time
          description: Timestamp when the error occurred
          example: '2024-10-10T15:45:30Z'
        status:
          type: integer
          description: HTTP status code
          example: 400
        error:
          type: string
          description: HTTP status text
          example: Bad Request
        message:
          type: string
          description: Human-readable error message describing what went wrong
          example: 'Invalid date range: fromDate must be before toDate'
        path:
          type: string
          description: API endpoint path where the error occurred
          example: >-
            /api/v1/companies/a3f2e1d0-5c4b-4a3e-9f8e-7d6c5b4a3e2f/users/f7e6d5c4-b3a2-4918-8e7d-6c5b4a3f2e1d/spend-report
        errors:
          type: array
          description: Detailed validation errors (present for validation failures)
          items:
            $ref: '#/components/schemas/ValidationError'
        traceId:
          type: string
          format: uuid
          description: Unique identifier for tracing this error in logs
          example: a1b2c3d4-e5f6-4a8b-9c0d-e1f2a3b4c5d6
    ValidationError:
      type: object
      required:
        - field
        - message
      properties:
        field:
          type: string
          description: Name of the field that failed validation
          example: email
        message:
          type: string
          description: Validation error message for this field
          example: Email address is already in use
        rejectedValue:
          type: string
          description: The value that was rejected (may be omitted for sensitive data)
          example: sarah.johnson@techflow.com
