Rifqi Hafizuddin
[KM-688] feat(api): v2 chat pilot + regroup report under /tools; adopt lead API contracts
ad2ce61 | # Frontend API Contract | |
| Dokumen ini merangkum endpoint Orchestration Agent Service yang dipakai oleh frontend. Fokus flow: | |
| 1. User login dan menyimpan token. | |
| 2. User menyiapkan knowledge source: upload/proses file, connect database, ingest schema, dan rebuild data catalog. | |
| 3. Setelah knowledge siap, user membuat `new analysis` dengan judul, objective, business question, dan data source binding. | |
| 4. Frontend mengirim pertanyaan ke AI Agent Service terpisah. | |
| 5. Service ini hanya merekam riwayat tanya jawab ke `analyses_messages`. | |
| Base URL lokal contoh: `http://localhost:8080` | |
| ## Konvensi | |
| Semua endpoint protected wajib memakai: | |
| ```http | |
| Authorization: Bearer <access_token> | |
| ``` | |
| Endpoint public: | |
| - `GET /health` | |
| - `POST /api/login` | |
| - `POST /api/refresh` | |
| Sebagian besar response memakai envelope: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "human-readable message", | |
| "data": {} | |
| } | |
| ``` | |
| Error response: | |
| ```json | |
| { | |
| "status": "error", | |
| "message": "error message", | |
| "data": { | |
| "code": "OPTIONAL_ERROR_CODE" | |
| } | |
| } | |
| ``` | |
| Catatan ownership: beberapa endpoint masih menerima `user_id` di body, path, atau query untuk kompatibilitas. Nilainya wajib sama dengan user dari Bearer token. | |
| ## Flow Frontend | |
| ### 1. Login | |
| Frontend memanggil `POST /api/login`, lalu simpan: | |
| - `data.user.id` sebagai `user_id` | |
| - `data.access_token` untuk header Bearer | |
| - `data.refresh_token` untuk refresh token rotation | |
| `access_token` berlaku 1 jam. `refresh_token` berlaku 7 hari dan akan diganti setiap kali refresh sukses. | |
| ### 2. Refresh Token | |
| Jika request protected menerima `401` karena token expired, panggil `POST /api/refresh` menggunakan refresh token terakhir. Setelah sukses, ganti access token dan refresh token lama dengan token baru dari response. | |
| Refresh token lama tidak boleh dipakai lagi setelah refresh sukses. | |
| ### 3. Menyiapkan Knowledge Source | |
| Frontend dapat menyediakan knowledge source dari dokumen dan/atau database. | |
| Untuk dokumen: | |
| 1. Ambil tipe file yang didukung: `GET /api/v1/documents/doctypes` | |
| 2. Upload file: `POST /api/v1/document/upload` | |
| 3. Proses dokumen: `POST /api/v1/document/process` | |
| 4. Pantau status dokumen: `GET /api/v1/documents/{user_id}` | |
| Untuk database: | |
| 1. Ambil tipe database dan schema form: `GET /api/v1/database-clients/dbtypes` | |
| 2. Simpan koneksi database: `POST /api/v1/database-clients` | |
| 3. Ingest schema database: `POST /api/v1/database-clients/{client_id}/ingest?user_id={user_id}` | |
| 4. Pantau koneksi: `GET /api/v1/database-clients/{user_id}` | |
| Setelah dokumen/database siap, frontend dapat rebuild dan membaca user data catalog: | |
| 1. `POST /api/v1/data-catalog/rebuild` | |
| 2. `GET /api/v1/data-catalog/{user_id}` | |
| ### 4. Membuat New Analysis | |
| Frontend menampilkan form: | |
| - `analysis_title` | |
| - `objective` | |
| - `business_questions` | |
| - `data_bind` | |
| `POST /api/v1/analyses` wajib menerima `analysis_title`, `objective`, `business_questions`, dan `data_bind`. `business_questions` berbentuk array string karena satu analysis dapat membawa lebih dari satu pertanyaan bisnis awal. | |
| Flow yang direkomendasikan: | |
| 1. `POST /api/v1/analyses` dengan title, objective, business_questions, dan data_bind. | |
| 2. Ambil `data.id` dari response sebagai `analysis_id`. | |
| 3. Frontend memanggil AI Agent Service terpisah memakai context analysis, business_questions, dan catalog. | |
| 4. Saat user mulai bertanya ke AI Agent Service, rekam pertanyaan dengan `role=user` ke endpoint messages. | |
| 5. Setelah AI Agent Service menjawab, simpan jawaban dengan `role=ai` ke endpoint messages. | |
| ### 5. Conversation Recording | |
| Endpoint message di service ini tidak memanggil AI agent, tidak melakukan reasoning, dan tidak membuat balasan otomatis. | |
| Frontend bertanggung jawab melakukan dua write terpisah: | |
| 1. Rekam pertanyaan user: | |
| ```json | |
| { | |
| "role": "user", | |
| "content": "Apa penyebab revenue turun di Q3?" | |
| } | |
| ``` | |
| 2. Setelah AI Agent Service menjawab, rekam jawaban agent: | |
| ```json | |
| { | |
| "role": "ai", | |
| "content": "Revenue Q3 turun terutama karena penurunan volume transaksi di segmen enterprise..." | |
| } | |
| ``` | |
| ## Endpoint Ringkas | |
| | Method | Path | Kegunaan | | |
| | --- | --- | --- | | |
| | `GET` | `/health` | Health check service | | |
| | `POST` | `/api/login` | Login dan issue token pair | | |
| | `POST` | `/api/refresh` | Rotate refresh token dan issue token pair baru | | |
| | `GET` | `/api/v1/documents/doctypes` | List tipe dokumen yang didukung | | |
| | `POST` | `/api/v1/document/upload` | Upload dokumen ke Azure Blob Storage | | |
| | `POST` | `/api/v1/document/upload-local` | Upload dokumen ke local filesystem untuk benchmark | | |
| | `POST` | `/api/v1/document/process` | Proses dokumen async | | |
| | `GET` | `/api/v1/documents/{user_id}` | List dokumen milik user | | |
| | `DELETE` | `/api/v1/document/delete` | Hapus dokumen | | |
| | `GET` | `/api/v1/database-clients/dbtypes` | List tipe database dan schema credential form | | |
| | `POST` | `/api/v1/database-clients` | Buat koneksi database | | |
| | `GET` | `/api/v1/database-clients/{user_id}` | List koneksi database user | | |
| | `GET` | `/api/v1/database-clients/{user_id}/{client_id}` | Detail koneksi database | | |
| | `PUT` | `/api/v1/database-clients/{client_id}` | Update koneksi database | | |
| | `DELETE` | `/api/v1/database-clients/{client_id}` | Hapus koneksi database | | |
| | `POST` | `/api/v1/database-clients/{client_id}/ingest` | Introspect schema database ke catalog | | |
| | `POST` | `/api/v1/data-catalog/rebuild` | Rebuild user data catalog | | |
| | `GET` | `/api/v1/data-catalog/{user_id}` | Ambil user data catalog index | | |
| | `POST` | `/api/v1/analyses` | Buat analysis baru | | |
| | `GET` | `/api/v1/analyses` | List analysis user | | |
| | `GET` | `/api/v1/analyses/{id}` | Detail analysis | | |
| | `PATCH` | `/api/v1/analyses/{id}` | Update metadata/status analysis | | |
| | `DELETE` | `/api/v1/analyses/{id}` | Hapus analysis | | |
| | `PUT` | `/api/v1/analyses/{id}/data-bind` | Update data source binding analysis | | |
| | `GET` | `/api/v1/analyses/{id}/data-catalog` | Ambil catalog yang scoped ke analysis | | |
| | `POST` | `/api/v1/analyses/{id}/data-catalog/rebuild` | Rebuild catalog scoped ke analysis dari data_bind | | |
| | `GET` | `/api/v1/analyses/{id}/messages` | Ambil riwayat pesan analysis | | |
| | `POST` | `/api/v1/analyses/{id}/messages` | Rekam satu pesan conversation | | |
| ## Auth | |
| ### `POST /api/login` | |
| Login user dengan email dan password. | |
| Request: | |
| ```json | |
| { | |
| "email": "user@example.com", | |
| "password": "password" | |
| } | |
| ``` | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "login successful", | |
| "data": { | |
| "user": { | |
| "id": "user-id", | |
| "email": "user@example.com", | |
| "fullname": "User Name", | |
| "role": "user", | |
| "status": "active" | |
| }, | |
| "access_token": "jwt-access-token", | |
| "refresh_token": "opaque-refresh-token", | |
| "token_type": "Bearer", | |
| "expires_in": 3600, | |
| "refresh_expires_in": 604800 | |
| } | |
| } | |
| ``` | |
| Errors: `400`, `401`, `403`, `404`, `500`. | |
| ### `POST /api/refresh` | |
| Menukar refresh token aktif dengan token pair baru. | |
| Request: | |
| ```json | |
| { | |
| "refresh_token": "opaque-refresh-token" | |
| } | |
| ``` | |
| Success `200` mengembalikan bentuk `data` yang sama dengan login, berisi user, access token baru, refresh token baru, `token_type`, `expires_in`, dan `refresh_expires_in`. | |
| Errors: `400`, `401`, `403`, `500`. | |
| ## Documents | |
| ### Document Model | |
| ```json | |
| { | |
| "id": "document-id", | |
| "user_id": "user-id", | |
| "filename": "sales.csv", | |
| "blob_name": "user-id/document-id/sales.csv", | |
| "file_size": 2048, | |
| "file_type": "csv", | |
| "status": "uploaded", | |
| "chunks_count": 0, | |
| "processed_at": "2026-06-30T08:00:00Z", | |
| "error_message": null, | |
| "created_at": "2026-06-30T08:00:00Z" | |
| } | |
| ``` | |
| Status umum: `uploaded`, `processing`, `processed`, `failed`. | |
| ### `GET /api/v1/documents/doctypes` | |
| Mengambil tipe dokumen yang didukung. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "supported document types", | |
| "data": [ | |
| { | |
| "type": "pdf", | |
| "max_size_mb": 10, | |
| "status": "active", | |
| "message": null | |
| } | |
| ] | |
| } | |
| ``` | |
| ### `POST /api/v1/document/upload` | |
| Upload dokumen ke Azure Blob Storage. Maksimum 10 MB. Mendukung `pdf`, `docx`, `txt`, `csv`, dan `xlsx`. | |
| Content-Type: `multipart/form-data` | |
| Form fields: | |
| | Field | Required | Keterangan | | |
| | --- | --- | --- | | |
| | `user_id` | Yes | Harus sama dengan user dari token | | |
| | `file` | Yes | File dokumen | | |
| Success `201`: `data` berisi Document Model. | |
| Errors: `400`, `401`, `403`, `429`, `500`. | |
| ### `POST /api/v1/document/upload-local` | |
| Upload file ke filesystem lokal untuk benchmarking. Kontrak form sama dengan upload Azure. | |
| Success `201`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "file saved locally", | |
| "data": { | |
| "path": "files/user-id/sales.csv" | |
| } | |
| } | |
| ``` | |
| ### `POST /api/v1/document/process` | |
| Memulai proses dokumen secara async. Untuk dokumen unstructured, service melakukan extract text dan embedding jika tersedia. Untuk dokumen tabular, service membuat parquet/catalog source. | |
| Request: | |
| ```json | |
| { | |
| "document_id": "document-id", | |
| "user_id": "user-id" | |
| } | |
| ``` | |
| Success `202`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "document processing started", | |
| "data": { | |
| "document_id": "document-id", | |
| "file_type": "csv", | |
| "status": "processing" | |
| } | |
| } | |
| ``` | |
| Pantau hasilnya lewat `GET /api/v1/documents/{user_id}`. | |
| Errors: `400`, `401`, `403`, `404`, `500`. | |
| ### `GET /api/v1/documents/{user_id}` | |
| List dokumen milik user. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "documents", | |
| "data": [] | |
| } | |
| ``` | |
| Errors: `401`, `403`, `500`. | |
| ### `DELETE /api/v1/document/delete` | |
| Menghapus dokumen dari storage, embedding/parquet terkait, dan record database. | |
| Request: | |
| ```json | |
| { | |
| "document_id": "document-id", | |
| "user_id": "user-id" | |
| } | |
| ``` | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "document deleted" | |
| } | |
| ``` | |
| Errors: `400`, `401`, `403`, `404`, `500`. | |
| ## Database Clients | |
| ### DB Client Model | |
| ```json | |
| { | |
| "id": "client-id", | |
| "user_id": "user-id", | |
| "name": "Analytics Warehouse", | |
| "db_type": "postgres", | |
| "status": "active", | |
| "created_at": "2026-06-30T08:00:00Z", | |
| "updated_at": "2026-06-30T08:00:00Z" | |
| } | |
| ``` | |
| ### `GET /api/v1/database-clients/dbtypes` | |
| Mengambil tipe database dan daftar field credential untuk render form dinamis. Saat ini `postgres` aktif; tipe lain dapat muncul sebagai `inactive`. | |
| ### `POST /api/v1/database-clients` | |
| Menyimpan koneksi database. Credentials disimpan terenkripsi. Jika koneksi dengan identity yang sama sudah ada, response `200` mengembalikan client existing. | |
| Request: | |
| ```json | |
| { | |
| "user_id": "user-id", | |
| "name": "Analytics Warehouse", | |
| "db_type": "postgres", | |
| "credentials": { | |
| "host": "db.example.com", | |
| "port": 5432, | |
| "database": "analytics", | |
| "username": "db_user", | |
| "password": "db_password", | |
| "ssl_mode": "require" | |
| } | |
| } | |
| ``` | |
| Success: | |
| - `201`: database client created | |
| - `200`: database client already exists | |
| Errors: `400`, `401`, `403`, `429`, `500`. | |
| ### `GET /api/v1/database-clients/{user_id}` | |
| List koneksi database milik user. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "database clients", | |
| "data": [] | |
| } | |
| ``` | |
| Errors: `401`, `403`, `500`. | |
| ### `GET /api/v1/database-clients/{user_id}/{client_id}` | |
| Ambil detail satu koneksi database. Success `200` dengan `data` berisi DB Client Model. | |
| Errors: `401`, `403`, `404`, `500`. | |
| ### `PUT /api/v1/database-clients/{client_id}?user_id={user_id}` | |
| Update nama, credentials, atau status koneksi. Semua field body optional, tetapi body harus JSON valid. | |
| Request: | |
| ```json | |
| { | |
| "name": "Updated Warehouse", | |
| "credentials": { | |
| "host": "db.example.com", | |
| "port": 5432, | |
| "database": "analytics", | |
| "username": "db_user", | |
| "password": "new_password", | |
| "ssl_mode": "require" | |
| }, | |
| "status": "active" | |
| } | |
| ``` | |
| Success `200`: `data` berisi DB Client Model. | |
| Errors: `400`, `401`, `403`, `404`, `500`. | |
| ### `DELETE /api/v1/database-clients/{client_id}?user_id={user_id}` | |
| Menghapus koneksi database dan memicu pembersihan catalog. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "database client deleted" | |
| } | |
| ``` | |
| Errors: `400`, `401`, `403`, `404`, `500`. | |
| ### `POST /api/v1/database-clients/{client_id}/ingest?user_id={user_id}` | |
| Melakukan introspection schema database dan menyimpan hasilnya ke catalog. Tidak membutuhkan request body. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "schema ingested", | |
| "data": { | |
| "tables": [] | |
| } | |
| } | |
| ``` | |
| Errors: `400`, `401`, `403`, `404`, `409`, `429`, `500`. | |
| ## Data Catalog | |
| ### `POST /api/v1/data-catalog/rebuild` | |
| Rebuild seluruh catalog user dari dokumen tabular dan database client aktif. | |
| Request: | |
| ```json | |
| { | |
| "user_id": "user-id" | |
| } | |
| ``` | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "catalog rebuilt", | |
| "data": { | |
| "user_id": "user-id", | |
| "schema_version": "1.0", | |
| "generated_at": "2026-06-30T08:00:00Z", | |
| "sources": [] | |
| } | |
| } | |
| ``` | |
| Errors: `400`, `401`, `403`, `429`, `500`. | |
| ### `GET /api/v1/data-catalog/{user_id}` | |
| Mengambil index catalog user. Response `sources` berisi ringkasan source, tanpa detail table penuh. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "data catalog", | |
| "data": { | |
| "user_id": "user-id", | |
| "schema_version": "1.0", | |
| "generated_at": "2026-06-30T08:00:00Z", | |
| "sources": [ | |
| { | |
| "source_id": "document-or-client-id", | |
| "source_type": "tabular", | |
| "name": "sales.csv", | |
| "location_ref": "blob/path/or/db-ref", | |
| "table_count": 1, | |
| "updated_at": "2026-06-30T08:00:00Z" | |
| } | |
| ] | |
| } | |
| } | |
| ``` | |
| Errors: `401`, `403`, `500`. | |
| ### `POST /api/v1/analyses/{id}/data-catalog/rebuild` | |
| Membangun ulang catalog khusus analysis berdasarkan `data_bind` terbaru milik analysis tersebut. Endpoint ini hanya memakai source yang ter-bind ke analysis, bukan semua knowledge source user. | |
| Gunakan endpoint ini setelah perubahan binding jika frontend ingin memicu rebuild secara eksplisit. `PUT /api/v1/analyses/{id}/data-bind` juga melakukan rebuild analysis catalog sebagai bagian dari update binding. | |
| Tidak membutuhkan request body. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "analysis catalog rebuilt", | |
| "data": { | |
| "user_id": "user-id", | |
| "schema_version": "1.0", | |
| "generated_at": "2026-06-30T08:00:00Z", | |
| "sources": [] | |
| } | |
| } | |
| ``` | |
| Errors: `400`, `401`, `404`, `500`. | |
| ### `GET /api/v1/analyses/{id}/data-catalog` | |
| Mengambil catalog yang scoped ke analysis dan mengikuti `data_bind` analysis, bukan seluruh catalog user. | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "analysis data catalog", | |
| "data": { | |
| "user_id": "user-id", | |
| "schema_version": "1.0", | |
| "generated_at": "2026-06-30T08:00:00Z", | |
| "sources": [] | |
| } | |
| } | |
| ``` | |
| Errors: `401`, `404`. | |
| ## Analyses | |
| ### Data Bind Item | |
| `data_bind` adalah daftar source yang dipilih user untuk analysis. | |
| ```json | |
| { | |
| "id": "source-id", | |
| "name": "sales.csv", | |
| "group_type": "document", | |
| "type": "csv" | |
| } | |
| ``` | |
| Field: | |
| | Field | Required | Keterangan | | |
| | --- | --- | --- | | |
| | `id` | Yes | `document.id` atau `database_client.id` | | |
| | `name` | Yes | Nama yang ditampilkan di UI | | |
| | `group_type` | Yes | `document` atau `database` | | |
| | `type` | Yes | File type (`csv`, `pdf`, `xlsx`) atau database type (`postgres`) | | |
| Rules: | |
| - `data_bind` wajib berisi minimal satu source. | |
| - Semua source harus milik user yang sedang login. | |
| - Duplicate source dalam satu `data_bind` ditolak. | |
| ### Analysis Model | |
| ```json | |
| { | |
| "id": "analysis-id", | |
| "user_id": "user-id", | |
| "analysis_title": "Q3 Revenue Analysis", | |
| "objective": "Find revenue movement and root cause", | |
| "business_questions": [ | |
| "Why did revenue drop in Q3?", | |
| "Which customer segment contributed the most to the change?" | |
| ], | |
| "status": "active", | |
| "data_bind": [ | |
| { | |
| "id": "document-id", | |
| "name": "sales.csv", | |
| "group_type": "document", | |
| "type": "csv" | |
| } | |
| ], | |
| "data_bind_version": 1, | |
| "report_collection": [], | |
| "created_at": "2026-06-30T08:00:00Z", | |
| "updated_at": "2026-06-30T08:00:00Z" | |
| } | |
| ``` | |
| ### `POST /api/v1/analyses` | |
| Membuat analysis aktif dengan source binding awal. | |
| Request: | |
| ```json | |
| { | |
| "analysis_title": "Q3 Revenue Analysis", | |
| "objective": "Find revenue movement and root cause", | |
| "business_questions": [ | |
| "Why did revenue drop in Q3?", | |
| "Which customer segment contributed the most to the change?" | |
| ], | |
| "data_bind": [ | |
| { | |
| "id": "document-id", | |
| "name": "sales.csv", | |
| "group_type": "document", | |
| "type": "csv" | |
| }, | |
| { | |
| "id": "database-client-id", | |
| "name": "Analytics Warehouse", | |
| "group_type": "database", | |
| "type": "postgres" | |
| } | |
| ] | |
| } | |
| ``` | |
| Success `201`: `data` berisi Analysis Model. | |
| Validation: | |
| - `business_questions` wajib berisi minimal satu string non-empty. | |
| - `data_bind` wajib berisi minimal satu source. | |
| Errors: `400`, `401`, `409`. | |
| ### `GET /api/v1/analyses` | |
| List analysis milik user. | |
| Query: | |
| | Query | Default | Keterangan | | |
| | --- | --- | --- | | |
| | `status` | `active` | `active` atau `inactive` | | |
| | `page` | `1` | Nomor halaman | | |
| | `limit` | `20` | Maksimum `100` | | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "Analyses retrieved", | |
| "data": { | |
| "analyses": [], | |
| "pagination": { | |
| "page": 1, | |
| "limit": 20 | |
| } | |
| } | |
| } | |
| ``` | |
| Errors: `401`, `500`. | |
| ### `GET /api/v1/analyses/{id}` | |
| Ambil detail analysis milik user. Success `200` dengan `data` berisi Analysis Model. | |
| Errors: `400`, `401`, `404`. | |
| ### `PATCH /api/v1/analyses/{id}` | |
| Update metadata analysis. Field optional. | |
| Request: | |
| ```json | |
| { | |
| "analysis_title": "Updated title", | |
| "objective": "Updated objective", | |
| "status": "inactive" | |
| } | |
| ``` | |
| `status` hanya `active` atau `inactive`. | |
| Success `200`: `data` berisi Analysis Model. | |
| Errors: `400`, `401`, `404`. | |
| ### `DELETE /api/v1/analyses/{id}` | |
| Hapus analysis milik user. | |
| Success `204` tanpa response body. | |
| Errors: `400`, `401`, `404`. | |
| ### `PUT /api/v1/analyses/{id}/data-bind` | |
| Mengganti daftar source yang ter-bind ke analysis secara atomic dengan optimistic version check. Jika update berhasil, service juga rebuild catalog scope analysis dari `data_bind` terbaru. Jika rebuild catalog gagal, perubahan binding ditolak/rollback. | |
| Request: | |
| ```json | |
| { | |
| "expected_version": 1, | |
| "data_bind": [ | |
| { | |
| "id": "new-document-id", | |
| "name": "updated-sales.csv", | |
| "group_type": "document", | |
| "type": "csv" | |
| } | |
| ] | |
| } | |
| ``` | |
| Success `200`: `data` berisi Analysis Model dengan `data_bind_version` yang sudah naik. | |
| Errors: | |
| - `400`: payload invalid, empty binding, source invalid | |
| - `401`: token invalid/missing | |
| - `409`: stale `expected_version`, inactive analysis, atau limit violation | |
| ## Analysis Messages | |
| ### Message Model | |
| ```json | |
| { | |
| "id": "message-id", | |
| "analysis_id": "analysis-id", | |
| "user_id": "user-id", | |
| "role": "user", | |
| "content": "Apa penyebab revenue turun di Q3?", | |
| "created_at": "2026-06-30T08:00:00Z" | |
| } | |
| ``` | |
| `role` hanya: | |
| - `user`: pertanyaan atau instruksi dari user | |
| - `ai`: jawaban dari AI Agent Service | |
| ### `POST /api/v1/analyses/{id}/messages` | |
| Merekam tepat satu pesan conversation ke `analyses_messages`. | |
| Request untuk pertanyaan user: | |
| ```json | |
| { | |
| "role": "user", | |
| "content": "Apa penyebab revenue turun di Q3?" | |
| } | |
| ``` | |
| Request untuk jawaban AI: | |
| ```json | |
| { | |
| "role": "ai", | |
| "content": "Revenue turun karena penurunan transaksi enterprise dan kenaikan churn di wilayah barat." | |
| } | |
| ``` | |
| Success `201`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "Message created", | |
| "data": { | |
| "message": { | |
| "id": "message-id", | |
| "analysis_id": "analysis-id", | |
| "user_id": "user-id", | |
| "role": "user", | |
| "content": "Apa penyebab revenue turun di Q3?", | |
| "created_at": "2026-06-30T08:00:00Z" | |
| } | |
| } | |
| } | |
| ``` | |
| Errors: | |
| - `400`: invalid role/content, invalid analysis ID | |
| - `401`: token invalid/missing | |
| - `409`: inactive analysis atau message limit tercapai | |
| ### `GET /api/v1/analyses/{id}/messages` | |
| Mengambil riwayat conversation analysis. | |
| Query: | |
| | Query | Default | Keterangan | | |
| | --- | --- | --- | | |
| | `limit` | `100` | Maksimum `100` | | |
| Success `200`: | |
| ```json | |
| { | |
| "status": "success", | |
| "message": "Messages retrieved", | |
| "data": { | |
| "messages": [] | |
| } | |
| } | |
| ``` | |
| Errors: `400`, `401`, `404`. | |
| ## Suggested Frontend Integration Sequence | |
| ### Login | |
| ```text | |
| POST /api/login | |
| store access_token, refresh_token, user.id | |
| ``` | |
| ### Upload and Process File | |
| ```text | |
| GET /api/v1/documents/doctypes | |
| POST /api/v1/document/upload | |
| POST /api/v1/document/process | |
| GET /api/v1/documents/{user_id} | |
| ``` | |
| ### Connect Database | |
| ```text | |
| GET /api/v1/database-clients/dbtypes | |
| POST /api/v1/database-clients | |
| POST /api/v1/database-clients/{client_id}/ingest?user_id={user_id} | |
| GET /api/v1/database-clients/{user_id} | |
| ``` | |
| ### Generate Knowledge Catalog | |
| ```text | |
| POST /api/v1/data-catalog/rebuild | |
| GET /api/v1/data-catalog/{user_id} | |
| ``` | |
| ### Create Analysis and Start Conversation | |
| ```text | |
| POST /api/v1/analyses with business_questions | |
| call AI Agent Service outside this service | |
| POST /api/v1/analyses/{analysis_id}/messages with role=user and content=user_question | |
| POST /api/v1/analyses/{analysis_id}/messages with role=ai and content=agent_answer | |
| GET /api/v1/analyses/{analysis_id}/messages | |
| ``` | |
| ## Important Frontend Notes | |
| - Jangan mengirim pesan user ke `POST /api/v1/analyses/{id}/messages` dengan ekspektasi service ini akan menjawab. Endpoint ini hanya persistence. | |
| - AI Agent Service adalah service terpisah. Service ini menyimpan metadata analysis, knowledge catalog, data binding, dan history conversation. | |
| - User-level catalog berisi seluruh knowledge source user; analysis-level catalog hanya berisi source yang ada di `data_bind` analysis. | |
| - Perubahan `data_bind` akan rebuild analysis-level catalog. Frontend juga dapat memanggil endpoint rebuild analysis catalog secara eksplisit jika diperlukan. | |
| - Setelah refresh token sukses, selalu replace refresh token lama dengan refresh token baru. | |
| - Untuk endpoint yang membutuhkan `user_id`, gunakan `data.user.id` dari login dan pastikan sama dengan token aktif. | |
| - Untuk binding analysis, pakai source yang sudah berhasil diupload/diproses atau database client yang sudah diingest. | |