openapi: 3.0.3
info:
  title: SikaaHub API
  version: 1.0.0
  description: Ghana-focused merchant/customer financial API.
servers:
  - url: https://api.sikaahub.com/v1
security:
  - bearerAuth: []
paths:
  /health:
    get:
      security: []
      summary: Health check
      responses:
        "200": { description: API is healthy }
  /health/deep:
    get:
      summary: Deep operational health check
      responses:
        "200": { description: Deep health check completed }
  /auth/register/customer:
    post:
      security: []
      summary: Register a customer
      requestBody:
        required: true
        content:
          application/json:
            example: { full_name: "Ama Mensah", phone: "+233241234567", email: "ama@example.com", password: "StrongPass123" }
      responses:
        "201": { description: Customer registered }
  /auth/register/merchant:
    post:
      security: []
      summary: Register a merchant account and pending merchant profile
      requestBody:
        required: true
        content:
          application/json:
            example: { business_name: "Susu Ensu Enterprise", owner_name: "Kwame Mensah", phone: "+233201234567", password: "StrongPass123", region: "Greater Accra", city: "Accra" }
      responses:
        "201": { description: Merchant submitted }
  /auth/login:
    post:
      security: []
      summary: Login and register device
      parameters:
        - in: header
          name: X-Device-ID
          schema: { type: string }
        - in: header
          name: X-App-Version
          schema: { type: string }
      responses:
        "200": { description: Access and refresh tokens issued }
  /auth/verify-phone:
    post:
      security: []
      summary: Verify phone OTP and activate onboarding status
      responses:
        "200": { description: Phone verified }
  /auth/verify-device:
    post:
      security: []
      summary: Verify and trust a new login device
      responses:
        "200": { description: Device verified }
  /auth/refresh:
    post:
      security: []
      summary: Rotate refresh token and issue a new access token
      responses:
        "200": { description: Token refreshed }
  /customers/me:
    get:
      summary: Current customer profile
      responses:
        "200": { description: Customer profile }
    put:
      summary: Update current customer profile
      responses:
        "200": { description: Profile updated }
  /merchants/verify/{merchantCode}:
    get:
      security: []
      summary: Verify merchant QR payload code
      parameters:
        - in: path
          name: merchantCode
          required: true
          schema: { type: string }
      responses:
        "200": { description: Merchant display identity }
  /payments/initiate:
    post:
      summary: Create a pending payment
      parameters:
        - in: header
          name: Idempotency-Key
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            example: { merchant_code: "SHB-MER-000001", amount: 50.00, currency: "GHS", description: "Payment for goods" }
      responses:
        "201": { description: Pending payment created }
  /payments/confirm:
    post:
      summary: Confirm payment with transaction PIN
      parameters:
        - in: header
          name: Idempotency-Key
          required: true
          schema: { type: string }
      responses:
        "200": { description: Payment successful and ledger transaction created }
  /wallets/me:
    get:
      summary: Current actor wallet
      responses:
        "200": { description: Wallet fetched }
  /wallets/me/balance:
    get:
      summary: Current wallet balance and audit recalculation
      responses:
        "200": { description: Wallet balance fetched }
  /wallets/me/ledger:
    get:
      summary: Cursor-paginated immutable wallet ledger
      parameters:
        - { in: query, name: cursor, schema: { type: string } }
        - { in: query, name: limit, schema: { type: integer, maximum: 100, default: 20 } }
      responses:
        "200": { description: Ledger entries fetched }
  /devices:
    get:
      summary: List current user devices
      responses:
        "200": { description: Devices fetched }
  /kyc/customer/basic:
    post:
      summary: Submit customer basic KYC
      responses:
        "201": { description: Customer KYC submitted }
  /kyc/merchant/basic:
    post:
      summary: Submit merchant basic KYC
      responses:
        "201": { description: Merchant KYC submitted }
  /qr/verify:
    post:
      summary: Verify merchant QR token and code
      responses:
        "200": { description: Merchant verified }
  /withdrawals/initiate:
    post:
      summary: Customer initiates withdrawal from a merchant
      parameters:
        - in: header
          name: Idempotency-Key
          required: true
          schema: { type: string }
      responses:
        "201": { description: Withdrawal request created }
  /withdrawals/confirm:
    post:
      summary: Customer confirms withdrawal with transaction PIN
      parameters:
        - in: header
          name: Idempotency-Key
          required: true
          schema: { type: string }
      responses:
        "200": { description: Withdrawal confirmed }
  /withdrawals/complete:
    post:
      summary: Merchant completes cash payout and ledger movement
      responses:
        "200": { description: Withdrawal completed }
  /transactions:
    get:
      summary: Cursor-paginated transaction history
      parameters:
        - { in: query, name: cursor, schema: { type: integer } }
        - { in: query, name: limit, schema: { type: integer, maximum: 100, default: 20 } }
        - { in: query, name: type, schema: { type: string } }
        - { in: query, name: status, schema: { type: string } }
      responses:
        "200": { description: Transaction list }
  /admin/commission-rules:
    get:
      summary: List commission rules
      responses:
        "200": { description: Commission rules fetched }
    post:
      summary: Create commission rule
      responses:
        "201": { description: Commission rule created }
  /admin/wallets:
    get:
      summary: Admin wallet monitoring
      responses:
        "200": { description: Wallets fetched }
  /admin/risk-alerts:
    get:
      summary: List risk alerts
      responses:
        "200": { description: Risk alerts fetched }
  /webhooks/payment-provider:
    post:
      security: []
      summary: Payment provider webhook
      parameters:
        - in: header
          name: X-Signature
          required: true
          schema: { type: string }
      responses:
        "202": { description: Webhook accepted }
  /webhooks/{providerCode}:
    post:
      security: []
      summary: Generic provider webhook
      parameters:
        - { in: path, name: providerCode, required: true, schema: { type: string } }
        - { in: header, name: X-Signature, schema: { type: string } }
      responses:
        "202": { description: Webhook accepted }
  /admin/provider-configs:
    get:
      summary: List provider configs
      responses:
        "200": { description: Provider configs fetched }
    post:
      summary: Create provider config
      responses:
        "201": { description: Provider config created }
  /admin/providers/{providerCode}/check-health:
    post:
      summary: Run provider health check
      parameters:
        - { in: path, name: providerCode, required: true, schema: { type: string } }
      responses:
        "200": { description: Provider health checked }
  /admin/reconciliation/run:
    post:
      summary: Run provider reconciliation
      responses:
        "201": { description: Reconciliation completed }
  /admin/settlements:
    get:
      summary: List settlements
      responses:
        "200": { description: Settlements fetched }
  /admin/settlements/generate:
    post:
      summary: Generate settlements
      responses:
        "201": { description: Settlements generated }
  /merchants/me/settlements:
    get:
      summary: Merchant settlement history
      responses:
        "200": { description: Merchant settlements fetched }
  /admin/dashboard/summary:
    get:
      summary: Admin dashboard summary
      parameters:
        - { in: header, name: X-Request-ID, schema: { type: string } }
      responses:
        "200": { description: Dashboard summary fetched }
        "429": { description: Too many requests }
  /admin/users:
    get:
      summary: List users
      responses:
        "200": { description: Users fetched }
  /admin/fraud-rules:
    get:
      summary: List fraud rules
      responses:
        "200": { description: Fraud rules fetched }
    post:
      summary: Create fraud rule
      responses:
        "201": { description: Fraud rule created }
  /admin/reversal-requests:
    get:
      summary: List reversal requests
      responses:
        "200": { description: Reversal requests fetched }
  /admin/observability/requests:
    get:
      summary: Request logs
      responses:
        "200": { description: Request logs fetched }
  /admin/observability/errors:
    get:
      summary: Error logs
      responses:
        "200": { description: Error logs fetched }
  /admin/observability/slow-requests:
    get:
      summary: Slow request logs
      responses:
        "200": { description: Slow request logs fetched }
  /admin/system/jobs:
    get:
      summary: Queue jobs
      responses:
        "200": { description: Jobs fetched }
  /app/config:
    get:
      security: []
      summary: Mobile app configuration
      responses:
        "200": { description: App configuration loaded }
  /mobile/auth/login:
    post:
      security: []
      summary: Mobile login with device details
      responses:
        "200": { description: Mobile login successful }
  /mobile/customer/home:
    get:
      summary: Customer app home payload
      responses:
        "200": { description: Customer home loaded }
  /mobile/merchant/home:
    get:
      summary: Merchant app home payload
      responses:
        "200": { description: Merchant home loaded }
  /mobile/qr/verify:
    post:
      summary: Verify scanned merchant QR
      responses:
        "200": { description: Merchant verified }
  /mobile/payments/preview:
    post:
      summary: Preview payment before initiation
      responses:
        "200": { description: Payment preview generated }
  /mobile/withdrawals/preview:
    post:
      summary: Preview withdrawal before initiation
      responses:
        "200": { description: Withdrawal preview generated }
  /mobile/transactions/{id}/receipt:
    get:
      summary: Mobile transaction receipt
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Receipt loaded }
  /dashboard/merchant/summary:
    get:
      summary: Merchant dashboard summary
      responses:
        "200": { description: Merchant dashboard summary loaded }
        "403": { description: Merchant dashboard access required }
  /dashboard/merchant/analytics/transactions:
    get:
      summary: Merchant transaction analytics
      parameters:
        - { in: query, name: from, schema: { type: string, format: date } }
        - { in: query, name: to, schema: { type: string, format: date } }
        - { in: query, name: group_by, schema: { type: string, enum: [hour, day, week, month] } }
      responses:
        "200": { description: Analytics loaded }
  /dashboard/merchant/transactions:
    get:
      summary: Merchant dashboard transaction list
      parameters:
        - { in: query, name: limit, schema: { type: integer, maximum: 100 } }
        - { in: query, name: cursor, schema: { type: string } }
        - { in: query, name: status, schema: { type: string } }
        - { in: query, name: type, schema: { type: string } }
      responses:
        "200": { description: Merchant transactions fetched }
  /dashboard/merchant/payments/{id}:
    get:
      summary: Merchant payment detail
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Merchant payment loaded }
  /dashboard/merchant/withdrawal-requests/{id}/approve:
    post:
      summary: Approve merchant withdrawal request
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Withdrawal approved }
  /dashboard/merchant/commissions/summary:
    get:
      summary: Merchant commission summary
      responses:
        "200": { description: Merchant commission summary loaded }
  /dashboard/merchant/settlements/summary:
    get:
      summary: Merchant settlement summary
      responses:
        "200": { description: Merchant settlement summary loaded }
  /dashboard/merchant/qr/regenerate:
    post:
      summary: Regenerate merchant QR with transaction PIN
      responses:
        "200": { description: Merchant QR regenerated }
  /dashboard/merchant/staff:
    get:
      summary: List merchant staff
      responses:
        "200": { description: Merchant staff fetched }
    post:
      summary: Add merchant staff member
      responses:
        "201": { description: Merchant staff created }
  /dashboard/merchant/exports/{type}:
    post:
      summary: Create merchant report export
      parameters:
        - { in: path, name: type, required: true, schema: { type: string, enum: [transactions, payments, withdrawals, commissions, settlements] } }
      responses:
        "201": { description: Export job created }
  /disputes:
    get:
      summary: List disputes for authenticated user
      responses:
        "200": { description: Disputes fetched }
    post:
      summary: Create dispute
      responses:
        "201": { description: Dispute created }
  /admin/disputes:
    get:
      summary: Admin dispute list
      responses:
        "200": { description: Admin disputes fetched }
  /admin/pilot/merchants:
    get:
      summary: List pilot merchants
      responses:
        "200": { description: Pilot merchants fetched }
    post:
      summary: Tag merchant for pilot
      responses:
        "201": { description: Pilot merchant saved }
  /admin/feedback:
    get:
      summary: List merchant feedback
      responses:
        "200": { description: Merchant feedback fetched }
  /admin/operations/summary:
    get:
      summary: Internal admin operations summary
      responses:
        "200": { description: Admin operations summary loaded }
  /admin/customers:
    get:
      summary: Admin customer list
      responses:
        "200": { description: Customer list loaded }
  /admin/customers/{id}:
    get:
      summary: Admin customer detail
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Customer loaded }
  /admin/merchants:
    get:
      summary: Admin merchant list
      responses:
        "200": { description: Merchant list loaded }
  /admin/merchants/{id}:
    get:
      summary: Admin merchant detail
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Merchant loaded }
  /admin/kyc/workbench:
    get:
      summary: KYC review workbench
      responses:
        "200": { description: KYC workbench loaded }
  /admin/monitoring/transactions:
    get:
      summary: Internal transaction monitoring
      responses:
        "200": { description: Transactions monitoring loaded }
  /admin/finance/summary:
    get:
      summary: Finance operations summary
      responses:
        "200": { description: Finance summary loaded }
  /admin/support/summary:
    get:
      summary: Support workbench summary
      responses:
        "200": { description: Support summary loaded }
  /admin/risk/blacklist:
    get:
      summary: Risk blacklist entries
      responses:
        "200": { description: Risk blacklist loaded }
    post:
      summary: Add risk blacklist entry
      responses:
        "201": { description: Risk blacklist entry added }
  /admin/settings:
    get:
      summary: Internal settings
      responses:
        "200": { description: Settings loaded }
  /admin/maintenance:
    get:
      summary: Maintenance mode settings
      responses:
        "200": { description: Maintenance settings loaded }
  /admin/exports/{type}:
    post:
      summary: Create internal export job
      parameters:
        - { in: path, name: type, required: true, schema: { type: string } }
      responses:
        "201": { description: Admin export job created }
  /admin/compliance/summary:
    get:
      summary: Compliance report summary
      responses:
        "200": { description: Compliance summary loaded }
  /admin/admin-activity:
    get:
      summary: Admin activity audit trail
      responses:
        "200": { description: Admin activity loaded }
  /admin/announcements:
    get:
      summary: Internal announcements
      responses:
        "200": { description: Admin announcements loaded }
    post:
      summary: Create internal announcement
      responses:
        "201": { description: Admin announcement created }
  /admin/sandbox/wallets/{id}/credit:
    post:
      summary: Credit a sandbox wallet
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Sandbox wallet credited }
        "403": { description: Sandbox disabled in production }
  /admin/sandbox/wallets/{id}/debit:
    post:
      summary: Debit a sandbox wallet
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Sandbox wallet debited }
  /admin/sandbox/wallets/{id}/reset:
    post:
      summary: Reset a sandbox wallet
      parameters:
        - { in: path, name: id, required: true, schema: { type: string } }
      responses:
        "200": { description: Sandbox wallet reset }
  /admin/sandbox/provider-scenarios:
    get:
      summary: List sandbox provider scenarios
      responses:
        "200": { description: Scenario list loaded }
    post:
      summary: Create sandbox provider scenario
      responses:
        "201": { description: Scenario created }
  /sandbox/provider/payments/success:
    post:
      summary: Simulate sandbox payment success
      responses:
        "200": { description: Payment success simulated }
  /sandbox/provider/payments/fail:
    post:
      summary: Simulate sandbox payment failure
      responses:
        "200": { description: Payment failure simulated }
  /sandbox/provider/withdrawals/success:
    post:
      summary: Simulate sandbox withdrawal success
      responses:
        "200": { description: Withdrawal success simulated }
  /sandbox/provider/withdrawals/fail:
    post:
      summary: Simulate sandbox withdrawal failure
      responses:
        "200": { description: Withdrawal failure simulated }
  /sandbox/provider/webhooks/duplicate:
    post:
      summary: Simulate duplicate sandbox webhook
      responses:
        "200": { description: Duplicate webhook simulated }
  /sandbox/provider/webhooks/invalid-signature:
    post:
      summary: Simulate invalid sandbox webhook signature
      responses:
        "200": { description: Invalid webhook simulated }
  /admin/pilot/metrics:
    get:
      summary: Pilot metrics
      responses:
        "200": { description: Pilot metrics loaded }
  /admin/pilot/merchant-metrics/{merchantId}:
    get:
      summary: Pilot merchant metrics
      parameters:
        - { in: path, name: merchantId, required: true, schema: { type: string } }
      responses:
        "200": { description: Pilot merchant metrics loaded }
  /developers/register:
    post:
      summary: Register developer account
      responses:
        "201": { description: Developer account registered }
  /developers/me:
    get:
      summary: Developer profile
      responses:
        "200": { description: Developer profile loaded }
    put:
      summary: Update developer profile
      responses:
        "200": { description: Developer profile updated }
  /developers/apps:
    get:
      summary: List developer apps
      responses:
        "200": { description: Developer apps loaded }
    post:
      summary: Create developer app
      responses:
        "201": { description: Developer app created }
  /developers/apps/{id}/api-keys:
    post:
      summary: Create app API key
      responses:
        "201": { description: API key created and shown once }
    get:
      summary: List app API keys
      responses:
        "200": { description: API keys loaded }
  /developers/apps/{id}/webhooks:
    get:
      summary: List developer webhooks
      responses:
        "200": { description: Webhooks loaded }
    post:
      summary: Create developer webhook
      responses:
        "201": { description: Webhook created and secret shown once }
  /developers/apps/{id}/usage/summary:
    get:
      summary: Developer app API usage summary
      responses:
        "200": { description: Usage summary loaded }
  /partners/merchants/verify/{merchantCode}:
    get:
      summary: Partner merchant verification
      security:
        - apiKeyAuth: []
      responses:
        "200": { description: Merchant verified }
  /partners/payments/preview:
    post:
      summary: Partner payment preview
      security:
        - apiKeyAuth: []
      responses:
        "200": { description: Payment preview generated }
  /partners/payments/initiate:
    post:
      summary: Partner payment initiate
      security:
        - apiKeyAuth: []
      responses:
        "201": { description: Payment initiated }
  /partners/transactions:
    get:
      summary: Partner transaction list
      security:
        - apiKeyAuth: []
      responses:
        "200": { description: Transactions loaded }
  /admin/developers:
    get:
      summary: Admin developer list
      responses:
        "200": { description: Developers loaded }
  /admin/developer-apps:
    get:
      summary: Admin developer app list
      responses:
        "200": { description: Developer apps loaded }
  /admin/developer-rate-plans:
    get:
      summary: Developer rate plans
      responses:
        "200": { description: Rate plans loaded }
    post:
      summary: Create developer rate plan
      responses:
        "201": { description: Rate plan created }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-SikaaHub-Key
