openapi: 3.0.3
info:
  title: BlikPay Merchant App API
  version: 1.1.0
  description: Mobile (Android) authentication and merchant portal APIs for gatewayuser.
servers:
  - url: https://your-api-domain.com
    description: Production (replace with your real API domain)
  - url: http://localhost
    description: Local development
tags:
  - name: GatewayUser Auth
    description: OTP login + app session token
  - name: GatewayUser Portal
    description: Balance, transaction reports, and ledger APIs for the merchant mobile app
paths:
  /api/gatewayuser/login/request-otp:
    post:
      tags: [GatewayUser Auth]
      summary: Request login OTP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginRequestOtpRequest"
      responses:
        "200":
          description: OTP sent
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LoginRequestOtpResponse"
        "4XX":
          description: Validation or merchant access error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "5XX":
          description: Mail send or server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /api/gatewayuser/login/verify-otp:
    post:
      tags: [GatewayUser Auth]
      summary: Verify OTP and create app session
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginVerifyOtpRequest"
      responses:
        "200":
          description: Login success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LoginVerifyOtpResponse"
        "4XX":
          description: Invalid OTP / expired OTP / disabled access
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "5XX":
          description: Server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /api/gatewayuser/logout:
    post:
      tags: [GatewayUser Auth]
      summary: Logout and revoke app token
      security:
        - AppTokenHeader: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LogoutRequest"
      responses:
        "200":
          description: Logout success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LogoutResponse"
        "4XX":
          description: Invalid or missing token
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /api/gatewayuser/balance:
    get:
      tags: [GatewayUser Portal]
      summary: Check merchant balances
      security:
        - AppTokenHeader: []
      parameters:
        - $ref: "#/components/parameters/XAppPlatform"
        - $ref: "#/components/parameters/XAppVersion"
      responses:
        "200":
          description: Current wallet balances
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BalanceResponse"
        "4XX":
          description: Invalid token or merchant access error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /api/gatewayuser/transaction-reports:
    get:
      tags: [GatewayUser Portal]
      summary: Get transaction reports
      security:
        - AppTokenHeader: []
      parameters:
        - name: type
          in: query
          schema:
            type: string
            enum: [PAYIN, PAYOUT, BENEFICIARY]
        - name: status
          in: query
          schema:
            type: string
        - name: provider
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date
        - name: to
          in: query
          schema:
            type: string
            format: date
        - name: txn
          in: query
          schema:
            type: string
          description: Search by `txn:123`, `order:ABC`, `ref:XYZ`, or plain text
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/XAppPlatform"
        - $ref: "#/components/parameters/XAppVersion"
      responses:
        "200":
          description: Transaction report page
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionReportsResponse"
        "4XX":
          description: Invalid token or invalid filters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /api/gatewayuser/ledger:
    get:
      tags: [GatewayUser Portal]
      summary: Get merchant ledger entries
      security:
        - AppTokenHeader: []
      parameters:
        - name: wallet
          in: query
          schema:
            type: string
            enum: [PAYIN, PAYOUT]
        - name: type
          in: query
          schema:
            type: string
            enum: [CREDIT, DEBIT]
        - name: from
          in: query
          schema:
            type: string
            format: date
        - name: to
          in: query
          schema:
            type: string
            format: date
        - name: q
          in: query
          schema:
            type: string
          description: Search by ledger id, txn id, client ref, entry ref, or reason
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/XAppPlatform"
        - $ref: "#/components/parameters/XAppVersion"
      responses:
        "200":
          description: Ledger page with balances and recent fund requests
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LedgerResponse"
        "4XX":
          description: Invalid token or invalid filters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

