Agentic-Service-Data-Eyond-Catalog / API_CONTRACT_BE_GOLANG.md
ishaq101's picture
feat/ Endpoint Restructure (#5)
3bacc1d
|
Raw
History Blame Contribute Delete
22 kB
# 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.