{
  "openapi": "3.0.3",
  "info": {
    "title": "Infopay Core Financial Engine API",
    "description": "Dokumentasi Resmi API Infopay v1.0 — Platform Pembayaran & Gateway PPOB/H2H Multi-Tenant, Ledgers Berimbang, Rekonsiliasi 3-Way, & Investor Profit Distribution.",
    "version": "1.0.0",
    "contact": {
      "name": "Infopay Engineering Team",
      "email": "dev@infopay.co.id"
    }
  },
  "servers": [
    {
      "url": "http://localhost:8000/api/v1",
      "description": "Local Development Server"
    }
  ],
  "tags": [
    { "name": "System Health", "description": "Liveness & Readiness probe endpoints" },
    { "name": "Identity & Access Management (IAM)", "description": "Autentikasi Bearer, Identitas Utama, & Peran Tenant" },
    { "name": "Catalog & Routing", "description": "Katalog Produk PPOB, Evaluasi Harga, & Routing Provider" },
    { "name": "H2H Inquiry & Payment", "description": "Tagihan H2H, Inquiry, Transaksi Pembayaran, & Outbox Recovery" },
    { "name": "Operations & Risk", "description": "Workspace Diagnostik Bermasker, Limits, Freeze, Maker-Checker, & Sinyal Fraud" },
    { "name": "Finance, Recon & Settlement", "description": "Impor Mutasi Provider, Matching 3-Way, Net Settlement, & Close Periode Keuangan" },
    { "name": "Investor Workspace", "description": "Profil Investor, Porsi Bagi Hasil 3-Pihak (30/30/40), Posisi Modal, & Jurnal Distribusi" }
  ],
  "paths": {
    "/health/live": {
      "get": {
        "tags": ["System Health"],
        "summary": "Liveness Probe",
        "description": "Memeriksa apakah instance aplikasi backend berjalan.",
        "responses": {
          "200": {
            "description": "Service is alive",
            "content": {
              "application/json": {
                "example": { "status": "ok", "timestamp": "2026-08-30T16:00:00Z" }
              }
            }
          }
        }
      }
    },
    "/health/ready": {
      "get": {
        "tags": ["System Health"],
        "summary": "Readiness Probe",
        "description": "Memeriksa kesiapan koneksi PostgreSQL database dan Redis cache.",
        "responses": {
          "200": {
            "description": "Database and cache ready",
            "content": {
              "application/json": {
                "example": { "status": "ready", "database": "connected", "cache": "connected" }
              }
            }
          }
        }
      }
    },
    "/me": {
      "get": {
        "tags": ["Identity & Access Management (IAM)"],
        "summary": "Mendapatkan Profil & Hak Akses Pengguna",
        "description": "Mengembalikan informasi Principal ID, Tenant ID, dan daftar Permissions yang dimiliki.",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Profil identitas berhasil diambil",
            "content": {
              "application/json": {
                "example": {
                  "principalId": "9b1deb4d-3b7d-4148-9f1a-0b263b651001",
                  "tenantId": "8f3b2c1a-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
                  "displayName": "Tenant Operator",
                  "permissions": ["iam.profile.read", "catalog.product.read", "h2h.inquiry.create"]
                }
              }
            }
          }
        }
      }
    },
    "/catalog/products": {
      "get": {
        "tags": ["Catalog & Routing"],
        "summary": "Daftar Produk Katalog",
        "description": "Menampilkan seluruh produk PPOB yang tersedia untuk tenant.",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Daftar produk katalog",
            "content": {
              "application/json": {
                "example": {
                  "products": [
                    { "code": "PLN_POSTPAID", "name": "PLN Pascabayar", "category": "PLN", "status": "ACTIVE" },
                    { "code": "BPJS_KS", "name": "BPJS Kesehatan", "category": "BPJS", "status": "ACTIVE" }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/catalog/products/{product}/quote-route": {
      "post": {
        "tags": ["Catalog & Routing"],
        "summary": "Evaluasi Harga & Route Provider",
        "description": "Menghitung biaya/fee dan memilih provider terbaik secara deterministik.",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          { "name": "product", "in": "path", "required": true, "schema": { "type": "string" }, "example": "PLN_POSTPAID" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": { "customerNumber": "530000000001", "nominal": "100000.00" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Evaluasi harga dan kandidat provider",
            "content": {
              "application/json": {
                "example": {
                  "priceBook": "STANDARD_2026",
                  "principalAmount": "100000.00",
                  "feeAmount": "2500.00",
                  "totalAmount": "102500.00",
                  "selectedProvider": "LOCAL_VH2H",
                  "routeReason": "BEST_HEALTH_AND_COST"
                }
              }
            }
          }
        }
      }
    },
    "/h2h/inquiries": {
      "post": {
        "tags": ["H2H Inquiry & Payment"],
        "summary": "Membuat Inquiry Tagihan H2H",
        "description": "Mengeksekusi inquiry tagihan ke simulator/provider H2H.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "productCode": "PLN_POSTPAID",
                "partnerReference": "REF-INQ-20260830-001",
                "customerNumber": "SYNTHETIC-0001"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Inquiry berhasil dibuat",
            "content": {
              "application/json": {
                "example": {
                  "inquiryId": "inq_9f8e7d6c5b4a3210",
                  "status": "SUCCEEDED",
                  "customerName": "PELANGGAN SYNTHETIC 01",
                  "billPeriod": "2026-08",
                  "principalAmount": "10000.00",
                  "feeAmount": "2500.00",
                  "totalAmount": "12775.00"
                }
              }
            }
          }
        }
      }
    },
    "/h2h/inquiries/{id}": {
      "get": {
        "tags": ["H2H Inquiry & Payment"],
        "summary": "Detail Status Inquiry H2H",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "example": "inq_9f8e7d6c5b4a3210" }
        ],
        "responses": {
          "200": { "description": "Record data inquiry" }
        }
      }
    },
    "/h2h/payments": {
      "post": {
        "tags": ["H2H Inquiry & Payment"],
        "summary": "Eksekusi Pembayaran Tagihan H2H",
        "description": "Melakukan reservasi prefund saldo, eksekusi pembayaran, dan pembentukan jurnal ledger berimbang.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "inquiryId": "inq_9f8e7d6c5b4a3210",
                "partnerReference": "PAY-20260830-001"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pembayaran sukses dan receipt diterbitkan",
            "content": {
              "application/json": {
                "example": {
                  "paymentId": "txn_1a2b3c4d5e6f7890",
                  "status": "SUCCEEDED",
                  "receiptNumber": "RCPT-20260830-1001",
                  "totalAmount": "12775.00"
                }
              }
            }
          }
        }
      }
    },
    "/h2h/payments/{id}": {
      "get": {
        "tags": ["H2H Inquiry & Payment"],
        "summary": "Detail Status & Struk Pembayaran",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Detail pembayaran & struk" } }
      }
    },
    "/h2h/payments/{id}/recover": {
      "post": {
        "tags": ["H2H Inquiry & Payment"],
        "summary": "Recovery Transaksi Gantung",
        "description": "Penyelesaian otomatis transaksi status PENDING menggunakan bukti provider status.",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Status transaksi ter-recovery" } }
      }
    },
    "/ops/transactions": {
      "get": {
        "tags": ["Operations & Risk"],
        "summary": "Pencarian Diagnostik Transaksi (Customer Data Masked)",
        "description": "Pencarian transaksi operasional dengan pemaskeran otomatis nomor pelanggan (`SYN****0001`).",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Hasil pencarian transaksi bermasker",
            "content": {
              "application/json": {
                "example": {
                  "transactions": [
                    { "publicId": "txn_1a2b3c4d5e6f7890", "customerMasked": "SYN****0001", "status": "SUCCEEDED", "totalAmount": "12775.00" }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/ops/transactions/{id}": {
      "get": {
        "tags": ["Operations & Risk"],
        "summary": "Detail Diagnostik & History Attempt",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Diagnostik transaksi" } }
      }
    },
    "/ops/maker-checker/requests": {
      "post": {
        "tags": ["Operations & Risk"],
        "summary": "Membuat Permintaan Maker-Checker",
        "description": "Mengajukan persetujuan tindakan sensitif (seperti pembukaan pembekuan akun).",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": { "actionType": "UNFREEZE_TENANT", "payload": { "reason": "Verifikasi dokumen selesai" } }
            }
          }
        },
        "responses": { "201": { "description": "Request pending checker" } }
      }
    },
    "/ops/maker-checker/requests/{id}/approve": {
      "post": {
        "tags": ["Operations & Risk"],
        "summary": "Checker Approve Request (Enforces Separation of Duties)",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Request disetujui & eksekusi sukses" } }
      }
    },
    "/ops/maker-checker/requests/{id}/reject": {
      "post": {
        "tags": ["Operations & Risk"],
        "summary": "Checker Reject Request",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Request ditolak" } }
      }
    },
    "/ops/cases": {
      "get": {
        "tags": ["Operations & Risk"],
        "summary": "Daftar Sinyal Fraud & Kasus Risiko",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Daftar fraud signals" } }
      }
    },
    "/finance/recon/import": {
      "post": {
        "tags": ["Finance, Recon & Settlement"],
        "summary": "Impor File Laporan Mutasi Provider",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "providerCode": "LOCAL_VH2H",
                "fileName": "stmt_20260830.csv",
                "rows": [
                  { "externalReference": "txn_1a2b3c4d5e6f7890", "customerNumber": "SYNTHETIC-0001", "amount": "12775.00", "transactionDate": "2026-08-30T10:00:00Z" }
                ]
              }
            }
          }
        },
        "responses": { "201": { "description": "File ter-impor & ter-parsing" } }
      }
    },
    "/finance/recon/process": {
      "post": {
        "tags": ["Finance, Recon & Settlement"],
        "summary": "Eksekusi Matching 3-Way Rekonsiliasi",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "example": { "fileId": "file_uuid_here" } } }
        },
        "responses": { "200": { "description": "Proses matching selesai" } }
      }
    },
    "/finance/recon/discrepancies": {
      "get": {
        "tags": ["Finance, Recon & Settlement"],
        "summary": "Daftar Temuan Diskrepansi Rekonsiliasi",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Daftar selisih nominal/transaksi hilang" } }
      }
    },
    "/finance/settlements/calculate": {
      "post": {
        "tags": ["Finance, Recon & Settlement"],
        "summary": "Kalkulasi Batch Net Settlement",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": { "providerCode": "LOCAL_VH2H", "periodStart": "2026-08-01T00:00:00Z", "periodEnd": "2026-08-31T23:59:59Z" }
            }
          }
        },
        "responses": { "201": { "description": "Batch settlement draft dibuat" } }
      }
    },
    "/finance/settlements/{id}/approve": {
      "post": {
        "tags": ["Finance, Recon & Settlement"],
        "summary": "Approve Batch Settlement & Posting Jurnal",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Settlement disetujui & jurnal diposting" } }
      }
    },
    "/finance/periods/close": {
      "post": {
        "tags": ["Finance, Recon & Settlement"],
        "summary": "Menutup Periode Keuangan (Period Close Protection)",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "example": { "periodCode": "2026-08" } } }
        },
        "responses": { "200": { "description": "Periode keuangan ter-CLOSED" } }
      }
    },
    "/finance/periods/reopen": {
      "post": {
        "tags": ["Finance, Recon & Settlement"],
        "summary": "Membuka Kembali Periode Keuangan yang Ditutup",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "example": { "periodCode": "2026-08" } } }
        },
        "responses": { "200": { "description": "Periode ter-REOPENED" } }
      }
    },
    "/investor/profile": {
      "get": {
        "tags": ["Investor Workspace"],
        "summary": "Profil Investor",
        "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Detail profil investor" } }
      }
    },
    "/investor/participations": {
      "get": {
        "tags": ["Investor Workspace"],
        "summary": "Daftar Partisipasi & Rasio Bagi Hasil (30% / 30% / 40%)",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Daftar perjanjian bagi hasil 3 pihak",
            "content": {
              "application/json": {
                "example": {
                  "participations": [
                    { "investorName": "PT Infokomexe (Infokom)", "sharePercentage": "30.00", "status": "ACTIVE" },
                    { "investorName": "Pak Indra", "sharePercentage": "30.00", "status": "ACTIVE" },
                    { "investorName": "Lapakbayar", "sharePercentage": "40.00", "status": "ACTIVE" }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/investor/positions": {
      "get": {
        "tags": ["Investor Workspace"],
        "summary": "Ringkasan Posisi Modal & Return Investor",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Breakdown modal awal (Rp 100jt) & akumulasi return",
            "content": {
              "application/json": {
                "example": {
                  "positions": [
                    { "investorCode": "INV-INFOKOM", "investorName": "PT Infokomexe (Infokom)", "sharePercentage": "30.00", "totalCapital": "30000000.00", "accumulatedReturns": "3000.00" },
                    { "investorCode": "INV-INDRA", "investorName": "Pak Indra", "sharePercentage": "30.00", "totalCapital": "30000000.00", "accumulatedReturns": "3000.00" },
                    { "investorCode": "INV-LAPAKBAYAR", "investorName": "Lapakbayar", "sharePercentage": "40.00", "totalCapital": "40000000.00", "accumulatedReturns": "4000.00" }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/finance/investor/calculations/run": {
      "post": {
        "tags": ["Investor Workspace"],
        "summary": "Hitung Bagi Hasil Investor dari Periode Keuangan CLOSED",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "example": { "periodCode": "2026-08" } } }
        },
        "responses": {
          "201": {
            "description": "Hasil kalkulasi bagi hasil terhitung (Infokom 30%, Indra 30%, Lapakbayar 40%)",
            "content": {
              "application/json": {
                "example": {
                  "periodCode": "2026-08",
                  "distributableProfit": "10000.00",
                  "status": "CALCULATED",
                  "investorResults": [
                    { "investorName": "PT Infokomexe (Infokom)", "sharePercentage": "30.00", "netReturn": "3000.00" },
                    { "investorName": "Pak Indra", "sharePercentage": "30.00", "netReturn": "3000.00" },
                    { "investorName": "Lapakbayar", "sharePercentage": "40.00", "netReturn": "4000.00" }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/finance/investor/distributions/approve": {
      "post": {
        "tags": ["Investor Workspace"],
        "summary": "Approve Distribusi & Posting Jurnal Pembayaran Return",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "example": { "periodCode": "2026-08" } } }
        },
        "responses": { "200": { "description": "Distribusi disetujui & 3 jurnal diposting" } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Masukkan Bearer token otentikasi (misal token dari bootstrapper / auth API)"
      }
    }
  }
}
