openapi: 3.1.0
info:
  title: SwApp Mobile Money API V2
  version: 2.0.0
  summary: Versioned mobile money APIs with explicit HTTP status codes and numeric SwApp status values.
servers:
  - url: https://www.swapp.co.ug/swapp/api/v2
    description: Production
  - url: https://www.swapp.co.ug/apitest/v2
    description: SIT
tags:
  - name: Mobile Money
    description: Mobile money validation, payout, collection, balance, status, and bulk validation APIs.
paths:
  /mobile-money/token:
    post:
      tags: [Mobile Money]
      operationId: createMobileMoneyTokenV2
      summary: Create a bearer token for V2 mobile money requests.
      security:
        - clientBasicAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      responses:
        '200':
          description: Token created.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiEnvelope'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/TokenData'
        '401':
          $ref: '#/components/responses/AuthenticationError'
  /mobile-money/accounts/validate:
    post:
      tags: [Mobile Money]
      operationId: validateMobileMoneyAccountV2
      summary: Validate a mobile money account.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/AccountValidation'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
  /mobile-money/payouts:
    post:
      tags: [Mobile Money]
      operationId: createMobileMoneyPayoutV2
      summary: Send funds to a customer mobile money account.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/MoneyMovement'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '202':
          $ref: '#/components/responses/Pending'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
        '409':
          $ref: '#/components/responses/ConflictError'
  /mobile-money/collections:
    post:
      tags: [Mobile Money]
      operationId: createMobileMoneyCollectionV2
      summary: Collect funds from a customer mobile money account.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/MoneyMovement'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '202':
          $ref: '#/components/responses/Pending'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
        '409':
          $ref: '#/components/responses/ConflictError'
  /mobile-money/flat/accounts/validate:
    post:
      tags: [Mobile Money]
      operationId: validateFlatMobileMoneyAccountV2
      summary: Validate a flat mobile money account using the existing flat validation flow.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/AccountValidationWithAmount'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
  /mobile-money/flat/payouts:
    post:
      tags: [Mobile Money]
      operationId: createFlatMobileMoneyPayoutV2
      summary: Create a flat mobile money payout using the existing flat payout flow.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/MoneyMovement'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '202':
          $ref: '#/components/responses/Pending'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
        '409':
          $ref: '#/components/responses/ConflictError'
  /mobile-money/momo/accounts/validate:
    post:
      tags: [Mobile Money]
      operationId: validateMomoAccountV2
      summary: Validate a MoMo account using the existing MoMo validation flow.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/AccountValidationWithAmount'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
  /mobile-money/momo/deposits:
    post:
      tags: [Mobile Money]
      operationId: createMomoDepositV2
      summary: Create a MoMo deposit using the existing MoMo deposit flow.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/MoneyMovement'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '202':
          $ref: '#/components/responses/Pending'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
        '409':
          $ref: '#/components/responses/ConflictError'
  /mobile-money/balance:
    post:
      tags: [Mobile Money]
      operationId: getMobileMoneyBalanceV2
      summary: Get the API client's available mobile money balance.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
  /mobile-money/status:
    post:
      tags: [Mobile Money]
      operationId: getMobileMoneyStatusV2
      summary: Check a mobile money transaction by request ID.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        $ref: '#/components/requestBodies/Status'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '202':
          $ref: '#/components/responses/Pending'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /mobile-money/bulk/accounts/validate:
    post:
      tags: [Mobile Money]
      operationId: bulkValidateMobileMoneyAccountsV2
      summary: Validate multiple mobile money accounts.
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/SwappClientId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkValidationRequest'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/AuthorizationError'
components:
  securitySchemes:
    clientBasicAuth:
      type: http
      scheme: basic
      description: Basic credentials are user_key:user_secret and require Swapp-Client-ID.
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  parameters:
    SwappClientId:
      name: Swapp-Client-ID
      in: header
      required: true
      schema:
        type: string
      description: API client identifier.
  requestBodies:
    AccountValidation:
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/AccountValidationRequest'
    AccountValidationWithAmount:
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/AccountValidationWithAmountRequest'
    MoneyMovement:
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/MoneyMovementRequest'
    Status:
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/StatusRequest'
  responses:
    Success:
      description: Request completed successfully.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiEnvelope'
          examples:
            success:
              value:
                code: 200
                status: 1
                message: SUCCESS
                requestId: d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6
                data:
                  providerReference: MM-240901-0001
                  providerStatus: SUCCESS
    Pending:
      description: Transaction accepted and still pending.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiEnvelope'
          examples:
            pending:
              value:
                code: 202
                status: 2
                message: PENDING
                requestId: d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6
                data:
                  providerReference: MM-240901-0001
                  providerStatus: PENDING
    ValidationError:
      description: Request validation failed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiEnvelope'
          examples:
            missingField:
              value:
                code: 400
                status: 8
                message: 'Missing required field: account'
                data:
                  errors:
                    account:
                      - The account field is required.
    AuthenticationError:
      description: Authentication failed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiEnvelope'
          examples:
            invalidToken:
              value:
                code: 401
                status: 9
                message: Invalid or expired bearer token
                data: {}
    AuthorizationError:
      description: API capability is not enabled.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiEnvelope'
          examples:
            capabilityDisabled:
              value:
                code: 403
                status: 10
                message: Mobile money API access is not enabled for this client
                data: {}
    ConflictError:
      description: Duplicate or conflicting request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiEnvelope'
          examples:
            duplicateRequest:
              value:
                code: 409
                status: 6
                message: Duplicate requestId
                requestId: d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6
                data: {}
    NotFoundError:
      description: Transaction not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiEnvelope'
          examples:
            transactionNotFound:
              value:
                code: 404
                status: 11
                message: Transaction not found
                requestId: d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6
                data: {}
  schemas:
    ApiEnvelope:
      type: object
      required: [code, status, message]
      properties:
        code:
          type: integer
          description: HTTP status code returned by the API.
        status:
          $ref: '#/components/schemas/SwappStatus'
        message:
          type: string
        requestId:
          type: string
          format: uuid
        data:
          type: object
    SwappStatus:
      type: integer
      enum: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
      x-enumDescriptions:
        1: SUCCESS
        2: PENDING
        3: FAILED
        4: REJECTED
        5: EXPIRED
        6: DUPLICATE
        7: BLOCKED_REPLAY
        8: VALIDATION_ERROR
        9: AUTHENTICATION_ERROR
        10: AUTHORIZATION_ERROR
        11: NOT_FOUND
        12: RATE_LIMITED
        13: SYSTEM_ERROR
        14: PRECONDITION_REQUIRED
    AccountValidationRequest:
      type: object
      required: [account]
      properties:
        account:
          type: string
          minLength: 1
        amount:
          type: integer
          minimum: 0
          maximum: 5000000
        type:
          type: string
          enum: [collect, payout]
    AccountValidationWithAmountRequest:
      type: object
      required: [account, amount]
      properties:
        account:
          type: string
          minLength: 1
        amount:
          type: integer
          minimum: 1
          maximum: 5000000
        type:
          type: string
          enum: [deposit, payout]
    MoneyMovementRequest:
      type: object
      required: [account, amount, requestId]
      properties:
        account:
          type: string
          minLength: 1
        amount:
          type: integer
          minimum: 1000
          maximum: 5000000
        requestId:
          type: string
          format: uuid
        otp:
          type: string
          description: Optional OTP for collection flows where required by the provider.
    StatusRequest:
      type: object
      required: [requestId]
      properties:
        requestId:
          type: string
          format: uuid
    BulkValidationRequest:
      type: object
      required: [accounts]
      properties:
        accounts:
          type: array
          minItems: 1
          items:
            type: string
    TokenData:
      type: object
      required: [clientId, accessToken, tokenType, expiresIn, expiresAt]
      properties:
        clientId:
          type: string
        accessToken:
          type: string
        tokenType:
          type: string
          enum: [Bearer]
        expiresIn:
          type: integer
        expiresAt:
          type: integer
