openapi: 3.1.0
info:
  title: Onlobo Payment Gateway API
  version: 1.0.0
  description: Merchant-facing signed API for payments, refunds, subscriptions, payouts, funds and daily reports.
servers:
  - url: https://onlobo.com
security:
  - MerchantSignature: []
tags:
  - name: Payments
  - name: Refunds
  - name: Subscriptions
  - name: Payouts
  - name: Funds
  - name: Reports
paths:
  /gateway/v1/payments:
    post:
      tags: [Payments]
      summary: Create payment
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema: {$ref: '#/components/schemas/CreatePayment'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
        '400': {$ref: '#/components/responses/Error'}
    get:
      tags: [Payments]
      summary: Query payments
      parameters:
        - {$ref: '#/components/parameters/Page'}
        - {$ref: '#/components/parameters/PageSize'}
        - {name: merchantOrderNo, in: query, schema: {type: string}}
        - {name: status, in: query, schema: {type: string}}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/payments/{paymentNo}:
    get:
      tags: [Payments]
      summary: Get payment
      parameters:
        - {$ref: '#/components/parameters/PaymentNo'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
        '404': {$ref: '#/components/responses/Error'}
  /gateway/v1/payments/{paymentNo}/attempts:
    get:
      tags: [Payments]
      summary: List routing attempts
      parameters:
        - {$ref: '#/components/parameters/PaymentNo'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/payments/{paymentNo}/refunds:
    post:
      tags: [Refunds]
      summary: Create refund
      parameters:
        - {$ref: '#/components/parameters/PaymentNo'}
        - {$ref: '#/components/parameters/IdempotencyKey'}
      requestBody:
        required: true
        content:
          application/json:
            schema: {$ref: '#/components/schemas/CreateRefund'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
        '409': {$ref: '#/components/responses/Error'}
  /gateway/v1/refunds:
    get:
      tags: [Refunds]
      summary: Query refunds
      parameters:
        - {$ref: '#/components/parameters/Page'}
        - {$ref: '#/components/parameters/PageSize'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/subscriptions:
    post:
      tags: [Subscriptions]
      summary: Create subscription
      parameters:
        - {$ref: '#/components/parameters/IdempotencyKey'}
      requestBody:
        required: true
        content:
          application/json:
            schema: {$ref: '#/components/schemas/CreateSubscription'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
    get:
      tags: [Subscriptions]
      summary: Query subscriptions
      parameters:
        - {$ref: '#/components/parameters/Page'}
        - {$ref: '#/components/parameters/PageSize'}
        - {name: merchantSubscriptionNo, in: query, schema: {type: string}}
        - {name: providerSubscriptionId, in: query, schema: {type: string}}
        - {name: customerEmail, in: query, schema: {type: string, format: email}}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/subscriptions/{subscriptionNo}:
    get:
      tags: [Subscriptions]
      summary: Get subscription
      parameters:
        - {$ref: '#/components/parameters/SubscriptionNo'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/subscriptions/{subscriptionNo}/invoices:
    get:
      tags: [Subscriptions]
      summary: List every subscription cycle, including failed cycles
      parameters:
        - {$ref: '#/components/parameters/SubscriptionNo'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/subscriptions/{subscriptionNo}/cancel:
    post:
      tags: [Subscriptions]
      summary: Cancel subscription
      parameters:
        - {$ref: '#/components/parameters/SubscriptionNo'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/payouts:
    post:
      tags: [Payouts]
      summary: Create payout
      parameters:
        - {$ref: '#/components/parameters/IdempotencyKey'}
      requestBody:
        required: true
        content:
          application/json:
            schema: {$ref: '#/components/schemas/CreatePayout'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
    get:
      tags: [Payouts]
      summary: Query payouts
      parameters:
        - {$ref: '#/components/parameters/Page'}
        - {$ref: '#/components/parameters/PageSize'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/payouts/{payoutNo}:
    get:
      tags: [Payouts]
      summary: Get payout
      parameters:
        - {name: payoutNo, in: path, required: true, schema: {type: string}}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/payouts/{payoutNo}/query:
    post:
      tags: [Payouts]
      summary: Query payout status from provider
      parameters:
        - {name: payoutNo, in: path, required: true, schema: {type: string}}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/funds/ledger:
    get:
      tags: [Funds]
      summary: Query merchant ledger
      parameters:
        - {$ref: '#/components/parameters/Page'}
        - {$ref: '#/components/parameters/PageSize'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/daily-reports:
    get:
      tags: [Reports]
      summary: Query daily reports
      parameters:
        - {name: from, in: query, schema: {type: string, format: date}}
        - {name: to, in: query, schema: {type: string, format: date}}
        - {name: status, in: query, description: 0 means all statuses, schema: {type: integer, minimum: 0}}
        - {$ref: '#/components/parameters/Page'}
        - {$ref: '#/components/parameters/PageSize'}
      responses:
        '200': {$ref: '#/components/responses/Success'}
  /gateway/v1/daily-reports/{date}/download:
    get:
      tags: [Reports]
      summary: Download the fixed daily Excel report
      parameters:
        - {name: date, in: path, required: true, schema: {type: string, format: date}}
      responses:
        '200':
          description: Excel report stream
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema: {type: string, format: binary}
components:
  securitySchemes:
    MerchantSignature:
      type: apiKey
      in: header
      name: X-Signature
      description: Requires X-Merchant-Id, X-Api-Key, X-Timestamp, X-Nonce and X-Signature. See the online signature guide.
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      schema: {type: string, maxLength: 128}
    Page:
      name: page
      in: query
      schema: {type: integer, minimum: 1, default: 1}
    PageSize:
      name: pageSize
      in: query
      schema: {type: integer, minimum: 1, maximum: 200, default: 20}
    PaymentNo:
      name: paymentNo
      in: path
      required: true
      schema: {type: string}
    SubscriptionNo:
      name: subscriptionNo
      in: path
      required: true
      schema: {type: string}
  responses:
    Success:
      description: Successful API response
      content:
        application/json:
          schema: {$ref: '#/components/schemas/ApiResponse'}
    Error:
      description: Standard error response
      content:
        application/json:
          schema: {$ref: '#/components/schemas/ApiResponse'}
  schemas:
    ApiResponse:
      type: object
      required: [code, message, requestId]
      properties:
        code: {type: integer, description: 1 means success}
        message: {type: string}
        data: {}
        requestId: {type: string}
    CreatePayment:
      type: object
      required: [merchantOrderNo, currency, amount, paymentMethod]
      properties:
        merchantOrderNo: {type: string}
        currency: {type: string, pattern: '^[A-Z]{3}$'}
        amount: {type: integer, description: Minor currency unit}
        paymentMethod: {type: string}
        channelCode: {type: string}
        channelSelectionMode: {type: string, enum: [AUTO, PREFERRED, STRICT]}
        country: {type: string}
        returnUrl: {type: string, format: uri}
        notifyUrl: {type: string, format: uri}
        metadata: {type: object, additionalProperties: {type: string}}
    CreateRefund:
      type: object
      required: [merchantRefundNo, amount]
      properties:
        merchantRefundNo: {type: string}
        amount: {type: integer, description: Minor currency unit}
        reason: {type: string}
    CreateSubscription:
      type: object
      required: [merchantSubscriptionNo, customerEmail, currency, planCode, paymentMethod]
      properties:
        merchantSubscriptionNo: {type: string}
        customerReference: {type: string}
        customerEmail: {type: string, format: email}
        currency: {type: string, pattern: '^[A-Z]{3}$'}
        planCode: {type: string}
        paymentMethod: {type: string}
        notifyUrl: {type: string, format: uri}
        paymentMethodData: {type: object, additionalProperties: true}
    CreatePayout:
      type: object
      required: [merchantPayoutNo, amount, currency, paymentMethod, recipientType, recipientName]
      properties:
        merchantPayoutNo: {type: string}
        amount: {type: integer, description: Minor currency unit}
        currency: {type: string, pattern: '^[A-Z]{3}$'}
        paymentMethod: {type: string}
        channelCode: {type: string}
        channelSelectionMode: {type: string, enum: [AUTO, PREFERRED, STRICT]}
        recipientType: {type: integer}
        recipientName: {type: string}
        recipientCountry: {type: string}
        recipientAccountMask: {type: string}
        recipientDetails: {type: object, additionalProperties: true}
        purpose: {type: string}
        notifyUrl: {type: string, format: uri}
