openapi: 3.1.0
info:
  title: Billie API
  version: 0.1.0
  description: "Public Billie API contract for customer, merchant, biller, developer, and operations workflows."
servers:
  - 
    url: https://billie-api.kenac.co.zw/api/v1
    description: UAT public API
  - 
    url: http://localhost:8080/api/v1
    description: Local development API
paths:
  /auth/register:
    post:
      summary: Register a phone number and issue an OTP
      operationId: register
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegisterRequest"
      responses:
        200:
          description: OTP sent
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageResponse"
        429:
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /auth/verify:
    post:
      summary: Verify an OTP and issue tokens
      operationId: verifyOtp
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VerifyRequest"
      responses:
        200:
          description: Tokens and user profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AuthResponse"
        401:
          description: Invalid OTP
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        410:
          description: OTP expired
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /auth/pin:
    post:
      summary: Set a six digit customer PIN
      operationId: setPin
      tags:
        - Authentication
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PinRequest"
      responses:
        204:
          description: PIN set
  /auth/login:
    post:
      summary: Authenticate with phone number and PIN
      operationId: login
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginRequest"
      responses:
        200:
          description: Tokens and user profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AuthResponse"
        401:
          description: Invalid credentials
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        423:
          description: Account locked
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /auth/refresh:
    post:
      summary: Rotate access and refresh tokens
      operationId: refresh
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RefreshRequest"
      responses:
        200:
          description: Rotated tokens
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
  /auth/logout:
    post:
      summary: Revoke the active device session
      operationId: logout
      tags:
        - Authentication
      security:
        - 
          bearerAuth:

      responses:
        204:
          description: Logged out
  /auth/sessions:
    get:
      summary: List active customer device sessions
      operationId: listSessions
      tags:
        - Authentication
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Active sessions
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SessionResponse"
  "/auth/sessions/{sessionId}":
    delete:
      summary: Revoke a customer device session
      operationId: deleteSession
      tags:
        - Authentication
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: sessionId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Session revoked
  /kyc/tier1:
    post:
      summary: Submit Tier 1 KYC details
      operationId: submitTier1
      tags:
        - KYC
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/KycTier1Request"
      responses:
        200:
          description: KYC tier updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/KycTierResponse"
  /billers:
    get:
      summary: Search biller directory
      operationId: searchBillers
      tags:
        - Billers
      parameters:
        - 
          name: q
          in: query
          schema:
            type: string
        - 
          name: categorySlug
          in: query
          schema:
            type: string
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
        - 
          name: sort
          in: query
          schema:
            type: string
            enum:
              - popular
              - name
            default: popular
      responses:
        200:
          description: Matching billers
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillerSearchResponse"
  /billers/categories:
    get:
      summary: List biller categories
      operationId: listBillerCategories
      tags:
        - Billers
      responses:
        200:
          description: Active categories
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BillerCategoryResponse"
  "/billers/{billerIdOrSlug}":
    get:
      summary: Get biller detail
      operationId: getBiller
      tags:
        - Billers
      parameters:
        - 
          name: billerIdOrSlug
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Biller detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillerDetail"
  "/billers/{billerIdOrSlug}/account-validation":
    post:
      summary: Validate a direct biller account reference
      operationId: validateBillerAccount
      tags:
        - Billers
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: billerIdOrSlug
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BillerAccountValidationRequest"
      responses:
        200:
          description: Direct biller validation result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillerAccountValidationResponse"
  /saved-accounts:
    get:
      summary: List saved biller accounts
      operationId: listSavedAccounts
      tags:
        - Saved Accounts
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Saved accounts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SavedBillerAccountResponse"
    post:
      summary: Create saved biller account
      operationId: createSavedAccount
      tags:
        - Saved Accounts
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SavedAccountRequest"
      responses:
        204:
          description: Saved account created
  "/saved-accounts/{id}":
    patch:
      summary: Rename saved biller account
      operationId: updateSavedAccount
      tags:
        - Saved Accounts
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SavedAccountUpdateRequest"
      responses:
        204:
          description: Saved account updated
    delete:
      summary: Delete saved biller account
      operationId: deleteSavedAccount
      tags:
        - Saved Accounts
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Saved account deleted
  /payments:
    post:
      summary: Create a one-time payment
      operationId: createPayment
      tags:
        - Payments
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentRequest"
      responses:
        200:
          description: Payment response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentResponse"
        409:
          description: Duplicate payment or missing idempotency key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        422:
          description: Limit exceeded or biller unavailable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
    get:
      summary: List payment history
      operationId: listPayments
      tags:
        - Payments
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        200:
          description: Payment history
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionPage"
  /internal/customers/resolve:
    post:
      summary: Resolve uploaded bill identifiers to a verified Billie customer
      operationId: resolveInternalCustomer
      tags:
        - Internal BIP
      servers:
        - 
          url: https://billie-api.kenac.co.zw
          description: UAT internal API root
        - 
          url: http://localhost:8080
          description: Local internal API root
      security:
        - 
          internalApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InternalCustomerResolutionRequest"
      responses:
        200:
          description: High-confidence customer match or an explicit unmatched result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalCustomerResolutionResponse"
        401:
          description: Missing or invalid internal API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /bills:
    get:
      summary: "List the customer's consolidated pushed-bill inbox"
      operationId: listCustomerBills
      tags:
        - Bills
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: status
          in: query
          required: false
          schema:
            type: string
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        200:
          description: Customer bill inbox
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CustomerBillPage"
  /bills/claims:
    post:
      summary: Claim a pushed bill by biller and account reference
      operationId: claimCustomerBill
      tags:
        - Bills
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BillClaimRequest"
      responses:
        200:
          description: Claimed bill
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CustomerBillDetail"
        400:
          description: Invalid claim details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        404:
          description: Claimable bill not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/bills/{billId}":
    get:
      summary: Get one pushed bill detail and mark it viewed
      operationId: getCustomerBill
      tags:
        - Bills
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: billId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Customer bill detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CustomerBillDetail"
        404:
          description: Bill not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/bills/{billId}/pay":
    post:
      summary: Pay a pushed bill from the consolidated inbox
      operationId: payCustomerBill
      tags:
        - Bills
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
        - 
          name: billId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BillPayRequest"
      responses:
        200:
          description: Payment response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentResponse"
        409:
          description: "Bill already paid, claim required, or bill unresolvable"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/payments/{id}":
    get:
      summary: Get payment detail
      operationId: getPayment
      tags:
        - Payments
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Payment detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionDetail"
  "/payments/{id}/receipt":
    post:
      summary: Get a receipt URL
      operationId: getReceiptUrl
      tags:
        - Payments
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Receipt URL
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReceiptUrlResponse"
  "/payments/{id}/reorder":
    post:
      summary: Create a payment reorder draft
      operationId: reorderPayment
      tags:
        - Payments
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Payment draft
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentDraft"
  /schedules:
    post:
      summary: Create a scheduled payment
      operationId: createSchedule
      tags:
        - Schedules
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ScheduleRequest"
      responses:
        201:
          description: Schedule created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScheduleResponse"
        422:
          description: Consent missing or stale
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
    get:
      summary: List schedules
      operationId: listSchedules
      tags:
        - Schedules
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Customer schedules
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ScheduleResponse"
  "/schedules/{id}":
    get:
      summary: Get schedule detail
      operationId: getSchedule
      tags:
        - Schedules
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Schedule detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScheduleResponse"
    patch:
      summary: Update a schedule
      operationId: updateSchedule
      tags:
        - Schedules
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ScheduleUpdateRequest"
      responses:
        200:
          description: Updated schedule
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScheduleResponse"
    delete:
      summary: Cancel a schedule
      operationId: deleteSchedule
      tags:
        - Schedules
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Schedule cancelled
  "/schedules/{id}/runs":
    get:
      summary: List scheduled payment run history
      operationId: listScheduleRuns
      tags:
        - Schedules
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Schedule run history
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ScheduleRunResponse"
  /notifications:
    get:
      summary: List notifications
      operationId: listNotifications
      tags:
        - Notifications
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: isRead
          in: query
          schema:
            type: boolean
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        200:
          description: Notification deliveries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotificationPage"
  "/notifications/{id}/read":
    post:
      summary: Mark notification as read
      operationId: markNotificationRead
      tags:
        - Notifications
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Notification marked read
  /notifications/read-all:
    post:
      summary: Mark all notifications as read
      operationId: markAllNotificationsRead
      tags:
        - Notifications
      security:
        - 
          bearerAuth:

      responses:
        204:
          description: Notifications marked read
  /notifications/preferences:
    patch:
      summary: Update notification preferences
      operationId: updateNotificationPreferences
      tags:
        - Notifications
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/NotificationPreferenceRequest"
      responses:
        204:
          description: Preferences updated
  /profile:
    get:
      summary: Get authenticated user profile
      operationId: getProfile
      tags:
        - Profile
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Authenticated profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProfileResponse"
    patch:
      summary: Update authenticated user profile
      operationId: updateProfile
      tags:
        - Profile
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProfileUpdateRequest"
      responses:
        200:
          description: Updated profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProfileResponse"
  /disputes:
    post:
      summary: Raise a payment dispute
      operationId: createDispute
      tags:
        - Disputes
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DisputeRequest"
      responses:
        201:
          description: Dispute created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DisputeSummary"
    get:
      summary: List customer disputes
      operationId: listDisputes
      tags:
        - Disputes
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        200:
          description: Customer disputes
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DisputePage"
  "/disputes/{id}":
    get:
      summary: Get dispute detail
      operationId: getDispute
      tags:
        - Disputes
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Dispute detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DisputeDetail"
    patch:
      summary: Update dispute assignment or status
      operationId: updateDispute
      tags:
        - Disputes
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DisputePatchRequest"
      responses:
        200:
          description: Updated dispute
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DisputeSummary"
  "/disputes/{id}/comments":
    post:
      summary: Add a dispute comment
      operationId: addDisputeComment
      tags:
        - Disputes
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DisputeCommentRequest"
      responses:
        201:
          description: Comment added
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DisputeCommentResponse"
  /households:
    post:
      summary: Create a customer household
      operationId: createHousehold
      tags:
        - Households
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HouseholdRequest"
      responses:
        201:
          description: Household created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HouseholdResponse"
    get:
      summary: List customer households
      operationId: listHouseholds
      tags:
        - Households
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Customer households
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/HouseholdResponse"
  "/households/{id}/members":
    get:
      summary: List household members
      operationId: listHouseholdMembers
      tags:
        - Households
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Household members
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/HouseholdMemberResponse"
    post:
      summary: Add a household member
      operationId: addHouseholdMember
      tags:
        - Households
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HouseholdMemberRequest"
      responses:
        201:
          description: Household member added
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HouseholdMemberResponse"
  "/households/{id}/members/{userId}":
    patch:
      summary: Update a household member role
      operationId: updateHouseholdMember
      tags:
        - Households
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - 
          name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HouseholdRoleRequest"
      responses:
        204:
          description: Household member updated
    delete:
      summary: Remove a household member
      operationId: deleteHouseholdMember
      tags:
        - Households
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - 
          name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Household member removed
  /agent/cash-position:
    get:
      summary: Get agent cash position
      operationId: getAgentCashPosition
      tags:
        - Agent
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Agent cash position
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CashPositionResponse"
  /agent/payments:
    post:
      summary: Create an assisted payment
      operationId: createAgentPayment
      tags:
        - Agent
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AgentPaymentRequest"
      responses:
        200:
          description: Assisted payment response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentResponse"
  /agent/transactions:
    get:
      summary: List assisted payments
      operationId: listAgentTransactions
      tags:
        - Agent
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        200:
          description: Assisted payment history
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionPage"
  /admin/billers:
    get:
      summary: List admin biller records
      operationId: listAdminBillers
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Admin billers
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
    post:
      summary: Create an admin biller record
      operationId: createAdminBiller
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdminBillerRequest"
      responses:
        201:
          description: Admin biller created
  "/admin/billers/{id}":
    patch:
      summary: Update an admin biller record
      operationId: updateAdminBiller
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdminBillerRequest"
      responses:
        204:
          description: Admin biller updated
    delete:
      summary: Soft delete an admin biller record
      operationId: deleteAdminBiller
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Admin biller deactivated
  /admin/posting-attempts:
    get:
      summary: List direct biller posting attempts
      operationId: listPostingAttempts
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: status
          in: query
          schema:
            type: string
            enum:
              - PENDING
              - RETRYING
              - CONFIRMED
              - FAILED
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        200:
          description: Posting attempts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BillerPostingAttemptResponse"
  "/admin/posting-attempts/{id}/retry":
    post:
      summary: Retry a failed direct biller posting attempt
      operationId: retryPostingAttempt
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Posting attempt after retry
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillerPostingAttemptResponse"
  /admin/outbox-events:
    get:
      summary: List persisted event outbox rows
      operationId: listOutboxEvents
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: status
          in: query
          schema:
            type: string
            enum:
              - PENDING
              - PUBLISHED
              - FAILED
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 20
      responses:
        200:
          description: Persisted event outbox rows
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutboxEventPage"
  "/admin/outbox-events/{id}/retry":
    post:
      summary: Requeue a failed event outbox row
      operationId: retryOutboxEvent
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Requeued event outbox row
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutboxEventResponse"
  /admin/disputes:
    get:
      summary: List admin dispute queue
      operationId: listAdminDisputes
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Admin disputes
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DisputePage"
  /admin/biller-categories:
    get:
      summary: List biller categories for administration
      operationId: listAdminBillerCategories
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Admin categories
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
    post:
      summary: Create a biller category
      operationId: createAdminBillerCategory
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdminCategoryRequest"
      responses:
        201:
          description: Category created
  "/admin/biller-categories/{id}":
    patch:
      summary: Update a biller category
      operationId: updateAdminBillerCategory
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdminCategoryRequest"
      responses:
        204:
          description: Category updated
  /admin/payment-rails:
    post:
      summary: Create a payment rail
      operationId: createAdminPaymentRail
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdminRailRequest"
      responses:
        201:
          description: Payment rail created
  "/admin/payment-rails/{id}":
    patch:
      summary: Update a payment rail
      operationId: updateAdminPaymentRail
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdminRailRequest"
      responses:
        204:
          description: Payment rail updated
  /admin/users:
    get:
      summary: List users for administration
      operationId: listAdminUsers
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Admin users
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AdminUserPage"
  "/admin/users/{id}/role":
    patch:
      summary: Change a user role
      operationId: updateAdminUserRole
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdminUserRoleRequest"
      responses:
        204:
          description: User role changed
  "/admin/users/{id}/deactivate":
    post:
      summary: Deactivate a user
      operationId: deactivateAdminUser
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: User deactivated
  /admin/metrics:
    get:
      summary: Get admin dashboard metrics
      operationId: getAdminMetrics
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Admin metrics
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/AdminMetric"
  /admin/funnel-metrics:
    get:
      summary: Get payment funnel metrics
      operationId: getFunnelMetrics
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Funnel metrics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FunnelMetricsResponse"
  /admin/reconciliation:
    get:
      summary: Get reconciliation totals
      operationId: getReconciliation
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Reconciliation result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReconciliationResponse"
  /admin/reconciliation/export:
    get:
      summary: Export reconciliation CSV
      operationId: exportReconciliation
      tags:
        - Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: CSV export
          content:
            text/plain:
              schema:
                type: string
  /compliance/aml-queue:
    get:
      summary: List AML review queue
      operationId: listAmlQueue
      tags:
        - Compliance
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: AML flags
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/AmlFlagResponse"
  "/compliance/aml-queue/{txnId}/review":
    patch:
      summary: Review an AML flag
      operationId: reviewAmlFlag
      tags:
        - Compliance
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: txnId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AmlReviewRequest"
      responses:
        204:
          description: AML flag reviewed
  /merchants/register:
    post:
      summary: Register a merchant for KYB review
      operationId: registerMerchant
      tags:
        - Merchants
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantRegisterRequest"
      responses:
        200:
          description: Merchant created with pending KYB status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantResponse"
  "/merchants/{merchantId}/kyb-documents":
    post:
      summary: Upload merchant KYB evidence for an onboarding application
      operationId: uploadMerchantKybDocument
      tags:
        - Merchants
      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
        - 
          name: token
          in: query
          required: true
          schema:
            type: string
            minLength: 1
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - documentType
                - registrationNo
                - file
              properties:
                documentType:
                  type: string
                  enum:
                    - CERTIFICATE_OF_INCORPORATION
                    - TAX_CLEARANCE
                    - DIRECTORS_ID
                    - PROOF_OF_ADDRESS
                    - BANK_ACCOUNT_LETTER
                registrationNo:
                  type: string
                file:
                  type: string
                  format: binary
      responses:
        201:
          description: Merchant KYB document stored
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantKybDocumentResponse"
  "/merchants/{merchantId}/status":
    get:
      summary: Read merchant onboarding application status
      operationId: getMerchantApplicationStatus
      tags:
        - Merchants
      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
        - 
          name: token
          in: query
          required: true
          schema:
            type: string
            minLength: 1
      responses:
        200:
          description: Merchant application status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantResponse"
  /admin/merchants:
    get:
      summary: List merchant KYB records
      operationId: listMerchants
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant records
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantResponse"
  "/admin/merchants/{merchantId}/kyb":
    patch:
      summary: Update merchant KYB status
      operationId: updateMerchantKyb
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantKybRequest"
      responses:
        200:
          description: Merchant updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantResponse"
  "/admin/merchants/{merchantId}/api-keys":
    post:
      summary: Issue a merchant API key
      operationId: createMerchantApiKey
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantApiKeyRequest"
      responses:
        200:
          description: Raw API key returned once
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantApiKeyResponse"
  "/admin/merchants/{merchantId}/pricing":
    patch:
      summary: Update merchant pricing and reserve policy
      operationId: updateMerchantPricing
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantPricingRequest"
      responses:
        200:
          description: Merchant updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantResponse"
  "/admin/merchants/{merchantId}/settlement-account":
    patch:
      summary: Update merchant settlement account
      operationId: updateMerchantSettlementAccount
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantSettlementAccountRequest"
      responses:
        200:
          description: Merchant updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantResponse"
  "/admin/merchants/{merchantId}/risk-tier":
    post:
      summary: Update merchant risk tier
      operationId: updateMerchantRiskTier
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantRiskTierRequest"
      responses:
        200:
          description: Merchant risk profile updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantRiskProfileResponse"
        404:
          description: Merchant not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/admin/merchants/{merchantId}/velocity-caps":
    post:
      summary: Update merchant velocity caps
      operationId: updateMerchantVelocityCaps
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantVelocityCapsRequest"
      responses:
        200:
          description: Merchant risk profile updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantRiskProfileResponse"
        404:
          description: Merchant not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/auth/login:
    post:
      summary: Authenticate a merchant user and issue merchant-scoped tokens
      operationId: loginMerchant
      tags:
        - Merchant Identity
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantLoginRequest"
      responses:
        200:
          description: Merchant-scoped tokens
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
        401:
          description: Invalid credentials
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        403:
          description: Active merchant membership not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/auth/refresh:
    post:
      summary: Rotate merchant-scoped access and refresh tokens
      operationId: refreshMerchant
      tags:
        - Merchant Identity
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RefreshRequest"
      responses:
        200:
          description: Rotated merchant-scoped tokens
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
        401:
          description: Invalid refresh token
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/auth/logout:
    post:
      summary: Revoke the active merchant user session
      operationId: logoutMerchant
      tags:
        - Merchant Identity
      security:
        - 
          bearerAuth:

      responses:
        204:
          description: Merchant session revoked
        403:
          description: Human merchant context required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/merchant/invitations/{token}/accept":
    post:
      summary: Accept a merchant team invitation
      operationId: acceptMerchantInvitation
      tags:
        - Merchant Identity
      parameters:
        - 
          name: token
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantInvitationAcceptRequest"
      responses:
        200:
          description: Merchant-scoped tokens
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
        401:
          description: Invalid credentials
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        403:
          description: Invitation not found or membership unavailable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        410:
          description: Invitation expired
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/me:
    get:
      summary: Read the active merchant user context
      operationId: getMerchantMe
      tags:
        - Merchant Identity
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Active merchant user context
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantMeResponse"
        403:
          description: Human merchant context required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/memberships:
    get:
      summary: List merchants the current user belongs to
      operationId: listMerchantMemberships
      tags:
        - Merchant Identity
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant memberships
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantMembershipResponse"
  "/merchant/memberships/{merchantId}/switch":
    post:
      summary: Issue tokens scoped to one merchant membership
      operationId: switchMerchantMembership
      tags:
        - Merchant Identity
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/MerchantId"
      responses:
        200:
          description: Merchant-scoped tokens
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
        403:
          description: Active membership not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/origins:
    get:
      summary: List verified-origin records for the active merchant
      operationId: listMerchantOrigins
      tags:
        - Merchant Origins
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant origin records
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantOriginResponse"
        403:
          description: Merchant owner or developer role required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
    post:
      summary: Create a merchant origin verification challenge
      operationId: createMerchantOrigin
      tags:
        - Merchant Origins
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantOriginRequest"
      responses:
        201:
          description: Merchant origin challenge created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantOriginResponse"
        400:
          description: Origin is invalid
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        409:
          description: Origin already exists for the merchant
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/merchant/origins/{id}/verify":
    post:
      summary: Verify a merchant origin DNS or HTML challenge
      operationId: verifyMerchantOrigin
      tags:
        - Merchant Origins
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Merchant origin verified
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantOriginResponse"
        404:
          description: Merchant origin not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        422:
          description: Verification challenge was not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/merchant/origins/{id}":
    delete:
      summary: Delete a merchant origin
      operationId: deleteMerchantOrigin
      tags:
        - Merchant Origins
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Merchant origin deleted
        404:
          description: Merchant origin not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/team/members:
    get:
      summary: List merchant team members
      operationId: listMerchantTeamMembers
      tags:
        - Merchant Team
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant team members
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantTeamMemberResponse"
        403:
          description: Merchant owner or admin role required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/team/invitations:
    post:
      summary: Invite a merchant team member
      operationId: createMerchantTeamInvitation
      tags:
        - Merchant Team
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantInvitationRequest"
      responses:
        201:
          description: Merchant team invitation created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantInvitationResponse"
        403:
          description: Merchant owner or admin role required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/merchant/team/invitations/{id}/resend":
    post:
      summary: Resend a pending merchant team invitation
      operationId: resendMerchantTeamInvitation
      tags:
        - Merchant Team
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Merchant team invitation refreshed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantInvitationResponse"
        404:
          description: Merchant invitation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/merchant/team/invitations/{id}":
    delete:
      summary: Revoke a pending merchant team invitation
      operationId: deleteMerchantTeamInvitation
      tags:
        - Merchant Team
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Merchant team invitation revoked
        404:
          description: Merchant invitation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  "/merchant/team/members/{id}":
    patch:
      summary: Update a merchant team member role
      operationId: updateMerchantTeamMemberRole
      tags:
        - Merchant Team
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantTeamRoleRequest"
      responses:
        200:
          description: Merchant team member updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantTeamMemberResponse"
        404:
          description: Merchant team member not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
    delete:
      summary: Revoke a merchant team member
      operationId: deleteMerchantTeamMember
      tags:
        - Merchant Team
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Merchant team member revoked
        404:
          description: Merchant team member not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/audit-log:
    get:
      summary: List audit events for the active merchant
      operationId: listMerchantAuditLog
      tags:
        - Merchant Audit
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: cursor
          in: query
          description: Page cursor returned by the previous response.
          schema:
            type: string
        - 
          name: action
          in: query
          description: Audit action code.
          schema:
            type: string
        - 
          name: actor
          in: query
          description: Merchant actor role.
          schema:
            type: string
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 100
      responses:
        200:
          description: Merchant audit events
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAuditLogPageResponse"
        400:
          description: Invalid cursor
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
        403:
          description: Human merchant context required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/risk/profile:
    get:
      summary: Read the active merchant risk profile
      operationId: getMerchantRiskProfile
      tags:
        - Merchant Risk
      security:
        - 
          bearerAuth:

        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant risk profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantRiskProfileResponse"
        403:
          description: Merchant context required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/risk/limits:
    get:
      summary: Read merchant velocity caps and remaining headroom
      operationId: getMerchantRiskLimits
      tags:
        - Merchant Risk
      security:
        - 
          bearerAuth:

        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant velocity caps
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantRiskLimitsResponse"
        403:
          description: Merchant context required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/risk/kpis:
    get:
      summary: Read daily merchant risk KPIs
      operationId: listMerchantRiskKpis
      tags:
        - Merchant Risk
      security:
        - 
          bearerAuth:

        - 
          merchantApiKey:

      parameters:
        - 
          name: range
          in: query
          schema:
            type: string
            default: 30d
      responses:
        200:
          description: Daily merchant risk KPIs
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantRiskKpiResponse"
        403:
          description: Merchant context required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /merchant/api-keys:
    get:
      summary: List merchant API keys without exposing raw secrets
      operationId: listMerchantApiKeys
      tags:
        - Merchant API Keys
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant API key inventory
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantApiKeySummaryResponse"
    post:
      summary: Create a merchant API key from the merchant dashboard
      operationId: createMerchantSelfApiKey
      tags:
        - Merchant API Keys
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantApiKeyRequest"
      responses:
        201:
          description: Raw API key returned once
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantApiKeyResponse"
  "/merchant/api-keys/{apiKeyId}":
    delete:
      summary: Revoke a merchant API key from the merchant dashboard
      operationId: revokeMerchantApiKey
      tags:
        - Merchant API Keys
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: apiKeyId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Revoked merchant API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantApiKeySummaryResponse"
  /merchant/payment-links:
    post:
      summary: Create a merchant payment link
      operationId: createMerchantPaymentLink
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantPaymentLinkRequest"
      responses:
        201:
          description: Payment link created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantPaymentLinkResponse"
    get:
      summary: List merchant payment links
      operationId: listMerchantPaymentLinks
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant payment links
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantPaymentLinkResponse"
  /merchant/checkout-sessions:
    post:
      summary: Create a hosted checkout session
      operationId: createMerchantCheckoutSession
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantCheckoutSessionRequest"
      responses:
        201:
          description: Checkout session created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantCheckoutSessionResponse"
  "/merchant/checkout-sessions/{checkoutSessionId}":
    get:
      summary: Read a merchant checkout session
      operationId: getMerchantCheckoutSession
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: checkoutSessionId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Checkout session
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantCheckoutSessionResponse"
  /merchant/ledger:
    get:
      summary: Read merchant ledger balance
      operationId: getMerchantLedger
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: currency
          in: query
          schema:
            type: string
            default: USD
      responses:
        200:
          description: Ledger balances
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantLedgerBalance"
  /merchant/payments:
    get:
      summary: List merchant payments with search and filters
      operationId: listMerchantPayments
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: cursor
          in: query
          schema:
            type: string
        - 
          name: date_from
          in: query
          schema:
            type: string
            format: date-time
        - 
          name: date_to
          in: query
          schema:
            type: string
            format: date-time
        - 
          name: status
          in: query
          schema:
            type: string
            enum:
              - PAID
              - REFUNDED
        - 
          name: rail
          in: query
          schema:
            type: string
        - 
          name: min_amount
          in: query
          schema:
            type: number
        - 
          name: max_amount
          in: query
          schema:
            type: number
        - 
          name: q
          in: query
          schema:
            type: string
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 50
            maximum: 50
      responses:
        200:
          description: Merchant payments
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantPaymentPageResponse"
  /merchant/payments.csv:
    get:
      summary: Export merchant payments as CSV
      operationId: exportMerchantPaymentsCsv
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: date_from
          in: query
          schema:
            type: string
            format: date-time
        - 
          name: date_to
          in: query
          schema:
            type: string
            format: date-time
        - 
          name: status
          in: query
          schema:
            type: string
            enum:
              - PAID
              - REFUNDED
        - 
          name: rail
          in: query
          schema:
            type: string
        - 
          name: min_amount
          in: query
          schema:
            type: number
        - 
          name: max_amount
          in: query
          schema:
            type: number
        - 
          name: q
          in: query
          schema:
            type: string
      responses:
        200:
          description: Payments CSV stream
          content:
            text/csv:
              schema:
                type: string
  /merchant/events:
    get:
      summary: Stream live merchant dashboard events
      operationId: streamMerchantEvents
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Server-sent merchant dashboard events
          content:
            text/event-stream:
              schema:
                $ref: "#/components/schemas/MerchantDashboardEventResponse"
  /merchant/analytics/overview:
    get:
      summary: Read merchant analytics overview
      operationId: getMerchantAnalyticsOverview
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: range
          in: query
          schema:
            type: string
            default: 7d
      responses:
        200:
          description: Merchant analytics overview
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAnalyticsOverviewResponse"
  /merchant/analytics/timeseries:
    get:
      summary: Read merchant analytics timeseries
      operationId: getMerchantAnalyticsTimeseries
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: metric
          in: query
          schema:
            type: string
            default: volume
        - 
          name: range
          in: query
          schema:
            type: string
            default: 7d
        - 
          name: bucket
          in: query
          schema:
            type: string
            enum:
              - hour
              - day
            default: hour
      responses:
        200:
          description: Merchant analytics timeseries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAnalyticsTimeseriesResponse"
  /merchant/analytics/rails:
    get:
      summary: Read merchant payment rail mix
      operationId: getMerchantAnalyticsRails
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: range
          in: query
          schema:
            type: string
            default: 30d
      responses:
        200:
          description: Merchant payment rail mix
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantRailMixResponse"
  /merchant/analytics/funnel:
    get:
      summary: Read merchant checkout funnel
      operationId: getMerchantAnalyticsFunnel
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: range
          in: query
          schema:
            type: string
            default: 30d
      responses:
        200:
          description: Merchant checkout funnel
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantFunnelResponse"
  /merchant/analytics/top-customers:
    get:
      summary: Read merchant top customers
      operationId: getMerchantAnalyticsTopCustomers
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: range
          in: query
          schema:
            type: string
            default: 30d
        - 
          name: limit
          in: query
          schema:
            type: integer
            default: 10
            maximum: 50
      responses:
        200:
          description: Merchant top customers
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantTopCustomersResponse"
  /merchant/analytics/payout-schedule:
    get:
      summary: Read merchant payout schedule
      operationId: getMerchantAnalyticsPayoutSchedule
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant payout schedule
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantPayoutScheduleResponse"
  /merchant/health:
    get:
      summary: Read merchant operational health KPIs
      operationId: getMerchantHealth
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant operational health KPIs
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantHealthResponse"
  /merchant/statements:
    get:
      summary: List generated merchant statements
      operationId: listMerchantStatements
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: page
          in: query
          schema:
            type: integer
            default: 0
            minimum: 0
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 100
      responses:
        200:
          description: Generated merchant statements
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantStatementPageResponse"
  "/merchant/statements/{statementId}.pdf":
    get:
      summary: Download a generated merchant statement PDF
      operationId: downloadMerchantStatementPdf
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: statementId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Merchant statement PDF
          content:
            application/pdf:
              schema:
                type: string
                format: binary
  "/merchant/payments/{paymentId}":
    get:
      summary: Read one merchant payment
      operationId: getMerchantPayment
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: paymentId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Merchant payment
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantPaymentDetailResponse"
  "/merchant/payments/{paymentId}/receipt/resend":
    post:
      summary: Resend a branded merchant payment receipt
      operationId: resendMerchantPaymentReceipt
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: paymentId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Receipt delivery queued
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantReceiptDeliveryResponse"
  /merchant/payouts:
    get:
      summary: List merchant payouts
      operationId: listMerchantPayouts
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant payouts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantPayoutResponse"
  /merchant/refunds:
    get:
      summary: List merchant refunds
      operationId: listMerchantRefunds
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: cursor
          in: query
          schema:
            type: string
        - 
          name: status
          in: query
          schema:
            type: string
            enum:
              - COMPLETED
        - 
          name: size
          in: query
          schema:
            type: integer
            default: 50
            maximum: 50
      responses:
        200:
          description: Merchant refunds
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantRefundPageResponse"
    post:
      summary: Create a full merchant refund
      operationId: createMerchantRefund
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantRefundRequest"
      responses:
        201:
          description: Refund completed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantRefundResponse"
  /merchant/receipts/bulk-resend:
    post:
      summary: Bulk resend branded merchant payment receipts
      operationId: bulkResendMerchantReceipts
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantBulkReceiptResendRequest"
      responses:
        200:
          description: Receipt deliveries queued
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantBulkReceiptResendResponse"
  /merchant/branding:
    get:
      summary: Read merchant receipt branding
      operationId: getMerchantBranding
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant receipt branding
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantBrandingResponse"
    patch:
      summary: Update merchant receipt branding
      operationId: updateMerchantBranding
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantBrandingRequest"
      responses:
        200:
          description: Merchant receipt branding
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantBrandingResponse"
  /merchant/branding/logo:
    post:
      summary: Upload merchant receipt logo
      operationId: uploadMerchantBrandingLogo
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
              properties:
                file:
                  type: string
                  format: binary
      responses:
        200:
          description: Merchant receipt branding
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantBrandingResponse"
  /merchant/webhook:
    get:
      summary: Read merchant webhook configuration
      operationId: getMerchantWebhook
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Webhook configuration without signing secret
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantWebhookResponse"
    post:
      summary: Configure merchant webhook endpoint
      operationId: configureMerchantWebhook
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantWebhookRequest"
      responses:
        200:
          description: Webhook signing secret returned once
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantWebhookSecretResponse"
  /merchant/webhook-endpoints:
    get:
      summary: List merchant webhook endpoints
      operationId: listMerchantWebhookEndpoints
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant webhook endpoints
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantWebhookEndpointResponse"
    post:
      summary: Create a merchant webhook endpoint
      operationId: createMerchantWebhookEndpoint
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantWebhookEndpointRequest"
      responses:
        201:
          description: Webhook signing secret returned once
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantWebhookEndpointSecretResponse"
  "/merchant/webhook-endpoints/{endpointId}/deliveries":
    get:
      summary: List webhook delivery attempts for one endpoint
      operationId: listMerchantWebhookEndpointDeliveries
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Merchant webhook endpoint deliveries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantWebhookDeliveryResponse"
  "/merchant/webhook-endpoints/{endpointId}":
    delete:
      summary: Deactivate a merchant webhook endpoint
      operationId: deleteMerchantWebhookEndpoint
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        204:
          description: Merchant webhook endpoint deactivated
        404:
          description: Merchant webhook endpoint not found
  "/merchant/webhook-endpoints/{endpointId}/test":
    post:
      summary: Send a synthetic webhook endpoint test event
      operationId: testMerchantWebhookEndpoint
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Test delivery result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantWebhookDeliveryResponse"
  "/merchant/webhook-endpoints/{endpointId}/deliveries/{deliveryId}/replay":
    post:
      summary: Replay a webhook endpoint delivery
      operationId: replayMerchantWebhookEndpointDelivery
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - 
          name: deliveryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Replay result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantWebhookDeliveryResponse"
  /merchant/webhook-deliveries:
    get:
      summary: List merchant webhook delivery attempts
      operationId: listMerchantWebhookDeliveries
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Merchant webhook deliveries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantWebhookDeliveryResponse"
  "/merchant/webhook-deliveries/{deliveryId}/replay":
    post:
      summary: Replay a merchant webhook delivery
      operationId: replayMerchantWebhookDelivery
      tags:
        - Merchant API
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: deliveryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Replay result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantWebhookDeliveryResponse"
  /webhook-events:
    get:
      summary: List webhook events available for merchant subscriptions
      operationId: listWebhookEvents
      tags:
        - Merchant API
      responses:
        200:
          description: Webhook event catalogue
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WebhookEventResponse"
  "/checkout-sessions/{token}":
    get:
      summary: Read a hosted checkout session
      operationId: getHostedCheckoutSession
      tags:
        - Checkout
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: token
          in: path
          required: true
          schema:
            type: string
      responses:
        200:
          description: Hosted checkout session
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantCheckoutSessionResponse"
  "/checkout-sessions/{token}/pay":
    post:
      summary: Pay a hosted checkout session
      operationId: payHostedCheckoutSession
      tags:
        - Checkout
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: token
          in: path
          required: true
          schema:
            type: string
        - 
          name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantCheckoutPayRequest"
      responses:
        200:
          description: Checkout paid
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantPaymentResponse"
  /admin/merchant-ledger/reconciliation:
    get:
      summary: List merchant ledger reconciliation balances
      operationId: getMerchantLedgerReconciliation
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant reconciliation rows
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantReconciliationRow"
  /admin/merchant-payouts:
    get:
      summary: List merchant payouts for finance operations
      operationId: listAdminMerchantPayouts
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant payouts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantPayoutResponse"
  "/admin/merchant-payouts/{payoutId}/retry":
    post:
      summary: Retry a failed merchant payout
      operationId: retryMerchantPayout
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: payoutId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Retry result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantPayoutResponse"
  /admin/merchant-refunds:
    get:
      summary: List merchant refunds for finance operations
      operationId: listAdminMerchantRefunds
      tags:
        - Merchant Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Merchant refunds
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantRefundResponse"
  /developers/signup:
    post:
      summary: Register a developer sandbox account
      operationId: signupDeveloper
      tags:
        - Developers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeveloperSignupRequest"
      responses:
        200:
          description: Verification code issued for sandbox onboarding
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperSignupResponse"
  /developers/verify-email:
    post:
      summary: Verify developer email and issue sandbox API key
      operationId: verifyDeveloperEmail
      tags:
        - Developers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeveloperVerifyEmailRequest"
      responses:
        200:
          description: Sandbox API key returned once
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperApiKeyResponse"
  /developer/me:
    get:
      summary: Read developer profile
      operationId: getDeveloperProfile
      tags:
        - Developer API
      security:
        - 
          developerApiKey:

      responses:
        200:
          description: Developer profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperProfileResponse"
  /developer/sandbox/checkout-sessions:
    post:
      summary: Create a sandbox checkout session
      operationId: createDeveloperSandboxCheckout
      tags:
        - Developer API
      security:
        - 
          developerApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeveloperCheckoutSessionRequest"
      responses:
        201:
          description: Sandbox checkout session
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantCheckoutSessionResponse"
  /developer/api-explorer/run:
    post:
      summary: Run an API explorer sandbox request
      operationId: runDeveloperApiExplorer
      tags:
        - Developer API
      security:
        - 
          developerApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeveloperExplorerRunRequest"
      responses:
        201:
          description: API explorer run
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperExplorerRunResponse"
  /developer/webhook-signature:
    post:
      summary: Generate webhook signature example
      operationId: signDeveloperWebhook
      tags:
        - Developer API
      security:
        - 
          developerApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeveloperWebhookSignatureRequest"
      responses:
        200:
          description: Signed webhook header values
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperWebhookSignatureResponse"
  /developer/integrations:
    get:
      summary: List developer integrations
      operationId: listDeveloperIntegrations
      tags:
        - Developer API
      security:
        - 
          developerApiKey:

      responses:
        200:
          description: Developer integrations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeveloperIntegrationResponse"
    post:
      summary: Install a developer integration
      operationId: installDeveloperIntegration
      tags:
        - Developer API
      security:
        - 
          developerApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeveloperIntegrationRequest"
      responses:
        201:
          description: Integration installed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperIntegrationResponse"
  "/developer/integrations/{integrationId}/test-order":
    post:
      summary: Create plugin test order and update status
      operationId: createDeveloperPluginTestOrder
      tags:
        - Developer API
      security:
        - 
          developerApiKey:

      parameters:
        - 
          name: integrationId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Plugin test order result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperPluginTestOrderResponse"
  /admin/developers:
    get:
      summary: List developer accounts
      operationId: listAdminDevelopers
      tags:
        - Developer Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Developer accounts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeveloperProfileResponse"
  "/admin/developers/{developerId}/status":
    patch:
      summary: Update developer account status
      operationId: updateDeveloperStatus
      tags:
        - Developer Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: developerId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeveloperStatusRequest"
      responses:
        200:
          description: Developer account updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeveloperProfileResponse"
  /bip/billers/register:
    post:
      summary: Register a biller for local BIP onboarding
      operationId: registerBipBiller
      tags:
        - BIP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BipBillerRegisterRequest"
      responses:
        200:
          description: BIP biller registered for KYB review
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipBillerResponse"
  "/bip/billers/{billerId}/kyb-documents":
    post:
      summary: Upload BIP biller KYB evidence for an onboarding application
      operationId: uploadBipKybDocument
      tags:
        - BIP
      parameters:
        - 
          $ref: "#/components/parameters/BipBillerId"
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - documentType
                - registrationNo
                - file
              properties:
                documentType:
                  type: string
                  enum:
                    - CERTIFICATE_OF_INCORPORATION
                    - TAX_CLEARANCE
                    - DIRECTORS_ID
                    - PROOF_OF_ADDRESS
                    - BANK_ACCOUNT_LETTER
                registrationNo:
                  type: string
                file:
                  type: string
                  format: binary
      responses:
        201:
          description: BIP KYB document stored
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipKybDocumentResponse"
  /admin/bip/billers:
    get:
      summary: List BIP billers
      operationId: listBipBillers
      tags:
        - BIP Admin
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: BIP billers
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BipBillerResponse"
  "/admin/bip/billers/{billerId}/kyb":
    patch:
      summary: Update BIP biller KYB status
      operationId: updateBipKyb
      tags:
        - BIP Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/BipBillerId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BipKybRequest"
      responses:
        200:
          description: BIP biller updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipBillerResponse"
  "/admin/bip/billers/{billerId}/api-keys":
    post:
      summary: Issue a one-time BIP biller API key
      operationId: createBipApiKey
      tags:
        - BIP Admin
      security:
        - 
          bearerAuth:

      parameters:
        - 
          $ref: "#/components/parameters/BipBillerId"
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BipApiKeyRequest"
      responses:
        200:
          description: One-time BIP API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipApiKeyResponse"
  /bip/biller/bills/single:
    post:
      summary: Push one bill through local BIP
      operationId: pushBipBill
      tags:
        - BIP Biller
      security:
        - 
          bipBillerKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BipBillPushRequest"
      responses:
        202:
          description: Bill accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipBillResponse"
  /bip/biller/bills/batch:
    post:
      summary: Push a batch of bills through local BIP
      operationId: pushBipBillBatch
      tags:
        - BIP Biller
      security:
        - 
          bipBillerKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BipBatchPushRequest"
      responses:
        202:
          description: Batch accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipBatchPushResponse"
  /bip/biller/subscription-plans:
    get:
      summary: List BIP subscription plans
      operationId: listBipSubscriptionPlans
      tags:
        - BIP Biller
      security:
        - 
          bipBillerKey:

      responses:
        200:
          description: Subscription plans
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BipSubscriptionPlanResponse"
    post:
      summary: Create a BIP subscription plan
      operationId: createBipSubscriptionPlan
      tags:
        - BIP Biller
      security:
        - 
          bipBillerKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BipSubscriptionPlanRequest"
      responses:
        201:
          description: Subscription plan created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipSubscriptionPlanResponse"
  /bip/biller/subscriptions/enroll:
    post:
      summary: Enroll a customer into a BIP subscription
      operationId: enrollBipSubscription
      tags:
        - BIP Biller
      security:
        - 
          bipBillerKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BipSubscriptionEnrollRequest"
      responses:
        201:
          description: Customer enrolled
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipSubscriptionResponse"
  /bip/biller/subscriptions/run-due:
    post:
      summary: Generate due BIP subscription bills
      operationId: runBipDueSubscriptions
      tags:
        - BIP Biller
      security:
        - 
          bipBillerKey:

      responses:
        200:
          description: Due cycle result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BipSubscriptionRunResponse"
  /admin/trust/status:
    get:
      summary: Get trust and scale platform status
      operationId: getTrustPlatformStatus
      tags:
        - Trust
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Platform component status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlatformStatusResponse"
  /admin/trust/risk-assessments:
    get:
      summary: List recent fraud risk assessments
      operationId: listTrustRiskAssessments
      tags:
        - Trust
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Risk assessments
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TrustAssessmentResponse"
  /compliance/cases:
    get:
      summary: List compliance cases
      operationId: listComplianceCases
      tags:
        - Compliance
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: status
          in: query
          required: false
          schema:
            type: string
            enum:
              - OPEN
              - UNDER_REVIEW
              - CLEARED
              - ESCALATED
              - BLOCKED
      responses:
        200:
          description: Compliance cases
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ComplianceCaseResponse"
  "/compliance/cases/{caseId}/review":
    patch:
      summary: Review a compliance case
      operationId: reviewComplianceCase
      tags:
        - Compliance
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: caseId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ComplianceCaseReviewRequest"
      responses:
        200:
          description: Reviewed compliance case
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComplianceCaseResponse"
  /admin/trust/regulatory-reports:
    get:
      summary: List regulatory report packs
      operationId: listRegulatoryReports
      tags:
        - Trust
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Regulatory reports
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/RegulatoryReportResponse"
    post:
      summary: Generate a regulatory report pack
      operationId: generateRegulatoryReport
      tags:
        - Trust
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegulatoryReportRequest"
      responses:
        201:
          description: Generated regulatory report
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RegulatoryReportResponse"
  "/admin/trust/regulatory-reports/{reportId}/submit":
    post:
      summary: Mark a regulatory report as submitted
      operationId: submitRegulatoryReport
      tags:
        - Trust
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: reportId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        200:
          description: Submitted regulatory report
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RegulatoryReportResponse"
  /financial/wallet:
    get:
      summary: Read customer wallet balance
      operationId: getFinancialWallet
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: currency
          in: query
          required: false
          schema:
            type: string
            default: USD
      responses:
        200:
          description: Customer wallet
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WalletResponse"
  /financial/wallet/top-ups:
    post:
      summary: Create a wallet top-up
      operationId: topUpFinancialWallet
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WalletAmountRequest"
      responses:
        200:
          description: Updated wallet
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WalletResponse"
  /financial/wallet/savings-transfer:
    post:
      summary: Transfer wallet balance to savings balance
      operationId: transferWalletSavings
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WalletAmountRequest"
      responses:
        200:
          description: Updated wallet
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WalletResponse"
  /financial/virtual-cards:
    get:
      summary: List customer virtual cards
      operationId: listVirtualCards
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Virtual cards
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/VirtualCardResponse"
    post:
      summary: Issue a customer virtual card
      operationId: issueVirtualCard
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VirtualCardRequest"
      responses:
        201:
          description: Virtual card issued
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VirtualCardResponse"
  /financial/open-banking/consents:
    get:
      summary: List customer open banking consents
      operationId: listOpenBankingConsents
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Open banking consents
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/OpenBankingConsentResponse"
    post:
      summary: Create an open banking consent
      operationId: createOpenBankingConsent
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OpenBankingConsentRequest"
      responses:
        201:
          description: Consent created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OpenBankingConsentResponse"
  /financial/ussd/sessions:
    post:
      summary: Start a USSD session
      operationId: startUssdSession
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UssdSessionRequest"
      responses:
        201:
          description: USSD session started
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UssdSessionResponse"
  /merchant/advances:
    get:
      summary: List merchant cash advance offers
      operationId: listMerchantAdvances
      tags:
        - Merchant Acceptance
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Advance offers
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantAdvanceOfferResponse"
  /merchant/advances/offers:
    post:
      summary: Create a merchant cash advance offer
      operationId: createMerchantAdvanceOffer
      tags:
        - Merchant Acceptance
      security:
        - 
          merchantApiKey:

      responses:
        201:
          description: Advance offer created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAdvanceOfferResponse"
  "/merchant/advances/{advanceId}/draw":
    post:
      summary: Draw an approved merchant advance
      operationId: drawMerchantAdvance
      tags:
        - Merchant Acceptance
      security:
        - 
          merchantApiKey:

      parameters:
        - 
          name: advanceId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AdvanceDrawRequest"
      responses:
        200:
          description: Advance drawn
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAdvanceOfferResponse"
  /merchant/platforms/sub-merchants:
    get:
      summary: List platform sub-merchants
      operationId: listPlatformSubMerchants
      tags:
        - Merchant Acceptance
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Platform sub-merchants
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PlatformSubMerchantResponse"
    post:
      summary: Register a platform sub-merchant
      operationId: createPlatformSubMerchant
      tags:
        - Merchant Acceptance
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PlatformSubMerchantRequest"
      responses:
        201:
          description: Sub-merchant registered
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlatformSubMerchantResponse"
  /merchant/platforms/split-rules:
    get:
      summary: List platform split rules
      operationId: listPlatformSplitRules
      tags:
        - Merchant Acceptance
      security:
        - 
          merchantApiKey:

      responses:
        200:
          description: Platform split rules
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PlatformSplitRuleResponse"
    post:
      summary: Create a platform split rule
      operationId: createPlatformSplitRule
      tags:
        - Merchant Acceptance
      security:
        - 
          merchantApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PlatformSplitRuleRequest"
      responses:
        201:
          description: Split rule created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlatformSplitRuleResponse"
  /developer/marketplace/apps:
    get:
      summary: List developer marketplace apps
      operationId: listDeveloperMarketplaceApps
      tags:
        - Developer Platform
      security:
        - 
          developerApiKey:

      responses:
        200:
          description: Marketplace apps
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MarketplaceAppResponse"
    post:
      summary: Submit a developer marketplace app
      operationId: submitMarketplaceApp
      tags:
        - Developer Platform
      security:
        - 
          developerApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MarketplaceAppRequest"
      responses:
        201:
          description: Marketplace app submitted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MarketplaceAppResponse"
  /developer/partner-program/apply:
    post:
      summary: Apply for the Pay Mate partner programme
      operationId: applyPartnerProgram
      tags:
        - Developer Platform
      security:
        - 
          developerApiKey:

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PartnerApplicationRequest"
      responses:
        201:
          description: Partner application submitted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PartnerApplicationResponse"
  /developer/partner-program:
    get:
      summary: Read latest partner programme application
      operationId: getPartnerProgramApplication
      tags:
        - Developer Platform
      security:
        - 
          developerApiKey:

      responses:
        200:
          description: Partner application
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PartnerApplicationResponse"
  /admin/ecosystem/overview:
    get:
      summary: Read financial ecosystem overview
      operationId: getEcosystemOverview
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Ecosystem overview
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EcosystemOverviewResponse"
  /admin/ecosystem/marketplace-apps:
    get:
      summary: List marketplace apps for review
      operationId: listAdminMarketplaceApps
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Marketplace apps
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MarketplaceAppResponse"
  "/admin/ecosystem/marketplace-apps/{appId}":
    patch:
      summary: Review a marketplace app
      operationId: reviewMarketplaceApp
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: appId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MarketplaceReviewRequest"
      responses:
        200:
          description: Marketplace app reviewed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MarketplaceAppResponse"
  /admin/ecosystem/partner-applications:
    get:
      summary: List partner programme applications
      operationId: listAdminPartnerApplications
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      responses:
        200:
          description: Partner applications
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PartnerApplicationResponse"
  "/admin/ecosystem/partner-applications/{partnerId}":
    patch:
      summary: Review a partner programme application
      operationId: reviewPartnerApplication
      tags:
        - Financial Products
      security:
        - 
          bearerAuth:

      parameters:
        - 
          name: partnerId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PartnerReviewRequest"
      responses:
        200:
          description: Partner application reviewed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PartnerApplicationResponse"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    merchantApiKey:
      type: apiKey
      in: header
      name: X-PayMate-Merchant-Key
    developerApiKey:
      type: apiKey
      in: header
      name: X-PayMate-Developer-Key
    bipBillerKey:
      type: apiKey
      in: header
      name: X-PayMate-Biller-Key
    internalApiKey:
      type: apiKey
      in: header
      name: X-PAYMATE-INTERNAL-API-KEY
  parameters:
    BillieMode:
      name: Billie-Mode
      in: header
      required: false
      description: "Set to `test` when using a test-mode merchant API key."
      schema:
        type: string
        enum:
          - test
    MerchantId:
      name: merchantId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    BipBillerId:
      name: billerId
      in: path
      required: true
      schema:
        type: string
        format: uuid
  schemas:
    ApiError:
      type: object
      properties:
        error:
          type: string
        retryAfterSeconds:
          type:
            - integer
            - null
        limit:
          type:
            - number
            - null
        fieldErrors:
          type:
            - object
            - null
          additionalProperties:
            type: string
    RegisterRequest:
      type: object
      required:
        - phoneNumber
      properties:
        phoneNumber:
          type: string
          maxLength: 24
        email:
          type:
            - string
            - null
          format: email
          maxLength: 255
        fullName:
          type:
            - string
            - null
          maxLength: 120
    MessageResponse:
      type: object
      required:
        - message
      properties:
        message:
          type: string
    VerifyRequest:
      type: object
      required:
        - phoneNumber
        - code
        - purpose
      properties:
        phoneNumber:
          type: string
        code:
          type: string
          pattern: "^\\d{6}$"
        purpose:
          type: string
          enum:
            - REGISTER
            - LOGIN
            - VERIFY
    LoginRequest:
      type: object
      required:
        - phoneNumber
        - pin
      properties:
        phoneNumber:
          type: string
        pin:
          type: string
          pattern: "^\\d{6}$"
    PinRequest:
      type: object
      required:
        - pin
      properties:
        pin:
          type: string
          pattern: "^\\d{6}$"
    RefreshRequest:
      type: object
      required:
        - refreshToken
      properties:
        refreshToken:
          type: string
    UserSummary:
      type: object
      required:
        - id
        - phoneNumber
        - kycTier
        - role
      properties:
        id:
          type: string
          format: uuid
        phoneNumber:
          type: string
        kycTier:
          type: integer
          format: int32
        role:
          type: string
          enum:
            - CUSTOMER
            - AGENT
            - ADMIN
            - COMPLIANCE
    AuthResponse:
      type: object
      required:
        - accessToken
        - refreshToken
        - user
      properties:
        accessToken:
          type: string
        refreshToken:
          type: string
        user:
          $ref: "#/components/schemas/UserSummary"
    TokenResponse:
      type: object
      required:
        - accessToken
        - refreshToken
      properties:
        accessToken:
          type: string
        refreshToken:
          type: string
    SessionResponse:
      type: object
      required:
        - id
        - lastActiveAt
        - createdAt
      properties:
        id:
          type: string
          format: uuid
        deviceName:
          type:
            - string
            - null
        lastActiveAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
    KycTier1Request:
      type: object
      required:
        - nationalIdNumber
        - fullName
        - idDocumentBase64
      properties:
        nationalIdNumber:
          type: string
        fullName:
          type: string
        idDocumentBase64:
          type: string
    KycTierResponse:
      type: object
      required:
        - kycTier
      properties:
        kycTier:
          type: integer
          format: int32
    BillerCategoryResponse:
      type: object
      required:
        - id
        - name
        - slug
        - displayOrder
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        slug:
          type: string
        iconKey:
          type:
            - string
            - null
        displayOrder:
          type: integer
    BillerSummary:
      type: object
      required:
        - id
        - name
        - slug
        - categorySlug
        - integrationBadge
        - isVerified
        - feeFixed
        - feePercent
        - feeCurrency
        - postingSlaHours
        - status
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        slug:
          type: string
        categorySlug:
          type: string
        integrationBadge:
          type: string
        isVerified:
          type: boolean
        feeFixed:
          type: number
        feePercent:
          type: number
        feeCurrency:
          type: string
        postingSlaHours:
          type: integer
        status:
          type: string
          enum:
            - ACTIVE
            - MAINTENANCE
            - OFFLINE
    BillerSearchResponse:
      type: object
      required:
        - content
        - totalElements
        - page
      properties:
        content:
          type: array
          items:
            $ref: "#/components/schemas/BillerSummary"
        totalElements:
          type: integer
          format: int64
        page:
          type: integer
    BillerDetail:
      allOf:
        - 
          $ref: "#/components/schemas/BillerSummary"
        - 
          type: object
          required:
            - requiredFields
            - supportedRails
            - integrationTypeLabel
            - verifiedBadgeExplanation
          properties:
            requiredFields:
              type: string
            supportedRails:
              type: array
              items:
                type: string
            integrationTypeLabel:
              type: string
            verifiedBadgeExplanation:
              type: string
    BillerAccountValidationRequest:
      type: object
      required:
        - accountReference
      properties:
        accountReference:
          type: string
    BillerAccountValidationResponse:
      type: object
      required:
        - validationId
        - billerId
        - accountReference
        - valid
        - currency
        - expiresAt
      properties:
        validationId:
          type: string
          format: uuid
        billerId:
          type: string
          format: uuid
        accountReference:
          type: string
        valid:
          type: boolean
        customerName:
          type:
            - string
            - null
        amountDue:
          type:
            - number
            - null
        currency:
          type: string
        validationReference:
          type:
            - string
            - null
        failureReason:
          type:
            - string
            - null
        expiresAt:
          type: string
          format: date-time
    SavedAccountRequest:
      type: object
      required:
        - billerId
        - accountReference
      properties:
        billerId:
          type: string
          format: uuid
        accountReference:
          type: string
        nickname:
          type:
            - string
            - null
        householdId:
          type:
            - string
            - null
          format: uuid
    SavedAccountUpdateRequest:
      type: object
      required:
        - nickname
      properties:
        nickname:
          type: string
    SavedBillerAccountResponse:
      type: object
      required:
        - id
        - billerId
        - billerName
        - accountReference
      properties:
        id:
          type: string
          format: uuid
        billerId:
          type: string
          format: uuid
        billerName:
          type: string
        accountReference:
          type: string
        nickname:
          type:
            - string
            - null
        lastPaymentAt:
          type:
            - string
            - null
          format: date-time
        lastAmount:
          type:
            - number
            - null
    PaymentRequest:
      type: object
      required:
        - billerId
        - accountReference
        - amount
      properties:
        billerId:
          type: string
          format: uuid
        railId:
          type:
            - string
            - null
          format: uuid
        railCode:
          type:
            - string
            - null
        accountReference:
          type: string
        amount:
          type: number
          minimum: 0.01
        savedAccountId:
          type:
            - string
            - null
          format: uuid
        agentCustomerPhone:
          type:
            - string
            - null
    ReceiptResponse:
      type: object
      required:
        - id
        - paymateReference
        - content
      properties:
        id:
          type: string
          format: uuid
        paymateReference:
          type: string
        content:
          type: string
    PaymentResponse:
      type: object
      required:
        - transactionId
        - status
        - total
      properties:
        transactionId:
          type: string
          format: uuid
        status:
          type: string
        total:
          type: number
        receipt:
          oneOf:
            - 
              $ref: "#/components/schemas/ReceiptResponse"
            - 
              type: null
    TransactionSummary:
      type: object
      required:
        - id
        - billerName
        - accountReference
        - amount
        - total
        - currency
        - status
      properties:
        id:
          type: string
          format: uuid
        billerName:
          type: string
        accountReference:
          type: string
        amount:
          type: number
        total:
          type: number
        currency:
          type: string
        status:
          type: string
        createdAt:
          type:
            - string
            - null
          format: date-time
    TransactionPage:
      type: object
      required:
        - content
        - totalElements
        - page
      properties:
        content:
          type: array
          items:
            $ref: "#/components/schemas/TransactionSummary"
        totalElements:
          type: integer
          format: int64
        page:
          type: integer
    CustomerBillLineItem:
      type: object
      required:
        - description
        - quantity
        - unitPrice
        - currency
      properties:
        description:
          type: string
        quantity:
          type: number
        unitPrice:
          type: number
        currency:
          type: string
        taxPercent:
          type:
            - number
            - null
    CustomerBillView:
      type: object
      required:
        - billId
        - billerId
        - sourceBillerId
        - coreBillerId
        - billerName
        - customerRef
        - title
        - totalAmount
        - currency
        - dueDate
        - status
      properties:
        billId:
          type: string
          format: uuid
        billerId:
          type: string
          format: uuid
        sourceBillerId:
          type: string
          format: uuid
        coreBillerId:
          type: string
          format: uuid
        billerName:
          type: string
        billerCategory:
          type:
            - string
            - null
        billerLogoKey:
          type:
            - string
            - null
        customerRef:
          type: string
        title:
          type: string
        totalAmount:
          type: number
        currency:
          type: string
        dueDate:
          type: string
          format: date
        status:
          type: string
          enum:
            - DELIVERED
            - CLAIMABLE
            - VIEWED
            - PAID
            - OVERDUE
        overdue:
          type: boolean
          default: false
        daysUntilDue:
          type: integer
          default: 0
        lineItems:
          type: array
          items:
            $ref: "#/components/schemas/CustomerBillLineItem"
        attachmentUrl:
          type:
            - string
            - null
          format: uri
        paymentTransactionId:
          type:
            - string
            - null
          format: uuid
    CustomerBillPage:
      type: object
      required:
        - content
        - page
        - size
        - total
      properties:
        content:
          type: array
          items:
            $ref: "#/components/schemas/CustomerBillView"
        page:
          type: integer
        size:
          type: integer
        total:
          type: integer
        totalOutstanding:
          oneOf:
            - 
              $ref: "#/components/schemas/BillMoneySummary"
            - 
              type: null
        overdueCount:
          type:
            - integer
            - null
    CustomerBillTimelineItem:
      type: object
      required:
        - status
      properties:
        status:
          type: string
        note:
          type:
            - string
            - null
        createdAt:
          type:
            - string
            - null
          format: date-time
    CustomerBillDetail:
      type: object
      allOf:
        - 
          $ref: "#/components/schemas/CustomerBillView"
        - 
          type: object
          properties:
            timeline:
              type: array
              items:
                $ref: "#/components/schemas/CustomerBillTimelineItem"
    InternalCustomerResolutionRequest:
      type: object
      properties:
        customerPhone:
          type:
            - string
            - null
        customerEmail:
          type:
            - string
            - null
          format: email
        nationalId:
          type:
            - string
            - null
        nationalIdCountry:
          type:
            - string
            - null
          minLength: 2
          maxLength: 2
        customerIdentifiers:
          type: object
          description: "Source-scoped account identifiers accepted for transport; customer linking remains scoped by coreBillerId and customerRef in the aggregator."
          additionalProperties:
            type: string
    InternalCustomerResolutionResponse:
      type: object
      required:
        - matched
        - confidence
      properties:
        matched:
          type: boolean
        userId:
          type:
            - string
            - null
          format: uuid
        confidence:
          type: string
          enum:
            - HIGH
            - NONE
            - CONFLICT
    BillClaimRequest:
      type: object
      required:
        - coreBillerId
        - customerRef
        - totalAmount
        - dueDate
      properties:
        coreBillerId:
          type: string
          format: uuid
        customerRef:
          type: string
          minLength: 1
        totalAmount:
          type: number
          minimum: 0.01
        dueDate:
          type: string
          format: date
    BillPayRequest:
      type: object
      properties:
        railId:
          type:
            - string
            - null
          format: uuid
        railCode:
          type:
            - string
            - null
    BillMoneySummary:
      type: object
      required:
        - amount
        - currency
      properties:
        amount:
          type: number
        currency:
          type: string
    TimelineResponse:
      type: object
      required:
        - status
      properties:
        status:
          type: string
        note:
          type:
            - string
            - null
    PlatformComponentStatus:
      type: object
      required:
        - component
        - status
        - latencyMs
        - details
      properties:
        component:
          type: string
        status:
          type: string
          enum:
            - UP
            - DEGRADED
            - DOWN
        latencyMs:
          type: integer
          minimum: 0
        details:
          type: string
    PlatformStatusResponse:
      type: object
      required:
        - overallStatus
        - checkedAt
        - components
      properties:
        overallStatus:
          type: string
          enum:
            - UP
            - DEGRADED
            - DOWN
        checkedAt:
          type: string
          format: date-time
        components:
          type: array
          items:
            $ref: "#/components/schemas/PlatformComponentStatus"
    TrustAssessmentResponse:
      type: object
      required:
        - id
        - userId
        - billerId
        - railCode
        - amount
        - currency
        - riskScore
        - decision
        - reasons
      properties:
        id:
          type: string
          format: uuid
        transactionId:
          type:
            - string
            - null
          format: uuid
        userId:
          type: string
          format: uuid
        billerId:
          type: string
          format: uuid
        railCode:
          type: string
        amount:
          type: number
        currency:
          type: string
        riskScore:
          type: integer
          minimum: 0
          maximum: 100
        decision:
          type: string
          enum:
            - ALLOW
            - REVIEW
            - BLOCK
        reasons:
          type: string
        createdAt:
          type:
            - string
            - null
          format: date-time
    ComplianceCaseResponse:
      type: object
      required:
        - id
        - userId
        - caseType
        - priority
        - status
        - reason
      properties:
        id:
          type: string
          format: uuid
        assessmentId:
          type:
            - string
            - null
          format: uuid
        transactionId:
          type:
            - string
            - null
          format: uuid
        userId:
          type: string
          format: uuid
        caseType:
          type: string
          enum:
            - FRAUD_RISK
            - AML
            - SANCTIONS
            - REGULATORY
        priority:
          type: string
          enum:
            - LOW
            - MEDIUM
            - HIGH
            - CRITICAL
        status:
          type: string
          enum:
            - OPEN
            - UNDER_REVIEW
            - CLEARED
            - ESCALATED
            - BLOCKED
        reason:
          type: string
        decisionNote:
          type:
            - string
            - null
        openedAt:
          type:
            - string
            - null
          format: date-time
        closedAt:
          type:
            - string
            - null
          format: date-time
    ComplianceCaseReviewRequest:
      type: object
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - UNDER_REVIEW
            - CLEARED
            - ESCALATED
            - BLOCKED
        note:
          type:
            - string
            - null
    RegulatoryReportRequest:
      type: object
      required:
        - reportType
        - periodStart
        - periodEnd
      properties:
        reportType:
          type: string
          enum:
            - RBZ_MONTHLY
            - FIU_SUSPICIOUS_ACTIVITY
            - POTRAZ_SUMMARY
        periodStart:
          type: string
          format: date
        periodEnd:
          type: string
          format: date
    RegulatoryReportResponse:
      type: object
      required:
        - id
        - reportType
        - periodStart
        - periodEnd
        - status
        - payload
      properties:
        id:
          type: string
          format: uuid
        reportType:
          type: string
          enum:
            - RBZ_MONTHLY
            - FIU_SUSPICIOUS_ACTIVITY
            - POTRAZ_SUMMARY
        periodStart:
          type: string
          format: date
        periodEnd:
          type: string
          format: date
        status:
          type: string
          enum:
            - GENERATED
            - SUBMITTED
        payload:
          type: string
        generatedAt:
          type:
            - string
            - null
          format: date-time
        submittedAt:
          type:
            - string
            - null
          format: date-time
        createdAt:
          type:
            - string
            - null
          format: date-time
    TransactionDetail:
      type: object
      required:
        - id
        - billerName
        - railCode
        - accountReference
        - amount
        - fee
        - tax
        - total
        - currency
        - status
        - statusTimeline
      properties:
        id:
          type: string
          format: uuid
        billerName:
          type: string
        railCode:
          type: string
        accountReference:
          type: string
        amount:
          type: number
        fee:
          type: number
        tax:
          type: number
        total:
          type: number
        currency:
          type: string
        status:
          type: string
        failureReason:
          type:
            - string
            - null
        createdAt:
          type:
            - string
            - null
          format: date-time
        statusTimeline:
          type: array
          items:
            $ref: "#/components/schemas/TimelineResponse"
        receipt:
          oneOf:
            - 
              $ref: "#/components/schemas/ReceiptResponse"
            - 
              type: null
    ReceiptUrlResponse:
      type: object
      required:
        - receiptUrl
        - expiresAt
      properties:
        receiptUrl:
          type: string
          format: uri
        expiresAt:
          type: string
          format: date-time
    PaymentDraft:
      type: object
      required:
        - billerId
        - accountReference
        - suggestedAmount
      properties:
        billerId:
          type: string
          format: uuid
        accountReference:
          type: string
        suggestedAmount:
          type: number
    ScheduleRequest:
      type: object
      required:

      properties:
        savedAccountId:
          type:
            - string
            - null
          format: uuid
        billerId:
          type:
            - string
            - null
          format: uuid
        billerName:
          type:
            - string
            - null
        accountReference:
          type:
            - string
            - null
        railId:
          type:
            - string
            - null
          format: uuid
        railCode:
          type:
            - string
            - null
        type:
          type:
            - string
            - null
          enum:
            - ONCE
            - RECURRING
            - null
        recurrence:
          type:
            - string
            - null
          enum:
            - WEEKLY
            - MONTHLY
            - CUSTOM
            - null
        frequency:
          type:
            - string
            - null
        amount:
          type:
            - number
            - null
        maxAmount:
          type:
            - number
            - null
        nextRunAt:
          type:
            - string
            - null
          format: date-time
        firstRunAt:
          type:
            - string
            - null
          format: date-time
        consentGivenAt:
          type:
            - string
            - null
          format: date-time
        noticeHours:
          type:
            - integer
            - null
        reminderDaysBefore:
          type:
            - integer
            - null
        autoPay:
          type:
            - boolean
            - null
    ScheduleUpdateRequest:
      type: object
      properties:
        status:
          type:
            - string
            - null
          enum:
            - ACTIVE
            - PAUSED
            - CANCELLED
            - null
        amount:
          type:
            - number
            - null
        maxAmount:
          type:
            - number
            - null
        nextRunAt:
          type:
            - string
            - null
          format: date-time
    ScheduleResponse:
      type: object
      required:
        - id
        - savedAccountId
        - railId
        - billerName
        - accountReference
        - type
        - nextRunAt
        - consentGivenAt
        - noticeHours
        - status
      properties:
        id:
          type: string
          format: uuid
        savedAccountId:
          type: string
          format: uuid
        railId:
          type: string
          format: uuid
        billerName:
          type: string
        accountReference:
          type: string
        type:
          type: string
        recurrence:
          type:
            - string
            - null
        amount:
          type:
            - number
            - null
        maxAmount:
          type:
            - number
            - null
        nextRunAt:
          type: string
          format: date-time
        consentGivenAt:
          type: string
          format: date-time
        noticeHours:
          type: integer
        status:
          type: string
        lastRunAt:
          type:
            - string
            - null
          format: date-time
    ScheduleRunResponse:
      type: object
      required:
        - id
        - dueAt
        - startedAt
        - status
      properties:
        id:
          type: string
          format: uuid
        transactionId:
          type:
            - string
            - null
          format: uuid
        dueAt:
          type: string
          format: date-time
        startedAt:
          type: string
          format: date-time
        completedAt:
          type:
            - string
            - null
          format: date-time
        status:
          type: string
          enum:
            - PENDING
            - SUCCEEDED
            - FAILED
        failureReason:
          type:
            - string
            - null
    BillerPostingAttemptResponse:
      type: object
      required:
        - id
        - transactionId
        - billerId
        - billerName
        - accountReference
        - amount
        - currency
        - attemptNo
        - status
      properties:
        id:
          type: string
          format: uuid
        transactionId:
          type: string
          format: uuid
        billerId:
          type: string
          format: uuid
        billerName:
          type: string
        accountReference:
          type: string
        amount:
          type: number
        currency:
          type: string
        attemptNo:
          type: integer
        status:
          type: string
          enum:
            - PENDING
            - RETRYING
            - CONFIRMED
            - FAILED
        postingReference:
          type:
            - string
            - null
        failureReason:
          type:
            - string
            - null
        nextRetryAt:
          type:
            - string
            - null
          format: date-time
        createdAt:
          type:
            - string
            - null
          format: date-time
    OutboxEventPage:
      type: object
      required:
        - content
        - totalElements
        - page
      properties:
        content:
          type: array
          items:
            $ref: "#/components/schemas/OutboxEventResponse"
        totalElements:
          type: integer
          format: int64
        page:
          type: integer
    OutboxEventResponse:
      type: object
      required:
        - id
        - topic
        - eventKey
        - status
        - attempts
        - nextAttemptAt
        - createdAt
      properties:
        id:
          type: string
          format: uuid
        topic:
          type: string
        eventKey:
          type: string
        status:
          type: string
          enum:
            - PENDING
            - PUBLISHED
            - FAILED
        attempts:
          type: integer
          minimum: 0
        lastError:
          type:
            - string
            - null
        nextAttemptAt:
          type: string
          format: date-time
        publishedAt:
          type:
            - string
            - null
          format: date-time
        createdAt:
          type: string
          format: date-time
    NotificationDeliveryResponse:
      type: object
      required:
        - id
        - channel
        - eventType
        - title
        - body
        - isRead
      properties:
        id:
          type: string
          format: uuid
        channel:
          type: string
          enum:
            - PUSH
            - SMS
            - EMAIL
        eventType:
          type: string
        title:
          type: string
        body:
          type: string
        referenceId:
          type:
            - string
            - null
          format: uuid
        isRead:
          type: boolean
        createdAt:
          type:
            - string
            - null
          format: date-time
    NotificationPage:
      type: object
      required:
        - content
        - unreadCount
        - page
      properties:
        content:
          type: array
          items:
            $ref: "#/components/schemas/NotificationDeliveryResponse"
        unreadCount:
          type: integer
          format: int64
        page:
          type: integer
    NotificationPreferenceRequest:
      type: object
      properties:
        pushEnabled:
          type:
            - boolean
            - null
        smsEnabled:
          type:
            - boolean
            - null
        emailEnabled:
          type:
            - boolean
            - null
        securityAlerts:
          type:
            - boolean
            - null
    ProfileResponse:
      type: object
      required:
        - id
        - phoneNumber
        - kycTier
        - role
      properties:
        id:
          type: string
          format: uuid
        fullName:
          type:
            - string
            - null
        phoneNumber:
          type: string
        email:
          type:
            - string
            - null
        nationalIdNumber:
          type:
            - string
            - null
        kycTier:
          type: integer
        role:
          type: string
          enum:
            - CUSTOMER
            - AGENT
            - ADMIN
            - COMPLIANCE
    ProfileUpdateRequest:
      type: object
      properties:
        fullName:
          type:
            - string
            - null
        email:
          type:
            - string
            - null
    DisputeRequest:
      type: object
      required:
        - transactionId
        - issueType
      properties:
        transactionId:
          type: string
          format: uuid
        issueType:
          type: string
          enum:
            - FAILED_NOT_POSTED
            - DUPLICATE_DEBIT
            - WRONG_AMOUNT
            - WRONG_ACCOUNT
            - OTHER
        description:
          type:
            - string
            - null
        attachmentBase64:
          type:
            - string
            - null
    DisputePatchRequest:
      type: object
      properties:
        status:
          type:
            - string
            - null
          enum:
            - OPEN
            - IN_REVIEW
            - AWAITING_BILLER
            - RESOLVED
            - ESCALATED
            - CLOSED
            - null
        assignedTo:
          type:
            - string
            - null
          format: uuid
        resolutionNote:
          type:
            - string
            - null
    DisputeCommentRequest:
      type: object
      required:
        - body
      properties:
        body:
          type: string
        attachmentBase64:
          type:
            - string
            - null
    DisputeSummary:
      type: object
      required:
        - id
        - transactionId
        - status
        - slaDeadline
        - caseReference
        - issueType
      properties:
        id:
          type: string
          format: uuid
        transactionId:
          type: string
          format: uuid
        status:
          type: string
        slaDeadline:
          type: string
          format: date-time
        caseReference:
          type: string
        issueType:
          type: string
    DisputeCommentResponse:
      type: object
      required:
        - id
        - authorId
        - body
      properties:
        id:
          type: string
          format: uuid
        authorId:
          type: string
          format: uuid
        body:
          type: string
        attachmentKey:
          type:
            - string
            - null
        createdAt:
          type:
            - string
            - null
          format: date-time
    DisputeDetail:
      type: object
      required:
        - id
        - status
        - issueType
        - comments
        - transaction
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
        issueType:
          type: string
        description:
          type:
            - string
            - null
        assignedTo:
          type:
            - string
            - null
          format: uuid
        slaDeadline:
          type: string
          format: date-time
        resolvedAt:
          type:
            - string
            - null
          format: date-time
        resolutionNote:
          type:
            - string
            - null
        comments:
          type: array
          items:
            $ref: "#/components/schemas/DisputeCommentResponse"
        transaction:
          $ref: "#/components/schemas/TransactionSummary"
    DisputePage:
      type: object
      required:
        - content
        - overdueCount
        - page
      properties:
        content:
          type: array
          items:
            $ref: "#/components/schemas/DisputeSummary"
        overdueCount:
          type: integer
          format: int64
        page:
          type: integer
    HouseholdRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
    HouseholdMemberRequest:
      type: object
      required:
        - phoneNumber
        - role
      properties:
        phoneNumber:
          type: string
        role:
          type: string
          enum:
            - OWNER
            - MEMBER
            - VIEWER
    HouseholdRoleRequest:
      type: object
      required:
        - role
      properties:
        role:
          type: string
          enum:
            - OWNER
            - MEMBER
            - VIEWER
    HouseholdMemberResponse:
      type: object
      required:
        - userId
        - phoneNumber
        - role
      properties:
        userId:
          type: string
          format: uuid
        phoneNumber:
          type: string
        role:
          type: string
        joinedAt:
          type:
            - string
            - null
          format: date-time
    HouseholdResponse:
      type: object
      required:
        - id
        - name
        - ownerId
        - members
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        ownerId:
          type: string
          format: uuid
        createdAt:
          type:
            - string
            - null
          format: date-time
        members:
          type: array
          items:
            $ref: "#/components/schemas/HouseholdMemberResponse"
    CashPositionResponse:
      type: object
      required:
        - balance
        - dailyLimit
        - txnLimit
        - todaySpend
      properties:
        balance:
          type: number
        dailyLimit:
          type: number
        txnLimit:
          type: number
        todaySpend:
          type: number
    AgentPaymentRequest:
      type: object
      required:
        - customerPhone
        - billerId
        - accountReference
        - amount
        - cashReceived
      properties:
        customerPhone:
          type: string
        billerId:
          type: string
          format: uuid
        railId:
          type:
            - string
            - null
          format: uuid
        railCode:
          type:
            - string
            - null
        accountReference:
          type: string
        amount:
          type: number
          minimum: 0.01
        cashReceived:
          type: number
          minimum: 0.01
    AdminMetric:
      type: object
      required:
        - label
        - value
      properties:
        label:
          type: string
        value:
          oneOf:
            - 
              type: string
            - 
              type: number
        tone:
          type:
            - string
            - null
          enum:
            - danger
            - neutral
            - success
            - warning
            - null
    AdminBillerRequest:
      type: object
      properties:
        categoryId:
          type:
            - string
            - null
          format: uuid
        name:
          type:
            - string
            - null
        slug:
          type:
            - string
            - null
        integrationType:
          type:
            - string
            - null
        verified:
          type:
            - boolean
            - null
        feeFixed:
          type:
            - number
            - null
        feePercent:
          type:
            - number
            - null
        postingSlaHours:
          type:
            - integer
            - null
        supportedRails:
          type:
            - array
            - null
          items:
            type: string
        status:
          type:
            - string
            - null
    AdminCategoryRequest:
      type: object
      properties:
        name:
          type:
            - string
            - null
        slug:
          type:
            - string
            - null
        iconKey:
          type:
            - string
            - null
        displayOrder:
          type:
            - integer
            - null
    AdminRailRequest:
      type: object
      properties:
        code:
          type:
            - string
            - null
        displayName:
          type:
            - string
            - null
        minAmount:
          type:
            - number
            - null
        maxAmount:
          type:
            - number
            - null
        active:
          type:
            - boolean
            - null
    AdminUserRoleRequest:
      type: object
      required:
        - role
      properties:
        role:
          type: string
          enum:
            - CUSTOMER
            - AGENT
            - ADMIN
            - COMPLIANCE
    AdminUserResponse:
      type: object
      required:
        - id
        - phoneNumber
        - role
        - kycTier
        - active
      properties:
        id:
          type: string
          format: uuid
        phoneNumber:
          type: string
        fullName:
          type:
            - string
            - null
        role:
          type: string
          enum:
            - CUSTOMER
            - AGENT
            - ADMIN
            - COMPLIANCE
        kycTier:
          type: integer
        active:
          type: boolean
    AdminUserPage:
      type: object
      required:
        - content
        - totalElements
        - page
      properties:
        content:
          type: array
          items:
            $ref: "#/components/schemas/AdminUserResponse"
        totalElements:
          type: integer
          format: int64
        page:
          type: integer
    FunnelMetricsResponse:
      type: object
      required:
        - searchCount
        - selectCount
        - confirmCount
        - payCount
        - successCount
        - failCount
        - repeatRate
      properties:
        searchCount:
          type: integer
          format: int64
        selectCount:
          type: integer
          format: int64
        confirmCount:
          type: integer
          format: int64
        payCount:
          type: integer
          format: int64
        successCount:
          type: integer
          format: int64
        failCount:
          type: integer
          format: int64
        repeatRate:
          type: number
    ReconciliationResponse:
      type: object
      required:
        - summary
        - rows
      properties:
        summary:
          type: object
          additionalProperties:
            type: number
        rows:
          type: array
          items:
            type: object
    MerchantRegisterRequest:
      type: object
      required:
        - legalName
        - registrationNo
        - contactEmail
        - contactPhone
        - ownerFullName
        - ownerPhoneNumber
        - ownerPin
      properties:
        legalName:
          type: string
        tradingName:
          type:
            - string
            - null
        registrationNo:
          type: string
        contactEmail:
          type: string
          format: email
        contactPhone:
          type: string
        ownerFullName:
          type: string
          maxLength: 180
        ownerPhoneNumber:
          type: string
          maxLength: 24
        ownerPin:
          type: string
          pattern: "^\\d{6}$"
          writeOnly: true
        submitterEmail:
          type: string
          format: email
        legalStructure:
          type: string
        businessModel:
          type: array
          items:
            type: string
        vatNumber:
          type: string
        website:
          type: string
        country:
          type: string
        province:
          type: string
        city:
          type: string
        suburb:
          type: string
        streetAddress:
          type: string
        operatingAddress:
          type: string
        postalAddress:
          type: string
        supportPhone:
          type: string
        payoutPreference:
          type: string
        bankName:
          type: string
        accountName:
          type: string
        accountNumber:
          type: string
        settlementCurrency:
          type: string
        expectedMonthlyVolume:
          type: string
        highestTransaction:
          type: string
        productsSold:
          type: string
        riskNote:
          type: string
        certificateOfIncorporation:
          type: string
        taxClearance:
          type: string
        directorsId:
          type: string
        proofOfAddress:
          type: string
        bankAccountLetter:
          type: string
    MerchantLoginRequest:
      type: object
      required:
        - phoneNumber
        - pin
      properties:
        phoneNumber:
          type: string
          maxLength: 24
        pin:
          type: string
          pattern: "^\\d{6}$"
        merchantId:
          type:
            - string
            - null
          format: uuid
    MerchantInvitationAcceptRequest:
      type: object
      required:
        - phoneNumber
        - pin
      properties:
        phoneNumber:
          type: string
          pattern: "^\\+263\\d{9}$"
        pin:
          type: string
          pattern: "^\\d{6}$"
    MerchantMeResponse:
      type: object
      required:
        - userId
        - merchantId
        - merchantName
        - role
      properties:
        userId:
          type: string
          format: uuid
        merchantId:
          type: string
          format: uuid
        merchantName:
          type: string
        role:
          type: string
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
    MerchantMembershipResponse:
      type: object
      required:
        - merchantId
        - merchantName
        - role
        - status
      properties:
        merchantId:
          type: string
          format: uuid
        merchantName:
          type: string
        role:
          type: string
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
        status:
          type: string
          enum:
            - ACTIVE
            - PENDING
            - REVOKED
    MerchantInvitationRequest:
      type: object
      required:
        - email
        - role
      properties:
        email:
          type: string
          format: email
        role:
          type: string
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
    MerchantTeamRoleRequest:
      type: object
      required:
        - role
      properties:
        role:
          type: string
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
    MerchantInvitationResponse:
      type: object
      required:
        - id
        - email
        - role
        - status
        - expiresAt
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        role:
          type: string
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
        status:
          type: string
          enum:
            - PENDING
            - ACCEPTED
            - REVOKED
            - EXPIRED
        expiresAt:
          type: string
          format: date-time
    MerchantTeamMemberResponse:
      type: object
      required:
        - id
        - userId
        - phoneNumber
        - role
        - status
      properties:
        id:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        phoneNumber:
          type: string
        fullName:
          type:
            - string
            - null
        role:
          type: string
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
        status:
          type: string
          enum:
            - ACTIVE
            - PENDING
            - REVOKED
    MerchantAuditLogPageResponse:
      type: object
      required:
        - items
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/MerchantAuditLogResponse"
        nextCursor:
          type:
            - string
            - null
    MerchantAuditLogResponse:
      type: object
      required:
        - id
        - merchantId
        - action
        - resourceType
        - occurredAt
      properties:
        id:
          type: integer
          format: int64
        merchantId:
          type: string
          format: uuid
        actorType:
          type:
            - string
            - null
          enum:
            - USER
            - API_KEY
            - null
        actorId:
          type:
            - string
            - null
          format: uuid
        actorRole:
          type:
            - string
            - null
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
            - null
        action:
          type: string
        resourceType:
          type:
            - string
            - null
        resourceId:
          type:
            - string
            - null
          format: uuid
        occurredAt:
          type: string
          format: date-time
    MerchantOriginRequest:
      type: object
      required:
        - origin
        - verificationMethod
      properties:
        origin:
          type: string
          maxLength: 255
          example: https://shop.acme.co.zw
        label:
          type:
            - string
            - null
          maxLength: 120
        verificationMethod:
          $ref: "#/components/schemas/MerchantOriginVerificationMethod"
    MerchantOriginResponse:
      type: object
      required:
        - id
        - origin
        - label
        - verified
        - verificationMethod
        - verificationPayload
      properties:
        id:
          type: string
          format: uuid
        origin:
          type: string
          example: https://shop.acme.co.zw
        label:
          type: string
        verified:
          type: boolean
        verificationMethod:
          $ref: "#/components/schemas/MerchantOriginVerificationMethod"
        verificationPayload:
          type: string
          example: "billie-verify=token"
        createdAt:
          type:
            - string
            - null
          format: date-time
        verifiedAt:
          type:
            - string
            - null
          format: date-time
    MerchantOriginVerificationMethod:
      type: string
      enum:
        - DNS_TXT
        - HTML
    MerchantResponse:
      type: object
      required:
        - id
        - legalName
        - registrationNo
        - contactEmail
        - contactPhone
        - kybStatus
        - feeFixed
        - feePercent
        - reservePercent
        - reserveReleaseDays
        - payoutThreshold
        - workspaceMode
        - dashboardUrl
      properties:
        id:
          type: string
          format: uuid
        legalName:
          type: string
        tradingName:
          type:
            - string
            - null
        registrationNo:
          type: string
        contactEmail:
          type: string
        contactPhone:
          type: string
        coreBillerId:
          type:
            - string
            - null
          format: uuid
        kybStatus:
          type: string
          enum:
            - PENDING
            - UNDER_REVIEW
            - APPROVED
            - REJECTED
            - SUSPENDED
        feeFixed:
          type: number
        feePercent:
          type: number
        reservePercent:
          type: number
        reserveReleaseDays:
          type: integer
        payoutThreshold:
          type: number
        ownerUserId:
          type:
            - string
            - null
          format: uuid
        ownerPhoneNumber:
          type:
            - string
            - null
        ownerRole:
          type:
            - string
            - null
          enum:
            - MERCHANT_OWNER
            - MERCHANT_ADMIN
            - MERCHANT_DEVELOPER
            - MERCHANT_FINANCE
            - MERCHANT_VIEWER
            - null
        workspaceMode:
          type: string
          enum:
            - SANDBOX
            - LIVE
        dashboardUrl:
          type: string
        onboardingDetails:
          type: object
          additionalProperties: true
        applicationToken:
          type:
            - string
            - null
          description: One-time onboarding continuation token returned only by merchant registration.
    MerchantKybDocumentResponse:
      type: object
      required:
        - id
        - merchantId
        - documentType
        - storageKey
        - status
      properties:
        id:
          type: string
          format: uuid
        merchantId:
          type: string
          format: uuid
        documentType:
          type: string
          enum:
            - CERTIFICATE_OF_INCORPORATION
            - TAX_CLEARANCE
            - DIRECTORS_ID
            - PROOF_OF_ADDRESS
            - BANK_ACCOUNT_LETTER
        storageKey:
          type: string
        status:
          type: string
          enum:
            - RECEIVED
            - UNDER_REVIEW
            - REJECTED
            - APPROVED
    MerchantKybRequest:
      type: object
      required:
        - kybStatus
      properties:
        kybStatus:
          type: string
          enum:
            - PENDING
            - UNDER_REVIEW
            - APPROVED
            - REJECTED
            - SUSPENDED
        coreBillerId:
          type:
            - string
            - null
          format: uuid
    MerchantApiKeyRequest:
      type: object
      properties:
        label:
          type:
            - string
            - null
        mode:
          $ref: "#/components/schemas/MerchantApiKeyMode"
    MerchantApiKeyResponse:
      type: object
      required:
        - apiKey
        - keyPrefix
        - mode
      properties:
        apiKey:
          type: string
        keyPrefix:
          type: string
        label:
          type:
            - string
            - null
        mode:
          $ref: "#/components/schemas/MerchantApiKeyMode"
    MerchantApiKeySummaryResponse:
      type: object
      required:
        - id
        - keyPrefix
        - mode
        - active
      properties:
        id:
          type: string
          format: uuid
        keyPrefix:
          type: string
        label:
          type:
            - string
            - null
        mode:
          $ref: "#/components/schemas/MerchantApiKeyMode"
        active:
          type: boolean
        lastUsedAt:
          type:
            - string
            - null
          format: date-time
    MerchantApiKeyMode:
      type: string
      enum:
        - TEST
        - LIVE
    MerchantPricingRequest:
      type: object
      properties:
        feeFixed:
          type:
            - number
            - null
        feePercent:
          type:
            - number
            - null
        reservePercent:
          type:
            - number
            - null
        reserveReleaseDays:
          type:
            - integer
            - null
        payoutThreshold:
          type:
            - number
            - null
    MerchantSettlementAccountRequest:
      type: object
      required:
        - accountType
        - currency
      properties:
        accountType:
          type: string
        bankName:
          type:
            - string
            - null
        accountNumber:
          type:
            - string
            - null
        mobileNumber:
          type:
            - string
            - null
        currency:
          type: string
    MerchantPaymentLinkRequest:
      type: object
      required:
        - title
        - amount
      properties:
        title:
          type: string
        description:
          type:
            - string
            - null
        amount:
          type: number
          minimum: 0.01
        currency:
          type: string
          default: USD
        successUrl:
          type:
            - string
            - null
        cancelUrl:
          type:
            - string
            - null
    MerchantPaymentLinkResponse:
      type: object
      required:
        - id
        - slug
        - title
        - amount
        - currency
        - checkoutUrl
      properties:
        id:
          type: string
          format: uuid
        slug:
          type: string
        title:
          type: string
        amount:
          type: number
        currency:
          type: string
        checkoutUrl:
          type: string
    MerchantCheckoutSessionRequest:
      type: object
      required:
        - merchantReference
        - title
        - amount
      properties:
        merchantReference:
          type: string
        title:
          type: string
        description:
          type:
            - string
            - null
        amount:
          type: number
          minimum: 0.01
        currency:
          type: string
          default: USD
        successUrl:
          type:
            - string
            - null
        cancelUrl:
          type:
            - string
            - null
        expiresInMinutes:
          type:
            - integer
            - null
    MerchantCheckoutSessionResponse:
      type: object
      required:
        - id
        - token
        - merchantName
        - merchantReference
        - title
        - amount
        - currency
        - status
        - checkoutUrl
        - expiresAt
      properties:
        id:
          type: string
          format: uuid
        token:
          type: string
        merchantName:
          type: string
        merchantReference:
          type: string
        title:
          type: string
        description:
          type:
            - string
            - null
        amount:
          type: number
        currency:
          type: string
        status:
          type: string
          enum:
            - CREATED
            - PAID
            - EXPIRED
            - CANCELLED
            - REFUNDED
        checkoutUrl:
          type: string
        expiresAt:
          type: string
          format: date-time
    MerchantCheckoutPayRequest:
      type: object
      properties:
        railCode:
          type: string
          default: BANK_TRANSFER
    MerchantPaymentResponse:
      type: object
      required:
        - paymentId
        - checkoutSessionId
        - paymentTransactionId
        - status
        - amount
        - fee
        - reserve
        - netAmount
        - currency
      properties:
        paymentId:
          type: string
          format: uuid
        checkoutSessionId:
          type: string
          format: uuid
        paymentTransactionId:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - PAID
            - REFUNDED
        amount:
          type: number
        fee:
          type: number
        reserve:
          type: number
        netAmount:
          type: number
        currency:
          type: string
    MerchantPaymentListItemResponse:
      type: object
      required:
        - id
        - checkoutSessionId
        - merchantReference
        - status
        - railCode
        - amount
        - currency
      properties:
        id:
          type: string
          format: uuid
        checkoutSessionId:
          type: string
          format: uuid
        merchantReference:
          type: string
        status:
          type: string
          enum:
            - PAID
            - REFUNDED
        railCode:
          type: string
        amount:
          type: number
        currency:
          type: string
        createdAt:
          type:
            - string
            - null
          format: date-time
    MerchantPaymentDetailResponse:
      type: object
      required:
        - id
        - checkoutSessionId
        - merchantReference
        - status
        - railCode
        - amount
        - fee
        - reserve
        - netAmount
        - currency
      properties:
        id:
          type: string
          format: uuid
        checkoutSessionId:
          type: string
          format: uuid
        merchantReference:
          type: string
        status:
          type: string
          enum:
            - PAID
            - REFUNDED
        railCode:
          type: string
        railReference:
          type:
            - string
            - null
        amount:
          type: number
        fee:
          type: number
        reserve:
          type: number
        netAmount:
          type: number
        currency:
          type: string
        createdAt:
          type:
            - string
            - null
          format: date-time
    MerchantPaymentPageResponse:
      type: object
      required:
        - items
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/MerchantPaymentListItemResponse"
        nextCursor:
          type:
            - string
            - null
    MerchantRefundListItemResponse:
      type: object
      required:
        - id
        - paymentId
        - merchantReference
        - amount
        - currency
        - status
      properties:
        id:
          type: string
          format: uuid
        paymentId:
          type: string
          format: uuid
        merchantReference:
          type: string
        amount:
          type: number
        currency:
          type: string
        status:
          type: string
          enum:
            - COMPLETED
        reason:
          type:
            - string
            - null
        createdAt:
          type:
            - string
            - null
          format: date-time
    MerchantRefundPageResponse:
      type: object
      required:
        - items
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/MerchantRefundListItemResponse"
        nextCursor:
          type:
            - string
            - null
    MerchantBrandingRequest:
      type: object
      properties:
        logoUrl:
          type:
            - string
            - null
          maxLength: 2048
        brandColor:
          type:
            - string
            - null
          pattern: "^#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$"
        receiptFrom:
          type:
            - string
            - null
          maxLength: 120
        receiptFooter:
          type:
            - string
            - null
          maxLength: 1000
    MerchantBrandingResponse:
      type: object
      required:
        - merchantId
        - receiptFrom
      properties:
        merchantId:
          type: string
          format: uuid
        logoUrl:
          type:
            - string
            - null
        brandColor:
          type:
            - string
            - null
        receiptFrom:
          type: string
        receiptFooter:
          type:
            - string
            - null
        updatedAt:
          type:
            - string
            - null
          format: date-time
    MerchantReceiptDeliveryResponse:
      type: object
      required:
        - paymentId
        - status
        - receiptFrom
      properties:
        paymentId:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - QUEUED
        recipientPhone:
          type:
            - string
            - null
        receiptFrom:
          type: string
    MerchantBulkReceiptResendRequest:
      type: object
      required:
        - paymentIds
      properties:
        paymentIds:
          type: array
          minItems: 1
          maxItems: 100
          items:
            type: string
            format: uuid
    MerchantBulkReceiptResendResponse:
      type: object
      required:
        - deliveries
      properties:
        deliveries:
          type: array
          items:
            $ref: "#/components/schemas/MerchantReceiptDeliveryResponse"
    MerchantDashboardEventResponse:
      type: object
      required:
        - id
        - type
        - merchantId
        - resourceId
        - occurredAt
        - data
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          examples:
            - payment.created
            - payment.succeeded
        merchantId:
          type: string
          format: uuid
        resourceId:
          type: string
          format: uuid
        occurredAt:
          type: string
          format: date-time
        data:
          type: object
          additionalProperties: true
    MerchantAnalyticsOverviewResponse:
      type: object
      required:
        - range
        - totalVolume
        - netVolume
        - paymentCount
        - refundCount
        - refundVolume
        - averageTicket
        - generatedAt
      properties:
        range:
          type: string
        totalVolume:
          type: number
        netVolume:
          type: number
        paymentCount:
          type: integer
          format: int64
        refundCount:
          type: integer
          format: int64
        refundVolume:
          type: number
        averageTicket:
          type: number
        generatedAt:
          type: string
          format: date-time
    MerchantAnalyticsPoint:
      type: object
      required:
        - bucket
        - value
        - count
      properties:
        bucket:
          type: string
        value:
          type: number
        count:
          type: integer
          format: int64
    MerchantAnalyticsTimeseriesResponse:
      type: object
      required:
        - metric
        - bucket
        - points
      properties:
        metric:
          type: string
        bucket:
          type: string
          enum:
            - hour
            - day
        points:
          type: array
          items:
            $ref: "#/components/schemas/MerchantAnalyticsPoint"
    MerchantRailMixItem:
      type: object
      required:
        - railCode
        - volume
        - paymentCount
        - share
      properties:
        railCode:
          type: string
        volume:
          type: number
        paymentCount:
          type: integer
          format: int64
        share:
          type: number
    MerchantRailMixResponse:
      type: object
      required:
        - rails
      properties:
        rails:
          type: array
          items:
            $ref: "#/components/schemas/MerchantRailMixItem"
    MerchantFunnelResponse:
      type: object
      required:
        - checkoutSessionCount
        - paidSessionCount
        - expiredSessionCount
        - conversionRate
      properties:
        checkoutSessionCount:
          type: integer
          format: int64
        paidSessionCount:
          type: integer
          format: int64
        expiredSessionCount:
          type: integer
          format: int64
        conversionRate:
          type: number
    MerchantTopCustomerItem:
      type: object
      required:
        - customerId
        - customerPhone
        - volume
        - paymentCount
      properties:
        customerId:
          type: string
          format: uuid
        customerPhone:
          type: string
        volume:
          type: number
        paymentCount:
          type: integer
          format: int64
    MerchantTopCustomersResponse:
      type: object
      required:
        - customers
      properties:
        customers:
          type: array
          items:
            $ref: "#/components/schemas/MerchantTopCustomerItem"
    MerchantPayoutScheduleItem:
      type: object
      required:
        - payoutId
        - scheduledFor
        - amount
        - currency
        - status
      properties:
        payoutId:
          type: string
          format: uuid
        scheduledFor:
          type: string
          format: date
        amount:
          type: number
        currency:
          type: string
        status:
          type: string
          enum:
            - PENDING
            - SENT
            - FAILED
    MerchantPayoutScheduleResponse:
      type: object
      required:
        - payouts
      properties:
        payouts:
          type: array
          items:
            $ref: "#/components/schemas/MerchantPayoutScheduleItem"
    MerchantHealthResponse:
      type: object
      required:
        - webhookDeliverySuccessRate24h
        - checkoutSuccessRate24h
        - payoutBacklog
        - refundBacklog
        - lastSuccessfulPayoutAt
        - generatedAt
      properties:
        webhookDeliverySuccessRate24h:
          type: number
        checkoutSuccessRate24h:
          type: number
        payoutBacklog:
          type: integer
          format: int64
        refundBacklog:
          type: integer
          format: int64
        lastSuccessfulPayoutAt:
          type:
            - string
            - null
          format: date-time
        generatedAt:
          type: string
          format: date-time
    MerchantStatementResponse:
      type: object
      required:
        - id
        - merchantId
        - periodStart
        - periodEnd
        - totalVolume
        - refundVolume
        - payoutTotal
        - paymentCount
        - refundCount
        - payoutCount
        - recipientCount
        - generatedAt
      properties:
        id:
          type: string
          format: uuid
        merchantId:
          type: string
          format: uuid
        periodStart:
          type: string
          format: date
        periodEnd:
          type: string
          format: date
        totalVolume:
          type: number
        refundVolume:
          type: number
        payoutTotal:
          type: number
        paymentCount:
          type: integer
          format: int64
        refundCount:
          type: integer
          format: int64
        payoutCount:
          type: integer
          format: int64
        recipientCount:
          type: integer
        generatedAt:
          type: string
          format: date-time
    MerchantStatementPageResponse:
      type: object
      required:
        - items
        - page
        - size
        - total
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/MerchantStatementResponse"
        page:
          type: integer
        size:
          type: integer
        total:
          type: integer
          format: int64
    MerchantRiskTierRequest:
      type: object
      required:
        - riskTier
      properties:
        riskTier:
          type: string
          enum:
            - LOW
            - STANDARD
            - ELEVATED
            - HIGH
    MerchantVelocityCapsRequest:
      type: object
      properties:
        maxTxnAmount:
          type:
            - number
            - null
          minimum: 0.01
        maxDailyVolume:
          type:
            - number
            - null
          minimum: 0.01
        maxMonthlyVolume:
          type:
            - number
            - null
          minimum: 0.01
    MerchantRiskProfileResponse:
      type: object
      required:
        - merchantId
        - riskTier
        - updatedAt
      properties:
        merchantId:
          type: string
          format: uuid
        riskTier:
          type: string
          enum:
            - LOW
            - STANDARD
            - ELEVATED
            - HIGH
        maxTxnAmount:
          type:
            - number
            - null
        maxDailyVolume:
          type:
            - number
            - null
        maxMonthlyVolume:
          type:
            - number
            - null
        updatedAt:
          type: string
          format: date-time
    MerchantRiskLimitsResponse:
      type: object
      required:
        - riskTier
      properties:
        riskTier:
          type: string
          enum:
            - LOW
            - STANDARD
            - ELEVATED
            - HIGH
        maxTxnAmount:
          type:
            - number
            - null
        maxDailyVolume:
          type:
            - number
            - null
        maxMonthlyVolume:
          type:
            - number
            - null
        remainingDailyVolume:
          type:
            - number
            - null
        remainingMonthlyVolume:
          type:
            - number
            - null
    MerchantRiskKpiResponse:
      type: object
      required:
        - day
        - volume
        - txnCount
      properties:
        day:
          type: string
          format: date
        volume:
          type: number
        txnCount:
          type: integer
        successRate:
          type:
            - number
            - null
        refundRate:
          type:
            - number
            - null
        chargebackRate:
          type:
            - number
            - null
        disputeRate:
          type:
            - number
            - null
        fraudRate:
          type:
            - number
            - null
    MerchantWebhookRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          format: uri
        secret:
          type:
            - string
            - null
    MerchantWebhookResponse:
      type: object
      required:
        - configured
        - hasSigningSecret
      properties:
        url:
          type:
            - string
            - null
        configured:
          type: boolean
        hasSigningSecret:
          type: boolean
    MerchantWebhookSecretResponse:
      type: object
      required:
        - url
        - signingSecret
      properties:
        url:
          type: string
          format: uri
        signingSecret:
          type: string
    MerchantWebhookEndpointRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          format: uri
        description:
          type:
            - string
            - null
        subscribedEvents:
          type:
            - array
            - null
          items:
            type: string
        mode:
          type:
            - string
            - null
          enum:
            - TEST
            - LIVE
            - null
    MerchantWebhookEndpointResponse:
      type: object
      required:
        - id
        - url
        - subscribedEvents
        - mode
        - active
        - hasSigningSecret
      properties:
        id:
          type: string
          format: uuid
        url:
          type: string
          format: uri
        description:
          type:
            - string
            - null
        subscribedEvents:
          type: array
          items:
            type: string
        mode:
          type: string
          enum:
            - TEST
            - LIVE
        active:
          type: boolean
        hasSigningSecret:
          type: boolean
        lastSucceededAt:
          type:
            - string
            - null
          format: date-time
        createdAt:
          type:
            - string
            - null
          format: date-time
    MerchantWebhookEndpointSecretResponse:
      type: object
      required:
        - id
        - url
        - subscribedEvents
        - mode
        - signingSecret
      properties:
        id:
          type: string
          format: uuid
        url:
          type: string
          format: uri
        description:
          type:
            - string
            - null
        subscribedEvents:
          type: array
          items:
            type: string
        mode:
          type: string
          enum:
            - TEST
            - LIVE
        signingSecret:
          type: string
    MerchantWebhookDeliveryResponse:
      type: object
      required:
        - id
        - eventType
        - status
        - attemptCount
      properties:
        id:
          type: string
          format: uuid
        eventType:
          type: string
        status:
          type: string
          enum:
            - PENDING
            - SKIPPED
            - DELIVERED
            - FAILED
            - EXHAUSTED
        attemptCount:
          type: integer
        responseCode:
          type:
            - integer
            - null
        nextRetryAt:
          type:
            - string
            - null
          format: date-time
        createdAt:
          type:
            - string
            - null
          format: date-time
    WebhookEventResponse:
      type: object
      required:
        - eventType
        - description
      properties:
        eventType:
          type: string
        description:
          type: string
    MerchantLedgerBalance:
      type: object
      required:
        - currency
        - cash
        - available
        - reserve
        - feeRevenue
        - payoutClearing
        - refundClearing
      properties:
        currency:
          type: string
        cash:
          type: number
        available:
          type: number
        reserve:
          type: number
        feeRevenue:
          type: number
        payoutClearing:
          type: number
        refundClearing:
          type: number
    MerchantReconciliationRow:
      allOf:
        - 
          $ref: "#/components/schemas/MerchantLedgerBalance"
        - 
          type: object
          required:
            - merchantId
            - merchantName
          properties:
            merchantId:
              type: string
              format: uuid
            merchantName:
              type: string
    MerchantPayoutResponse:
      type: object
      required:
        - id
        - merchantId
        - amount
        - currency
        - status
      properties:
        id:
          type: string
          format: uuid
        merchantId:
          type: string
          format: uuid
        amount:
          type: number
        currency:
          type: string
        status:
          type: string
          enum:
            - PENDING
            - SENT
            - FAILED
        railReference:
          type:
            - string
            - null
        failureReason:
          type:
            - string
            - null
        scheduledFor:
          type:
            - string
            - null
          format: date
        sentAt:
          type:
            - string
            - null
          format: date-time
    MerchantRefundRequest:
      type: object
      required:
        - paymentId
        - amount
      properties:
        paymentId:
          type: string
          format: uuid
        amount:
          type: number
        reason:
          type:
            - string
            - null
    MerchantRefundResponse:
      type: object
      required:
        - id
        - amount
        - currency
        - status
      properties:
        id:
          type: string
          format: uuid
        amount:
          type: number
        currency:
          type: string
        status:
          type: string
          enum:
            - COMPLETED
    DeveloperSignupRequest:
      type: object
      required:
        - email
        - fullName
        - companyName
      properties:
        email:
          type: string
          format: email
        fullName:
          type: string
        companyName:
          type: string
    DeveloperSignupResponse:
      type: object
      required:
        - developerId
        - status
        - emailVerified
        - emailVerificationCode
      properties:
        developerId:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - PENDING_EMAIL_VERIFICATION
            - ACTIVE
            - SUSPENDED
        emailVerified:
          type: boolean
        emailVerificationCode:
          type: string
    DeveloperVerifyEmailRequest:
      type: object
      required:
        - developerId
        - code
      properties:
        developerId:
          type: string
          format: uuid
        code:
          type: string
    DeveloperApiKeyResponse:
      type: object
      required:
        - apiKey
        - keyPrefix
        - environment
      properties:
        apiKey:
          type: string
        keyPrefix:
          type: string
        environment:
          type: string
          enum:
            - SANDBOX
            - LIVE
    DeveloperProfileResponse:
      type: object
      required:
        - id
        - email
        - fullName
        - companyName
        - emailVerified
        - status
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        fullName:
          type: string
        companyName:
          type: string
        emailVerified:
          type: boolean
        status:
          type: string
          enum:
            - PENDING_EMAIL_VERIFICATION
            - ACTIVE
            - SUSPENDED
        sandboxMerchantId:
          type:
            - string
            - null
          format: uuid
    DeveloperStatusRequest:
      type: object
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - PENDING_EMAIL_VERIFICATION
            - ACTIVE
            - SUSPENDED
    DeveloperCheckoutSessionRequest:
      type: object
      required:
        - merchantReference
        - title
        - amount
      properties:
        merchantReference:
          type: string
        title:
          type: string
        description:
          type:
            - string
            - null
        amount:
          type: number
          minimum: 0.01
        currency:
          type: string
          default: USD
    DeveloperExplorerRunRequest:
      type: object
      required:
        - endpoint
      properties:
        endpoint:
          type: string
        merchantReference:
          type:
            - string
            - null
        amount:
          type:
            - number
            - null
        currency:
          type:
            - string
            - null
    DeveloperExplorerRunResponse:
      type: object
      required:
        - runId
        - statusCode
        - endpoint
        - requestPayload
        - responsePayload
        - checkoutToken
      properties:
        runId:
          type: string
          format: uuid
        statusCode:
          type: integer
        endpoint:
          type: string
        requestPayload:
          type: string
        responsePayload:
          type: string
        checkoutToken:
          type: string
    DeveloperWebhookSignatureRequest:
      type: object
      required:
        - payload
        - secret
      properties:
        payload:
          type: string
        secret:
          type: string
    DeveloperWebhookSignatureResponse:
      type: object
      required:
        - signature
        - timestamp
        - headerName
      properties:
        signature:
          type: string
        timestamp:
          type: string
        headerName:
          type: string
    DeveloperIntegrationRequest:
      type: object
      required:
        - type
        - storeUrl
      properties:
        type:
          type: string
          enum:
            - WOOCOMMERCE
            - OPENCART
            - ZAPIER
            - WHATSAPP
        storeUrl:
          type: string
    DeveloperIntegrationResponse:
      type: object
      required:
        - id
        - type
        - storeUrl
        - status
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - WOOCOMMERCE
            - OPENCART
            - ZAPIER
            - WHATSAPP
        storeUrl:
          type: string
        status:
          type: string
          enum:
            - CONFIGURED
            - TEST_PAYMENT_PAID
            - DISABLED
        lastTestOrderId:
          type:
            - string
            - null
    DeveloperPluginTestOrderResponse:
      type: object
      required:
        - integrationId
        - orderId
        - orderStatus
        - checkoutToken
      properties:
        integrationId:
          type: string
          format: uuid
        orderId:
          type: string
        orderStatus:
          type: string
          enum:
            - PAID
        checkoutToken:
          type: string
    WalletAmountRequest:
      type: object
      required:
        - amount
      properties:
        amount:
          type: number
          minimum: 0.01
        currency:
          type: string
          default: USD
    WalletResponse:
      type: object
      required:
        - id
        - currency
        - availableBalance
        - savingsBalance
        - status
      properties:
        id:
          type: string
          format: uuid
        currency:
          type: string
        availableBalance:
          type: number
        savingsBalance:
          type: number
        status:
          type: string
          enum:
            - ACTIVE
            - FROZEN
            - CLOSED
    VirtualCardRequest:
      type: object
      required:
        - spendLimit
      properties:
        spendLimit:
          type: number
          minimum: 1
        currency:
          type: string
          default: USD
    VirtualCardResponse:
      type: object
      required:
        - id
        - token
        - last4
        - currency
        - spendLimit
        - spentAmount
        - status
      properties:
        id:
          type: string
          format: uuid
        token:
          type: string
        last4:
          type: string
        currency:
          type: string
        spendLimit:
          type: number
        spentAmount:
          type: number
        status:
          type: string
          enum:
            - ACTIVE
            - FROZEN
            - CANCELLED
        createdAt:
          type:
            - string
            - null
          format: date-time
    OpenBankingConsentRequest:
      type: object
      required:
        - bankName
        - accountMask
      properties:
        bankName:
          type: string
        accountMask:
          type: string
    OpenBankingConsentResponse:
      type: object
      required:
        - id
        - bankName
        - accountMask
        - status
        - expiresAt
      properties:
        id:
          type: string
          format: uuid
        bankName:
          type: string
        accountMask:
          type: string
        status:
          type: string
          enum:
            - ACTIVE
            - REVOKED
            - EXPIRED
        expiresAt:
          type: string
          format: date-time
    UssdSessionRequest:
      type: object
      required:
        - flow
      properties:
        flow:
          type: string
        statePayload:
          type:
            - string
            - null
    UssdSessionResponse:
      type: object
      required:
        - id
        - phoneNumber
        - flow
        - status
        - statePayload
        - expiresAt
      properties:
        id:
          type: string
          format: uuid
        phoneNumber:
          type: string
        flow:
          type: string
        status:
          type: string
          enum:
            - ACTIVE
            - COMPLETED
            - EXPIRED
        statePayload:
          type: string
        expiresAt:
          type: string
          format: date-time
    AdvanceDrawRequest:
      type: object
      required:
        - amount
      properties:
        amount:
          type: number
          minimum: 1
    MerchantAdvanceOfferResponse:
      type: object
      required:
        - id
        - approvedAmount
        - outstandingAmount
        - currency
        - repaymentPercent
        - status
      properties:
        id:
          type: string
          format: uuid
        approvedAmount:
          type: number
        outstandingAmount:
          type: number
        currency:
          type: string
        repaymentPercent:
          type: number
        status:
          type: string
          enum:
            - OFFERED
            - ACTIVE
            - REPAID
            - DECLINED
    PlatformSubMerchantRequest:
      type: object
      required:
        - subMerchantId
        - externalAccountRef
        - displayName
      properties:
        subMerchantId:
          type: string
          format: uuid
        externalAccountRef:
          type: string
        displayName:
          type: string
    PlatformSubMerchantResponse:
      type: object
      required:
        - id
        - subMerchantId
        - externalAccountRef
        - displayName
        - status
      properties:
        id:
          type: string
          format: uuid
        subMerchantId:
          type: string
          format: uuid
        externalAccountRef:
          type: string
        displayName:
          type: string
        status:
          type: string
    PlatformSplitRuleRequest:
      type: object
      required:
        - subMerchantLinkId
        - splitPercent
      properties:
        subMerchantLinkId:
          type: string
          format: uuid
        splitPercent:
          type: number
          minimum: 0.0001
          maximum: 1
    PlatformSplitRuleResponse:
      type: object
      required:
        - id
        - subMerchantLinkId
        - splitPercent
        - active
      properties:
        id:
          type: string
          format: uuid
        subMerchantLinkId:
          type: string
          format: uuid
        splitPercent:
          type: number
        active:
          type: boolean
    MarketplaceAppRequest:
      type: object
      required:
        - name
        - category
        - installUrl
      properties:
        name:
          type: string
        category:
          type: string
        installUrl:
          type: string
    MarketplaceAppResponse:
      type: object
      required:
        - id
        - developerEmail
        - name
        - category
        - installUrl
        - status
      properties:
        id:
          type: string
          format: uuid
        developerEmail:
          type: string
          format: email
        name:
          type: string
        category:
          type: string
        installUrl:
          type: string
        status:
          type: string
          enum:
            - SUBMITTED
            - APPROVED
            - REJECTED
            - SUSPENDED
        createdAt:
          type:
            - string
            - null
          format: date-time
    MarketplaceReviewRequest:
      type: object
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - SUBMITTED
            - APPROVED
            - REJECTED
            - SUSPENDED
    PartnerApplicationRequest:
      type: object
      required:
        - tier
      properties:
        tier:
          type: string
          enum:
            - IMPLEMENTATION
            - TECHNOLOGY
            - AGENCY
    PartnerApplicationResponse:
      type: object
      required:
        - id
        - developerEmail
        - tier
        - status
      properties:
        id:
          type: string
          format: uuid
        developerEmail:
          type: string
          format: email
        tier:
          type: string
          enum:
            - IMPLEMENTATION
            - TECHNOLOGY
            - AGENCY
        status:
          type: string
          enum:
            - SUBMITTED
            - APPROVED
            - REJECTED
        createdAt:
          type:
            - string
            - null
          format: date-time
    PartnerReviewRequest:
      type: object
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - SUBMITTED
            - APPROVED
            - REJECTED
    EcosystemOverviewResponse:
      type: object
      required:
        - wallets
        - virtualCards
        - advanceOffers
        - marketplaceApps
        - partnerApplications
        - openBankingConsents
        - ussdSessions
      properties:
        wallets:
          type: integer
        virtualCards:
          type: integer
        advanceOffers:
          type: integer
        marketplaceApps:
          type: integer
        partnerApplications:
          type: integer
        openBankingConsents:
          type: integer
        ussdSessions:
          type: integer
    BipBillerRegisterRequest:
      type: object
      required:
        - coreBillerId
        - legalName
        - registrationNo
        - contactEmail
        - contactPhone
      properties:
        coreBillerId:
          type: string
          format: uuid
        legalName:
          type: string
        tradingName:
          type:
            - string
            - null
        registrationNo:
          type: string
        contactEmail:
          type: string
          format: email
        contactPhone:
          type: string
    BipBillerResponse:
      type: object
      required:
        - id
        - coreBillerId
        - legalName
        - displayName
        - registrationNo
        - contactEmail
        - contactPhone
        - kybStatus
      properties:
        id:
          type: string
          format: uuid
        coreBillerId:
          type: string
          format: uuid
        legalName:
          type: string
        tradingName:
          type:
            - string
            - null
        displayName:
          type: string
        registrationNo:
          type: string
        contactEmail:
          type: string
          format: email
        contactPhone:
          type: string
        kybStatus:
          type: string
          enum:
            - PENDING
            - APPROVED
            - REJECTED
            - SUSPENDED
    BipKybRequest:
      type: object
      required:
        - kybStatus
      properties:
        kybStatus:
          type: string
          enum:
            - PENDING
            - APPROVED
            - REJECTED
            - SUSPENDED
    BipKybDocumentResponse:
      type: object
      required:
        - id
        - billerId
        - documentType
        - storageKey
        - status
      properties:
        id:
          type: string
          format: uuid
        billerId:
          type: string
          format: uuid
        documentType:
          type: string
          enum:
            - CERTIFICATE_OF_INCORPORATION
            - TAX_CLEARANCE
            - DIRECTORS_ID
            - PROOF_OF_ADDRESS
            - BANK_ACCOUNT_LETTER
        storageKey:
          type: string
        status:
          type: string
          enum:
            - RECEIVED
            - UNDER_REVIEW
            - REJECTED
            - APPROVED
    BipApiKeyRequest:
      type: object
      properties:
        label:
          type:
            - string
            - null
    BipApiKeyResponse:
      type: object
      required:
        - apiKey
        - keyPrefix
      properties:
        apiKey:
          type: string
        keyPrefix:
          type: string
        label:
          type:
            - string
            - null
    BipBillPushRequest:
      type: object
      required:
        - billerBillId
        - customerRef
        - title
        - totalAmount
        - dueDate
      properties:
        billerBillId:
          type: string
        customerRef:
          type: string
        customerPhone:
          type:
            - string
            - null
        customerEmail:
          type:
            - string
            - null
          format: email
        customerName:
          type:
            - string
            - null
        nationalId:
          type:
            - string
            - null
        nationalIdCountry:
          type:
            - string
            - null
          minLength: 2
          maxLength: 2
        customerIdentifiers:
          type: object
          additionalProperties:
            type: string
        title:
          type: string
        description:
          type:
            - string
            - null
        totalAmount:
          type: number
          minimum: 0.01
        currency:
          type: string
          default: USD
        dueDate:
          type: string
          format: date
    BipBillResponse:
      type: object
      required:
        - id
        - billerId
        - billerName
        - billerBillId
        - customerRef
        - title
        - totalAmount
        - currency
        - dueDate
        - status
      properties:
        id:
          type: string
          format: uuid
        billerId:
          type: string
          format: uuid
        billerName:
          type: string
        billerBillId:
          type: string
        customerRef:
          type: string
        title:
          type: string
        totalAmount:
          type: number
        currency:
          type: string
        dueDate:
          type: string
          format: date
        status:
          type: string
          enum:
            - QUEUED
            - DELIVERED
            - CLAIMABLE
            - VIEWED
            - PAID
            - OVERDUE
            - CANCELLED
            - UNRESOLVABLE
        resolutionMethod:
          type:
            - string
            - null
        paymentTransactionId:
          type:
            - string
            - null
          format: uuid
    BipBatchPushRequest:
      type: object
      required:
        - bills
      properties:
        bills:
          type: array
          maxItems: 50000
          items:
            $ref: "#/components/schemas/BipBillPushRequest"
    BipBatchPushResponse:
      type: object
      required:
        - queued
        - delivered
        - unresolvable
      properties:
        queued:
          type: integer
        delivered:
          type: integer
        unresolvable:
          type: integer
    BipSubscriptionPlanRequest:
      type: object
      required:
        - name
        - amount
      properties:
        name:
          type: string
        amount:
          type: number
          minimum: 0.01
        currency:
          type: string
          default: USD
        gracePeriodDays:
          type: integer
          default: 3
    BipSubscriptionPlanResponse:
      type: object
      required:
        - id
        - name
        - amount
        - currency
        - gracePeriodDays
        - status
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        amount:
          type: number
        currency:
          type: string
        gracePeriodDays:
          type: integer
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
    BipSubscriptionEnrollRequest:
      type: object
      required:
        - planId
        - customerRef
      properties:
        planId:
          type: string
          format: uuid
        customerRef:
          type: string
        customerPhone:
          type:
            - string
            - null
        startDate:
          type:
            - string
            - null
          format: date
    BipSubscriptionResponse:
      type: object
      required:
        - id
        - planId
        - customerRef
        - nextBillingDate
        - status
      properties:
        id:
          type: string
          format: uuid
        planId:
          type: string
          format: uuid
        customerRef:
          type: string
        customerPhone:
          type:
            - string
            - null
        resolvedUserId:
          type:
            - string
            - null
          format: uuid
        nextBillingDate:
          type: string
          format: date
        status:
          type: string
          enum:
            - ACTIVE
            - CANCELLED
    BipSubscriptionRunResponse:
      type: object
      required:
        - generated
      properties:
        generated:
          type: integer
    AmlFlagResponse:
      type: object
      required:
        - transactionId
        - userId
        - amount
        - flagReason
      properties:
        transactionId:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        amount:
          type: number
        flagReason:
          type: string
        flaggedAt:
          type:
            - string
            - null
          format: date-time
    AmlReviewRequest:
      type: object
      required:
        - decision
      properties:
        decision:
          type: string
          enum:
            - CLEAR
            - ESCALATE
            - BLOCK
        note:
          type:
            - string
            - null
