openapi: 3.1.1
info:
  title: AffordX API
  description: >
    API documentation for the AffordX Backend Service, covering Authentication
    and Subscriber endpoints.


    **Base URLs:**

    - Demo: `https://api.broker.v1.demo.affordx.nz`

    - Production: `https://api.broker.affordx.nz`


    **Download the OpenAPI document:**
    [JSON](https://api-docs.affordx.nz/openapi.json) ·
    [YAML](https://api-docs.affordx.nz/openapi.yaml)
  version: 1.0.0
servers:
  - url: https://api.broker.v1.demo.affordx.nz
    description: Demo
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: "Bearer token for authentication. Example: 'Bearer {token}'"
  schemas:
    LoginRequest:
      type: object
      required:
        - username
        - password
      properties:
        username:
          type: string
          format: email
          description: User's email address.
          examples:
            - user@example.com
        password:
          type: string
          format: password
          description: User's password.
          examples:
            - string-password
    JwtResponse:
      type: object
      properties:
        token:
          type: string
          description: JWT access token.
        refreshToken:
          type: string
          description: Token to refresh the access token.
        id:
          type: string
          description: User's unique identifier.
        username:
          type: string
          description: User's username (email).
        email:
          type: string
          format: email
          description: User's email address.
        roles:
          type: array
          items:
            type: string
          description: List of roles assigned to the user.
          examples:
            - - ROLE_BROKER
    ApplicationResponse:
      type: object
      properties:
        applicationId:
          type: string
          description: Unique identifier for the application.
        clients:
          type: array
          items:
            type: object
            properties:
              clientId:
                type: string
              clientName:
                type: string
        status:
          type: string
          description: Current status of the application.
        applicationDate:
          type: string
          format: date-time
          description: The date the application was created.
        accounts:
          type: integer
          description: Total number of accounts associated with the application.
    ClientResponse:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the client.
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
          format: email
    ApplicationFilesResponse:
      type: object
      properties:
        documents:
          type: array
          items:
            type: object
            properties:
              documentType:
                type: string
              documentUrl:
                type: string
                format: uri
        pdfStatements:
          type: array
          items:
            type: object
            properties:
              period:
                type: string
              uri:
                type: string
                format: uri
    DocumentUploadResponse:
      type: object
      properties:
        applicationId:
          type: string
          description: The application the documents were uploaded to.
        documentCategory:
          type: string
          description: The category the documents were filed under.
          enum:
            - BANK_STATEMENTS
            - PAYSLIPS
            - TAX_SUMMARY
            - OTHER_DOCUMENTS
        totalUploaded:
          type: integer
          description: Number of files successfully uploaded.
        statementProcessingTriggered:
          type: boolean
          description: True when uploaded bank statements were submitted for automated
            statement processing. Processing is asynchronous; poll GET
            /v1/subscriber/applications/{applicationId} until its transaction
            summary populates.
        documents:
          type: array
          items:
            type: object
            properties:
              fileId:
                type: string
              fileName:
                type: string
              fileType:
                type: string
              fileSize:
                type: integer
                format: int64
              status:
                type: string
              documentCategory:
                type: string
              downloadUrl:
                type: string
                format: uri
              processingReference:
                type: string
                description: Reference assigned when a bank statement is submitted for automated
                  processing.
        errors:
          type: array
          items:
            type: string
    ClientApplicationRequest:
      type: object
      required:
        - clients
      properties:
        clients:
          type: array
          description: List of clients associated with the application.
          items:
            type: object
            properties:
              clientId:
                type: string
              isMainApplicant:
                type: boolean
        isJointApplication:
          type: boolean
        sentByEmail:
          type: boolean
    PlatformClientCreateRequest:
      type: object
      required:
        - firstName
        - lastName
        - email
        - dateOfBirth
        - externalReferenceId
      properties:
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
          format: email
        dateOfBirth:
          type: string
          format: date
        externalReferenceId:
          type: string
    BankCalculatorV2Request:
      type: object
      description: Inputs for the bank serviceability calculation. All monetary values
        are strings.
      properties:
        applicants:
          type: string
          description: Number of applicants. Must be 1 or 2.
          enum:
            - "1"
            - "2"
          examples:
            - "2"
        dependants:
          type: string
          description: Number of dependants. Must be 0-5.
          enum:
            - "0"
            - "1"
            - "2"
            - "3"
            - "4"
            - "5"
          examples:
            - "1"
        app1AnnualGrossIncome:
          type: string
          description: Applicant 1 annual gross income.
        app2AnnualGrossIncome:
          type: string
          description: Applicant 2 annual gross income.
        rentalIncomeGrossWeekly:
          type: string
          description: Gross weekly rental income.
        boarderIncomeGrossWeekly:
          type: string
          description: Gross weekly boarder income.
        otherIncomeNetWeekly:
          type: string
          description: Net weekly other income.
        app1StudentLoan:
          type: string
          description: Whether applicant 1 has a student loan. Must be Y or N.
          enum:
            - Y
            - N
        app2StudentLoan:
          type: string
          description: Whether applicant 2 has a student loan. Must be Y or N.
          enum:
            - Y
            - N
        existingMortgages:
          type: string
          description: Existing mortgage balances/repayments.
        overdraftLimit:
          type: string
          description: Overdraft limit.
        creditCardLimit:
          type: string
          description: Total credit card limit.
        personalLoanMonthlyRepayment:
          type: string
          description: Monthly personal loan repayment.
        hirePurchaseOtherLoanMonthlyPayment:
          type: string
          description: Monthly hire purchase / other loan payment.
        useBankBenchmark:
          type: string
          description: Whether to use the bank benchmark for expenses. Must be Y or N.
          enum:
            - Y
            - N
          default: Y
        rentBoard:
          type: string
          description: Rent or board expense.
        bodyCorpGroundRent:
          type: string
          description: Body corporate / ground rent expense.
        childcareSchooling:
          type: string
          description: Childcare and schooling expense.
        childSupport:
          type: string
          description: Child support expense.
        homeContentCarInsurance:
          type: string
          description: Home, contents and car insurance expense.
        lifeHealthInsurance:
          type: string
          description: Life and health insurance expense.
        ratesWater:
          type: string
          description: Rates and water expense.
        kiwisaverContribution:
          type: string
          description: KiwiSaver contribution.
        otherExpenses:
          type: string
          description: Other expenses.
        groceriesFood:
          type: string
          description: Groceries and food expense.
        utilities:
          type: string
          description: Utilities expense.
        phoneInternet:
          type: string
          description: Phone and internet expense.
        transportVehicle:
          type: string
          description: Transport and vehicle expense.
        clothingPersonalCare:
          type: string
          description: Clothing and personal care expense.
        proposedLoanTerm:
          type: string
          description: Proposed loan term in years.
          default: "30"
    BankResult:
      type: object
      description: Serviceability result for a single bank.
      properties:
        maxLending:
          description: Maximum lending amount calculated for the bank.
        maxMonthlySurplus:
          description: Maximum monthly surplus calculated for the bank.
    BankCalculationResults:
      type: object
      description: Serviceability results across supported banks.
      properties:
        anz:
          $ref: "#/components/schemas/BankResult"
        asb:
          $ref: "#/components/schemas/BankResult"
        bnz:
          $ref: "#/components/schemas/BankResult"
        kiwibank:
          $ref: "#/components/schemas/BankResult"
        westpac:
          $ref: "#/components/schemas/BankResult"
    ErrorResponse:
      type: object
      properties:
        timestamp:
          type: string
          format: date-time
        status:
          type: integer
        error:
          type: string
        message:
          type: string
        path:
          type: string
paths:
  /v1/auth/login:
    post:
      tags:
        - Authentication
      summary: Authenticate user
      description: Logs in a user and returns a JWT token upon successful
        authentication. By default login is validated via a reCAPTCHA token
        supplied in the request body. Server-to-server callers can instead send
        the `X-App-Name` header (matching the configured application name) to
        bypass the reCAPTCHA check.
      security: []
      parameters:
        - name: X-App-Name
          in: header
          required: true
          description: Application name for server-to-server callers. When it matches the
            configured application name, the reCAPTCHA check is skipped and no
            reCAPTCHA token is required. (Optional on the server, but pre-filled
            here so API clients send it automatically.)
          schema:
            type: string
            default: AffordX
            examples:
              - AffordX
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginRequest"
      responses:
        "200":
          description: Authentication successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JwtResponse"
        "400":
          description: Bad Request - Invalid input or failed reCAPTCHA
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized - Invalid credentials
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /v1/subscriber/applications:
    get:
      tags:
        - Subscription API
      summary: Get all applications
      description: Retrieves all applications for the current authenticated broker.
        Requires a JWT bearer token.
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ApplicationResponse"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
    post:
      tags:
        - Subscription API
      summary: Add new application
      description: Creates a new application for the authenticated broker. Requires a
        JWT bearer token.
      security:
        - bearerAuth: []
      parameters:
        - name: x-crm-platform
          in: header
          required: true
          description: The external CRM platform name.
          schema:
            type: string
            examples:
              - Monday
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ClientApplicationRequest"
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApplicationResponse"
        "400":
          description: Bad Request
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
  /v1/subscriber/applications/{applicationId}:
    get:
      tags:
        - Subscription API
      summary: Get application by ID
      description: Retrieves a specific application by its ID for the authenticated
        broker. Requires a JWT bearer token.
      security:
        - bearerAuth: []
      parameters:
        - name: applicationId
          in: path
          required: true
          description: ID of the application to retrieve.
          schema:
            type: string
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApplicationResponse"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Not Found
  /v1/subscriber/applications/{applicationId}/loan-accounts:
    get:
      tags:
        - Subscription API
      summary: Get all loan accounts for an application
      description: Retrieves all loan accounts for a specific application. Requires a
        JWT bearer token.
      security:
        - bearerAuth: []
      parameters:
        - name: applicationId
          in: path
          required: true
          description: ID of the application.
          schema:
            type: string
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Not Found
  /v1/subscriber/applications/{applicationId}/documents:
    get:
      tags:
        - Subscription API
      summary: Get application documents and PDF statements
      description: Retrieves all submitted documents and PDF statements for a specific
        application. Requires a JWT bearer token.
      security:
        - bearerAuth: []
      parameters:
        - name: applicationId
          in: path
          required: true
          description: ID of the application.
          schema:
            type: string
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApplicationFilesResponse"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Not Found
    post:
      tags:
        - Subscription API
      summary: Upload documents to an application
      description: Manually uploads one or more documents (e.g. bank statements) to an
        application. Uploading with documentCategory=BANK_STATEMENTS submits the
        files for automated statement processing and triggers asynchronous
        report generation. There is no webhook — poll GET
        /v1/subscriber/applications/{applicationId} until its transaction
        summary populates. Other categories are stored only. Requires a JWT
        bearer token.
      security:
        - bearerAuth: []
      parameters:
        - name: x-crm-platform
          in: header
          required: true
          description: The external CRM platform name.
          schema:
            type: string
            examples:
              - Monday
        - name: applicationId
          in: path
          required: true
          description: ID of the application to upload documents to.
          schema:
            type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - files
                - documentCategory
              properties:
                files:
                  type: array
                  description: One or more files to upload.
                  items:
                    type: string
                    contentMediaType: application/octet-stream
                documentCategory:
                  type: string
                  description: Document category. BANK_STATEMENTS triggers automated statement
                    processing.
                  enum:
                    - BANK_STATEMENTS
                    - PAYSLIPS
                    - TAX_SUMMARY
                    - OTHER_DOCUMENTS
                description:
                  type: string
                  description: Optional free-text description.
      responses:
        "200":
          description: Documents uploaded successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DocumentUploadResponse"
        "400":
          description: Bad Request - no files, or none uploaded successfully
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Not Found
  /v1/subscriber/clients:
    get:
      tags:
        - Subscription API
      summary: Get a list of clients for the login user
      description: Retrieves a list of client for the login user. Requires a JWT
        bearer token.
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ClientResponse"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
    post:
      tags:
        - Subscription API
      summary: Create a new client
      description: Creates a new client in the external CRM platform for the
        authenticated broker. Requires a JWT bearer token.
      security:
        - bearerAuth: []
      parameters:
        - name: x-crm-platform
          in: header
          required: true
          description: The external CRM platform name.
          schema:
            type: string
            examples:
              - Monday
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PlatformClientCreateRequest"
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ClientResponse"
        "400":
          description: Bad Request
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
  /v1/subscriber/clients/{clientId}:
    get:
      tags:
        - Subscription API
      summary: Get Client Details
      description: Retrieves detailed information about a specific client by their ID.
        Requires a JWT bearer token.
      security:
        - bearerAuth: []
      parameters:
        - name: clientId
          in: path
          required: true
          description: ID of the client to retrieve.
          schema:
            type: string
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ClientResponse"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Not Found
  /v2/bank-calculator/calculate:
    post:
      tags:
        - Bank Calculator
      summary: Calculate bank serviceability
      description: Runs the bank serviceability calculation for the supplied applicant
        income and expense details, returning the maximum lending and monthly
        surplus for each supported bank. Requires a JWT bearer token with at
        least the BROKER role.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BankCalculatorV2Request"
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BankCalculationResults"
        "400":
          description: Bad Request - Invalid input or Master Sheet ID not configured
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "500":
          description: Internal Server Error - Calculation failed
x-ext-urls: {}
