openapi: 3.0.3
info:
  title: PaySuite
  description: ''
  version: 1.0.0
servers:
  -
    url: 'https://paysuite.tech'
tags:
  -
    name: 'Payment Requests'
    description: "\nAPIs for managing payment requests"
  -
    name: 'Payout Requests'
    description: "\nAPIs for managing payout requests. Payout statuses: pending, completed, failed, cancelled."
  -
    name: Refunds
    description: "\nAPIs for managing refunds. Refund statuses: pending, processing, completed, failed, cancelled."
components:
  securitySchemes:
    default:
      type: http
      scheme: bearer
      description: 'You can retrieve your token by visiting your dashboard and clicking <b>Generate API token</b>.'
security:
  -
    default: []
paths:
  /api/v1/payments:
    post:
      summary: 'Create Payment Request'
      operationId: createPaymentRequest
      description: 'Creates a new payment request in the system.'
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  status: success
                  data:
                    id: 550e8400-e29b-41d4-a716-446655440000
                    amount: 100.5
                    reference: INV2024001
                    status: pending
                    checkout_url: 'https://paysuite.test/checkout/550e8400-e29b-41d4-a716-446655440000'
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: 550e8400-e29b-41d4-a716-446655440000
                      amount:
                        type: number
                        example: 100.5
                      reference:
                        type: string
                        example: INV2024001
                      status:
                        type: string
                        example: pending
                      checkout_url:
                        type: string
                        example: 'https://paysuite.test/checkout/550e8400-e29b-41d4-a716-446655440000'
        422:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  status: error
                  message: 'Invalid input'
                properties:
                  status:
                    type: string
                    example: error
                  message:
                    type: string
                    example: 'Invalid input'
      tags:
        - 'Payment Requests'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: numeric
                  description: 'Payment amount in MZN.'
                  example: '100.50'
                method:
                  type: string
                  description: 'optional Payment method.'
                  example: null
                  enum:
                    - credit_card
                    - mpesa
                    - emola
                reference:
                  type: string
                  description: 'Unique payment reference (max: 50 characters).'
                  example: INV2024001
                description:
                  type: string
                  description: 'optional Payment description (max: 125 characters).'
                  example: 'Payment for invoice INV2024001'
                  nullable: true
                return_url:
                  type: string
                  description: 'optional URL to redirect after payment completion.'
                  example: 'https://example.com/success'
                callback_url:
                  type: string
                  description: ''
                  example: null
              required:
                - amount
                - reference
  '/api/v1/payments/{id}':
    get:
      summary: 'Get Payment Request'
      operationId: getPaymentRequest
      description: 'Returns the details of a specific payment request.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  status: success
                  data:
                    id: 550e8400-e29b-41d4-a716-446655440000
                    amount: 100.5
                    reference: INV2024001
                    status: paid
                    transaction:
                      id: 1
                      status: completed
                      transaction_id: MPESA123456
                      paid_at: '2024-02-10T10:15:00.000000Z'
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: 550e8400-e29b-41d4-a716-446655440000
                      amount:
                        type: number
                        example: 100.5
                      reference:
                        type: string
                        example: INV2024001
                      status:
                        type: string
                        example: paid
                      transaction:
                        type: object
                        properties:
                          id:
                            type: integer
                            example: 1
                          status:
                            type: string
                            example: completed
                          transaction_id:
                            type: string
                            example: MPESA123456
                          paid_at:
                            type: string
                            example: '2024-02-10T10:15:00.000000Z'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  status: error
                  message: 'Payment request not found.'
                properties:
                  status:
                    type: string
                    example: error
                  message:
                    type: string
                    example: 'Payment request not found.'
      tags:
        - 'Payment Requests'
    parameters:
      -
        in: path
        name: id
        description: 'ULID of the payment request.'
        example: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
        required: true
        schema:
          type: string
  /api/v1/payouts:
    get:
      summary: 'List Payouts'
      operationId: listPayouts
      description: 'Returns a paginated list of payouts for the authenticated account.'
      parameters:
        -
          in: query
          name: page
          description: 'Page number.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'Page number.'
            example: 1
        -
          in: query
          name: limit
          description: 'Number of items per page.'
          example: 15
          required: false
          schema:
            type: integer
            description: 'Number of items per page.'
            example: 15
      responses:
        200:
          description: ''
          content:
            text/plain:
              schema:
                type: string
                example: "{\n    \"data\": [\n        {\n            \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n            \"amount\": 100.00,\n            \"reference\": \"PO123ABC456\",\n            \"status\": \"pending\",\n            \"description\": \"Payout request\",\n            \"method\": \"mpesa\",\n            \"beneficiary\": {\"phone\": \"841234567\", \"holder\": \"John Doe\"},\n            \"created_at\": \"2024-02-28T10:00:00.000000Z\"\n        }\n    ],\n    \"links\": {...},\n    \"meta\": {...}\n}"
      tags:
        - 'Payout Requests'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                page:
                  type: integer
                  description: ''
                  example: 11
                limit:
                  type: integer
                  description: ''
                  example: 12
  '/api/v1/payouts/{id}':
    get:
      summary: 'Get Payout'
      operationId: getPayout
      description: 'Returns the details of a specific payout.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: 550e8400-e29b-41d4-a716-446655440000
                    amount: 100.0
                    reference: PO123ABC456
                    status: pending
                    description: 'Payout request'
                    method: mpesa
                    beneficiary:
                      phone: '841234567'
                      holder: 'John Doe'
                    created_at: '2024-02-28T10:00:00.000000Z'
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: 550e8400-e29b-41d4-a716-446655440000
                      amount:
                        type: number
                        example: 100.0
                      reference:
                        type: string
                        example: PO123ABC456
                      status:
                        type: string
                        example: pending
                      description:
                        type: string
                        example: 'Payout request'
                      method:
                        type: string
                        example: mpesa
                      beneficiary:
                        type: object
                        properties:
                          phone:
                            type: string
                            example: '841234567'
                          holder:
                            type: string
                            example: 'John Doe'
                      created_at:
                        type: string
                        example: '2024-02-28T10:00:00.000000Z'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Payout not found.'
                properties:
                  message:
                    type: string
                    example: 'Payout not found.'
      tags:
        - 'Payout Requests'
    parameters:
      -
        in: path
        name: id
        description: 'ULID of the payout.'
        example: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
        required: true
        schema:
          type: string
  /api/v1/refunds:
    get:
      summary: 'List Refunds'
      operationId: listRefunds
      description: 'Returns a paginated list of refunds for the authenticated account.'
      parameters:
        -
          in: query
          name: page
          description: 'Page number.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'Page number.'
            example: 1
        -
          in: query
          name: limit
          description: 'Number of items per page.'
          example: 20
          required: false
          schema:
            type: integer
            description: 'Number of items per page.'
            example: 20
      responses:
        200:
          description: ''
          content:
            text/plain:
              schema:
                type: string
                example: "{\n    \"data\": [\n        {\n            \"id\": \"01H8X9V8X9Y8Z9A8B8C8D8E8F8\",\n            \"payment_id\": \"01H8X9V8X9Y8Z9A8B8C8D8E8F8\",\n            \"amount\": 50.00,\n            \"status\": \"completed\",\n            \"reason\": \"Customer requested refund\"\n        }\n    ],\n    \"links\": {...},\n    \"meta\": {...}\n}"
        422:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The limit field must not be greater than 100.'
                properties:
                  message:
                    type: string
                    example: 'The limit field must not be greater than 100.'
      tags:
        - Refunds
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                page:
                  type: integer
                  description: ''
                  example: 4
                limit:
                  type: integer
                  description: 'Must not be greater than 100.'
                  example: 25
    post:
      summary: 'Create Refund'
      operationId: createRefund
      description: 'Creates a new refund request for a completed payment.'
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  status: success
                  data:
                    id: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
                    payment_id: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
                    amount: 50.0
                    status: pending
                    reason: 'Customer requested refund'
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
                      payment_id:
                        type: string
                        example: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
                      amount:
                        type: number
                        example: 50.0
                      status:
                        type: string
                        example: pending
                      reason:
                        type: string
                        example: 'Customer requested refund'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  status: error
                  message: 'Payment not found.'
                properties:
                  status:
                    type: string
                    example: error
                  message:
                    type: string
                    example: 'Payment not found.'
        422:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: ''
                    type: object
                    example:
                      status: error
                      message: 'Payment cannot be refunded. It must be completed and have available refund amount.'
                    properties:
                      status:
                        type: string
                        example: error
                      message:
                        type: string
                        example: 'Payment cannot be refunded. It must be completed and have available refund amount.'
                  -
                    description: ''
                    type: object
                    example:
                      status: error
                      message: 'Refund amount cannot exceed available refund amount of {amount}.'
                    properties:
                      status:
                        type: string
                        example: error
                      message:
                        type: string
                        example: 'Refund amount cannot exceed available refund amount of {amount}.'
      tags:
        - Refunds
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_id:
                  type: ulid
                  description: 'ID of the payment to refund.'
                  example: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
                amount:
                  type: numeric
                  description: 'Refund amount (min 0.01, max 10,000,000).'
                  example: '50.00'
                reason:
                  type: string
                  description: 'Reason for refund (max 500 characters).'
                  example: 'Customer requested refund'
              required:
                - payment_id
                - amount
                - reason
  '/api/v1/refunds/{id}':
    get:
      summary: 'Get Refund'
      operationId: getRefund
      description: 'Returns the details of a specific refund including gateway records.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            text/plain:
              schema:
                type: string
                example: "{\n    \"status\": \"success\",\n    \"data\": {\n        \"id\": \"01H8X9V8X9Y8Z9A8B8C8D8E8F8\",\n        \"payment_id\": \"01H8X9V8X9Y8Z9A8B8C8D8E8F8\",\n        \"amount\": 50.00,\n        \"status\": \"completed\",\n        \"reason\": \"Customer requested refund\",\n        \"payment\": {...}\n    }\n}"
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  status: error
                  message: 'Refund not found.'
                properties:
                  status:
                    type: string
                    example: error
                  message:
                    type: string
                    example: 'Refund not found.'
      tags:
        - Refunds
    parameters:
      -
        in: path
        name: id
        description: 'The ID of the refund.'
        example: laudantium
        required: true
        schema:
          type: string
      -
        in: path
        name: ulid
        description: 'ULID of the refund.'
        example: 01H8X9V8X9Y8Z9A8B8C8D8E8F8
        required: true
        schema:
          type: string