components:
  securitySchemes:
    AppTokenHeader:
      type: apiKey
      in: header
      name: X-App-Token
      description: Merchant app session token returned by verify-otp

  parameters:
    Page:
      name: page
      in: query
      schema:
        type: integer
        minimum: 1
        default: 1
    Limit:
      name: limit
      in: query
      schema:
        type: integer
        enum: [25, 50, 100, 200]
        default: 50
    XAppPlatform:
      name: X-App-Platform
      in: header
      required: false
      schema:
        type: string
        example: android
    XAppVersion:
      name: X-App-Version
      in: header
      required: false
      schema:
        type: string
        example: 1.0.0

  schemas:
    LoginRequestOtpRequest:
      type: object
      additionalProperties: false
      required: [email, device_id]
      properties:
        email:
          type: string
          format: email
        device_id:
          type: string
        device_name:
          type: string
        app_platform:
          type: string
        app_version:
          type: string

    LoginRequestOtpResponse:
      type: object
      properties:
        ok:
          type: boolean
        message:
          type: string
        otp_id:
          type: integer
          format: int64
        expires_in:
          type: integer
        email:
          type: string
          format: email

    LoginVerifyOtpRequest:
      type: object
      additionalProperties: false
      required: [email, otp_id, otp, device_id]
      properties:
        email:
          type: string
          format: email
        otp_id:
          type: integer
          format: int64
        otp:
          type: string
          pattern: "^[0-9]{6}$"
        device_id:
          type: string
        device_name:
          type: string
        app_platform:
          type: string
        app_version:
          type: string

    LoginVerifyOtpResponse:
      type: object
      properties:
        ok:
          type: boolean
        message:
          type: string
        merchant:
          $ref: "#/components/schemas/MerchantProfile"
        session:
          type: object
          properties:
            app_token:
              type: string
            token_type:
              type: string
            device_id:
              type: string
            max_devices:
              type: integer

    LogoutRequest:
      type: object
      properties:
        app_token:
          type: string
          description: Optional alternative to X-App-Token header
        device_id:
          type: string
        device_name:
          type: string
        app_platform:
          type: string
        app_version:
          type: string

    LogoutResponse:
      type: object
      properties:
        ok:
          type: boolean
        message:
          type: string

    MerchantProfile:
      type: object
      properties:
        id:
          type: integer
          format: int64
        merchant_code:
          type: string
        name:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        active_from:
          type: string
          nullable: true
        active_to:
          type: string
          nullable: true

    ServicesVisibility:
      type: object
      properties:
        payin_enabled:
          type: boolean
        payout_enabled:
          type: boolean

    Balances:
      type: object
      properties:
        payout_balance:
          type: string
          example: "1000.00"
        lien_amount:
          type: string
          example: "50.00"
        available_payout_balance:
          type: string
          example: "950.00"
        payin_balance:
          type: string
          example: "0.00"
        updated_at:
          type: string
          nullable: true

    BalanceResponse:
      type: object
      properties:
        ok:
          type: boolean
        merchant:
          $ref: "#/components/schemas/MerchantProfile"
        services:
          $ref: "#/components/schemas/ServicesVisibility"
        balances:
          $ref: "#/components/schemas/Balances"

    TransactionSummary:
      type: object
      properties:
        total:
          type: integer
        total_amount:
          type: string
        success_count:
          type: integer
        pending_count:
          type: integer
        failed_count:
          type: integer

    TransactionItem:
      type: object
      properties:
        id:
          type: integer
        merchant_order_id:
          type: string
        type:
          type: string
        display_type:
          type: string
        mode:
          type: string
        display_mode:
          type: string
        amount:
          type: string
        display_amount:
          type: string
        currency:
          type: string
        status:
          type: string
        provider:
          type: string
        provider_ref:
          type: string
        fees_amount:
          type: string
        tax_amount:
          type: string
        net_amount:
          type: string
        created_at:
          type: string
          nullable: true
        is_beneficiary_verification:
          type: boolean

    TransactionReportsResponse:
      type: object
      properties:
        ok:
          type: boolean
        services:
          $ref: "#/components/schemas/ServicesVisibility"
        filters:
          type: object
        summary:
          $ref: "#/components/schemas/TransactionSummary"
        provider_options:
          type: array
          items:
            type: string
        allowed_types:
          type: array
          items:
            type: string
        items:
          type: array
          items:
            $ref: "#/components/schemas/TransactionItem"
        pagination:
          $ref: "#/components/schemas/Pagination"

    LedgerSummary:
      type: object
      properties:
        total:
          type: integer
        total_credit:
          type: string
        total_debit:
          type: string
        net:
          type: string

    LedgerItem:
      type: object
      properties:
        id:
          type: integer
        entry_ref:
          type: string
        client_ref:
          type: string
        wallet_type:
          type: string
        entry_type:
          type: string
        amount:
          type: string
        opening_balance:
          type: string
        closing_balance:
          type: string
        reason:
          type: string
        created_at:
          type: string
          nullable: true

    FundRequestItem:
      type: object
      properties:
        id:
          type: integer
        wallet_type:
          type: string
        amount:
          type: string
        note:
          type: string
        status:
          type: string
        decided_at:
          type: string
          nullable: true
        decision_note:
          type: string
        ledger_entry_ref:
          type: string
        created_at:
          type: string
          nullable: true

    LedgerResponse:
      type: object
      properties:
        ok:
          type: boolean
        services:
          $ref: "#/components/schemas/ServicesVisibility"
        balances:
          $ref: "#/components/schemas/Balances"
        filters:
          type: object
        summary:
          $ref: "#/components/schemas/LedgerSummary"
        allowed_wallets:
          type: array
          items:
            type: string
        items:
          type: array
          items:
            $ref: "#/components/schemas/LedgerItem"
        recent_fund_requests:
          type: array
          items:
            $ref: "#/components/schemas/FundRequestItem"
        pagination:
          $ref: "#/components/schemas/Pagination"

    Pagination:
      type: object
      properties:
        page:
          type: integer
        limit:
          type: integer
        total:
          type: integer
        pages:
          type: integer

    ErrorResponse:
      type: object
      properties:
        ok:
          type: boolean
        error:
          type: object
          properties:
            message:
              type: string
            status:
              type: integer
