openapi: 3.1.0
info:
  title: APEX Ledger API
  version: 1.0.0
  summary: Health Vault, Medical Credit & FedNow -- unified billing gateway
  description: |
    OpenAPI contract for APEX Ledger v1 endpoints.
    Consolidates payments, insurance claims, payer interactions, Health Vault
    patient financials, Medical Credit Score, and FedNow instant settlement
    under a single billing gateway.
  contact:
    name: Parker Health Engineering
    url: https://parkerapex.com
servers:
  - url: https://api.parkerapex.com/ledger
    description: Production
  - url: https://sandbox.api.parkerapex.com/ledger
    description: Sandbox
tags:
  - name: Dashboard
    description: Ledger dashboard and summary endpoints
  - name: Health Vault
    description: Patient financial records, coverage, claims, and balances
  - name: Credit
    description: Medical Credit Score assessment
  - name: Transactions
    description: Unified transaction ledger
  - name: FedNow
    description: FedNow real-time payment rail integration
security:
  - OAuth2: []
paths:
  /:
    get:
      tags: [Dashboard]
      operationId: getLedgerDashboard
      summary: Ledger dashboard summary
      description: High-level billing and payments summary with monthly trends.
      security:
        - OAuth2:
            - ledger.read
      responses:
        '200':
          description: Ledger dashboard data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LedgerDashboardResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /vault:
    get:
      tags: [Health Vault]
      operationId: getHealthVault
      summary: Health Vault patient financial overview
      description: |
        Returns unified patient financial records including coverage summaries,
        outstanding claims, active payment plans, recent payments, and balances.
        Staff users see an aggregate view unless patient_id is specified.
        Patient users are automatically scoped to their own records.
      security:
        - OAuth2:
            - ledger.vault.read
      parameters:
        - name: patient_id
          in: query
          required: false
          schema:
            type: integer
          description: Patient database ID. Auto-resolved for patient role users.
        - name: page
          in: query
          required: false
          schema:
            type: integer
            default: 1
        - name: per_page
          in: query
          required: false
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        '200':
          description: Health Vault data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthVaultResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /credit-score:
    get:
      tags: [Credit]
      operationId: getMedicalCreditScore
      summary: Medical Credit Score
      description: |
        Returns an internal medical credit score for a patient based on payment
        history, failed payments, and overdue plan status. Does not affect
        external credit bureau reports.
      security:
        - OAuth2:
            - ledger.credit.read
      parameters:
        - name: patient_id
          in: query
          required: false
          schema:
            type: integer
          description: Patient database ID. Required for staff; auto-resolved for patients.
      responses:
        '200':
          description: Medical Credit Score
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreditScoreResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /transactions:
    get:
      tags: [Transactions]
      operationId: getTransactions
      summary: Unified transaction ledger
      description: |
        Paginated, filterable list of all payments, refunds, and disbursements
        across the platform with aggregate statistics.
      security:
        - OAuth2:
            - ledger.transactions.read
      parameters:
        - name: patient_id
          in: query
          required: false
          schema:
            type: integer
        - name: status
          in: query
          required: false
          schema:
            type: string
            enum: [completed, pending, failed, refunded]
        - name: payment_method
          in: query
          required: false
          schema:
            type: string
            enum: [card, bank_transfer, cash, check, insurance]
        - name: date_from
          in: query
          required: false
          schema:
            type: string
            format: date
        - name: date_to
          in: query
          required: false
          schema:
            type: string
            format: date
        - name: page
          in: query
          required: false
          schema:
            type: integer
            default: 1
        - name: per_page
          in: query
          required: false
          schema:
            type: integer
            default: 25
            maximum: 100
      responses:
        '200':
          description: Paginated transaction list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionsResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /fednow/status:
    get:
      tags: [FedNow]
      operationId: getFedNowStatus
      summary: FedNow integration status
      description: |
        Returns current FedNow connectivity, enrollment progress, capabilities,
        and compliance configuration. This is a placeholder endpoint that will
        be expanded as the FedNow integration matures.
      security:
        - OAuth2:
            - ledger.fednow.read
      responses:
        '200':
          description: FedNow integration status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FedNowStatusResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  securitySchemes:
    OAuth2:
      type: oauth2
      description: Plexus OAuth2 bearer token.
      flows:
        authorizationCode:
          authorizationUrl: https://nexus.parkerapex.com/oauth/authorize
          tokenUrl: https://nexus.parkerapex.com/oauth/token
          scopes:
            ledger.read: Read ledger dashboard
            ledger.vault.read: Read Health Vault patient financials
            ledger.credit.read: Read Medical Credit Score
            ledger.transactions.read: Read transaction ledger
            ledger.fednow.read: Read FedNow integration status
  responses:
    BadRequest:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Authentication required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: string
    LedgerDashboardResponse:
      type: object
      required: [module, version, brand, data]
      properties:
        module:
          type: string
          const: APEX Ledger
        version:
          type: string
        brand:
          type: string
        data:
          type: object
          required: [payments, claims, payment_plans, monthly_trend, fednow_status]
          properties:
            payments:
              type: object
              properties:
                total_collected:
                  type: number
                last_30_days:
                  type: number
                pending:
                  type: integer
                failed:
                  type: integer
            claims:
              type: object
              properties:
                open:
                  type: integer
                total_outstanding:
                  type: number
            payment_plans:
              type: object
              properties:
                active:
                  type: integer
                overdue:
                  type: integer
            monthly_trend:
              type: array
              items:
                type: object
                properties:
                  year:
                    type: integer
                  month:
                    type: integer
                  count:
                    type: integer
                  total:
                    type: number
            fednow_status:
              type: string
    HealthVaultResponse:
      type: object
      required: [module, data]
      properties:
        module:
          type: string
        data:
          type: object
          properties:
            coverages:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: integer
                  coverage_type:
                    type: string
                  policy_number:
                    type: string
                  network:
                    type: string
                  active:
                    type: boolean
                  deductible_amount:
                    type: number
                  deductible_met:
                    type: number
                  out_of_pocket_max:
                    type: number
                  out_of_pocket_met:
                    type: number
            outstanding_claims:
              type: array
              items:
                type: object
                properties:
                  claim_number:
                    type: string
                  service_date:
                    type: string
                    format: date
                  total_charges:
                    type: number
                  patient_responsibility:
                    type: number
                  status:
                    type: string
            payment_plans:
              type: array
              items:
                type: object
                properties:
                  plan_id:
                    type: string
                  total_amount:
                    type: number
                  amount_paid:
                    type: number
                  remaining:
                    type: number
                  monthly_payment:
                    type: number
                  next_payment_date:
                    type: string
                    format: date
                  overdue:
                    type: boolean
            recent_payments:
              type: array
              items:
                type: object
                properties:
                  payment_id:
                    type: string
                  amount:
                    type: number
                  status:
                    type: string
                  payment_method:
                    type: string
                  payment_type:
                    type: string
                  date:
                    type: string
                    format: date-time
            totals:
              type: object
              properties:
                total_paid:
                  type: number
                total_owed:
                  type: number
                balance:
                  type: number
            summary:
              type: object
              description: Aggregate view returned for staff when no patient_id is specified.
              properties:
                total_active_patients_with_balance:
                  type: integer
                total_outstanding:
                  type: number
                active_payment_plans:
                  type: integer
                overdue_plans:
                  type: integer
    CreditScoreResponse:
      type: object
      required: [module, data]
      properties:
        module:
          type: string
        data:
          type: object
          required: [patient_id, score, rating, factors, disclaimer]
          properties:
            patient_id:
              type: integer
            score:
              type: integer
              minimum: 300
              maximum: 850
            rating:
              type: string
              enum: [Excellent, Good, Fair, Poor]
            factors:
              type: array
              items:
                type: object
                properties:
                  label:
                    type: string
                  impact:
                    type: string
                    enum: [positive, negative]
            total_claims:
              type: integer
            completed_payments:
              type: integer
            failed_payments:
              type: integer
            active_payment_plans:
              type: integer
            overdue_plans:
              type: integer
            disclaimer:
              type: string
    TransactionsResponse:
      type: object
      required: [module, data]
      properties:
        module:
          type: string
        data:
          type: object
          required: [transactions, pagination, aggregate]
          properties:
            transactions:
              type: array
              items:
                type: object
                properties:
                  payment_id:
                    type: string
                  patient_id:
                    type: integer
                  amount:
                    type: number
                  currency:
                    type: string
                  status:
                    type: string
                  payment_method:
                    type: string
                  payment_type:
                    type: string
                  transaction_date:
                    type: string
                    format: date-time
                  receipt_number:
                    type: string
                  refund_amount:
                    type: number
                  net_amount:
                    type: number
            pagination:
              type: object
              properties:
                page:
                  type: integer
                per_page:
                  type: integer
                total:
                  type: integer
                pages:
                  type: integer
            aggregate:
              type: object
              properties:
                count:
                  type: integer
                total_amount:
                  type: number
    FedNowStatusResponse:
      type: object
      required: [module, data]
      properties:
        module:
          type: string
        data:
          type: object
          required: [service, status, connectivity, enrollment, capabilities]
          properties:
            service:
              type: string
              const: FedNow
            status:
              type: string
              enum: [active, pending_enrollment, disabled]
            connectivity:
              type: object
              properties:
                environment:
                  type: string
                  enum: [production, sandbox]
                endpoint:
                  type: string
                  format: uri
                last_heartbeat:
                  type: string
                  format: date-time
                  nullable: true
                latency_ms:
                  type: number
                  nullable: true
            enrollment:
              type: object
              properties:
                institution_name:
                  type: string
                routing_number:
                  type: string
                  nullable: true
                participant_type:
                  type: string
                  enum: [send_receive, receive_only, send_only]
                onboarding_stage:
                  type: string
                estimated_go_live:
                  type: string
            capabilities:
              type: object
              properties:
                instant_payment_receive:
                  type: boolean
                instant_payment_send:
                  type: boolean
                request_for_payment:
                  type: boolean
                settlement_reporting:
                  type: boolean
            supported_use_cases:
              type: array
              items:
                type: string
            compliance:
              type: object
              properties:
                ofac_screening:
                  type: boolean
                fraud_detection:
                  type: boolean
                transaction_limits:
                  type: object
                  properties:
                    single_max_usd:
                      type: integer
                    daily_max_usd:
                      type: integer
