docs: Core API 完整測試報告,所有端點實測驗證

This commit is contained in:
2026-06-14 12:39:19 +08:00
parent 3ba2120c8e
commit 6d6fd2d43c

402
docs/CORE_API_REFERENCE.md Normal file
View File

@@ -0,0 +1,402 @@
# Core API 完整測試報告
> 測試時間2026-06-14
> Base URL`http://localhost:3002`
> 所有端點均需附 `?api_key=KEY`
---
## 1. Files API
### GET /api/v1/files/scan
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `page_size` (int), `page` (int), `pattern` (string), `sort_by` (string), `sort_order` (string) |
| **HTTP** | 200 |
| **Response Key** | `files` (array) |
**欄位:**
```
file_name, relative_path, file_path, file_size, modified_time,
is_registered, file_uuid, status, registration_time, job_id
```
**注意:**
- 未註冊檔案 `file_uuid``null`Rust 需 fallback 到 `file_path`
- `status``"completed"``"unregistered"`
---
## 2. Search API
### POST /api/v1/search/llm-smart
| 項目 | 內容 |
|---|---|
| **Method** | POST |
| **Body** | `{"query": "string", "limit": int}` |
| **HTTP** | 200 |
| **Response Key** | `results` (array) |
**欄位:**
```
id, file_uuid, parent_id, scene_order, start_frame, end_frame, fps,
start_time, end_time, raw_text, summary, metadata, similarity,
file_name, serve_url, thumbnail_url
```
---
## 3. Identities API
### GET /api/v1/identities (list)
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `page` (int), `per_page` (int) |
| **HTTP** | 200 |
| **Response Key** | `identities` (array) |
**欄位:**
```
id, identity_uuid, name, metadata
```
**metadata 欄位:**
```
role, aliases, starred, tmdb_gender, tmdb_aliases, tmdb_imdb_id,
tmdb_birthday, tmdb_deathday, tmdb_homepage, tmdb_movie_id,
tmdb_biography, tmdb_character, tmdb_cast_order, tmdb_department,
tmdb_popularity, tmdb_movie_title, tmdb_place_of_birth
```
**注意:** `starred` 在 metadata 內
### GET /api/v1/identities/search
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `q` (string) |
| **HTTP** | 200 |
| **Response Key** | `results` (array) |
**欄位search result 不同於 list**
```
identity_id, name, source, tmdb_id, file_uuid, trace_id, chunk_id,
start_frame, end_frame, fps, start_time, end_time, text_content
```
---
## 4. Identity Detail API
### GET /api/v1/identity/{uuid}
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **HTTP** | 200 |
| **Response Key** | 頂層物件 |
**欄位:**
```
success, identity_uuid, name, identity_type, source, status,
metadata, reference_data, tmdb_id, tmdb_profile, created_at, updated_at
```
**注意:** `tmdb_profile` 為本地絕對路徑(如 `/Users/accusys/momentry/output/identities/{uuid}/profile.jpg`
### PATCH /api/v1/identity/{uuid} (update)
| 項目 | 內容 |
|---|---|
| **Method** | PATCH |
| **Body** | `{"name": "string"}` 或其他可更新欄位 |
| **HTTP** | 200 |
**Response**
```json
{"success": true, "identity_uuid": "...", "updated_fields": ["name"]}
```
### DELETE /api/v1/identity/{uuid}
| 項目 | 內容 |
|---|---|
| **Method** | DELETE |
| **HTTP** | 204 (成功) / 404 (找不到) |
### POST /api/v1/identity (create)
| 項目 | 內容 |
|---|---|
| **Method** | POST |
| **Body** | 需要 `face_json_path` + `identity_name` 等欄位 |
| **HTTP** | 500 (缺少必要欄位時) |
**注意:** 此 API 需要 face JSON 路徑,不是單純建立空人物。需有 face data 才能建立。
---
## 5. Identity Faces API
### GET /api/v1/identity/{uuid}/faces
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `page_size` (int) |
| **HTTP** | 200 |
| **Response Key** | `data` (array) **不是** `faces` |
**欄位data 內):**
```
id, file_uuid, frame_number, timestamp_secs, face_id, bbox, confidence
```
**Response 結構:**
```json
{
"success": true,
"identity_uuid": "...",
"name": "...",
"total": int,
"page": int,
"page_size": int,
"data": [...]
}
```
---
## 6. Identity Traces API
### GET /api/v1/identity/{uuid}/traces
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `page_size` (int) |
| **HTTP** | 200 |
| **Response Key** | `traces` (array) |
**欄位:**
```
file_uuid, trace_id, frame_count, first_frame, last_frame,
first_sec, last_sec, avg_confidence
```
**Response 結構:**
```json
{
"success": true,
"identity_uuid": "...",
"name": "...",
"total": int,
"page": int,
"page_size": int,
"total_faces": int,
"traces": [...]
}
```
---
## 7. Face Candidates API
### GET /api/v1/faces/candidates
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `page` (int), `page_size` (int) |
| **HTTP** | 200 |
| **Response Key** | `candidates` (array) |
**欄位:**
```
id, face_id, file_uuid, frame_number, confidence, bbox, attributes
```
**Response 結構:**
```json
{
"candidates": [...],
"total": int,
"page": int,
"page_size": int
}
```
---
## 8. Bind / Unbind / Merge APIs
### POST /api/v1/identity/{uuid}/bind
| 項目 | 內容 |
|---|---|
| **Method** | POST |
| **Body** | `{"face_id": "string", "file_uuid": "string"}` |
| **HTTP** | 200 |
**Response**
```json
{"success": true, "message": "Bound face ... to ...", "data": {"rows_affected": 0}}
```
**注意:** `face_id` 必須是 **string**,不能是 integer
### POST /api/v1/identity/{uuid}/unbind
| 項目 | 內容 |
|---|---|
| **Method** | POST |
| **Body** | `{"face_id": "string", "file_uuid": "string"}` |
| **HTTP** | 200 |
**Response**
```json
{"success": true, "message": "Unbound face ... from ..."}
```
### POST /api/v1/identity/{uuid}/mergeinto
| 項目 | 內容 |
|---|---|
| **Method** | POST |
| **Body** | `{"into_uuid": "string"}` |
| **HTTP** | 200 (成功) / 404 (目標不存在) |
**注意:** URL 中的 `{uuid}`**來源** identitybody 中的 `into_uuid`**目標** identity
---
## 9. Media APIs
### GET /api/v1/file/{uuid}/thumbnail
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `frame` (int, default 30) |
| **HTTP** | 200 |
| **Content-Type** | `image/jpeg` |
| **Response** | Binary image data |
### GET /api/v1/file/{uuid}/video
| 項目 | 內容 |
|---|---|
| **Method** | GET |
| **Params** | `start_time` (float), `end_time` (float), `start_frame` (int), `end_frame` (int) |
| **HTTP** | 200 |
| **Content-Type** | `video/mp4` |
| **Response** | Binary MP4 data |
| **格式** | ISO Media, MP4 Base Media v1 |
---
## API Response Key 摘要
| 端點 | Response Key | 備註 |
|---|---|---|
| `/files/scan` | `files` | |
| `/search/llm-smart` | `results` | |
| `/identities` (list) | `identities` | |
| `/identities/search` | `results` | 欄位不同於 list |
| `/identity/{uuid}` | 頂層物件 | 包含 `success` |
| `/identity/{uuid}/faces` | `data` | **不是** `faces` |
| `/identity/{uuid}/traces` | `traces` | |
| `/faces/candidates` | `candidates` | |
---
## Rust Struct 映射建議
```rust
// Files
struct FileInfo {
file_uuid: String, // null 時 fallback file_path
file_name: String,
file_size: i64,
modified_time: String,
is_registered: bool,
}
// Identities (list)
struct PersonInfo {
identity_uuid: String,
name: String,
starred: bool, // 從 metadata.starred 提取
}
// Identity detail
struct IdentityDetail {
identity_uuid: String,
name: String,
identity_type: String,
source: String,
status: String,
tmdb_id: Option<i64>,
tmdb_profile: Option<String>, // 本地路徑
created_at: String,
}
// Face (from /faces endpoint)
struct FaceInfo {
id: i64,
file_uuid: String,
frame_number: i64,
timestamp_secs: f64,
face_id: Option<String>,
bbox: Option<BBox>,
confidence: f64,
}
// Trace
struct TraceInfo {
trace_id: i64,
file_uuid: String,
frame_count: i64,
first_frame: i64,
last_frame: i64,
first_sec: f64,
last_sec: f64,
avg_confidence: f64,
}
// Face Candidate
struct FaceCandidate {
id: i64,
face_id: Option<String>,
file_uuid: String,
frame_number: i64,
confidence: f64,
bbox: Option<BBox>,
}
struct BBox {
x: f64,
y: f64,
width: f64,
height: f64,
}
// Search result (不同於 list)
struct SearchIdentityResult {
identity_id: i64,
name: String,
source: String,
tmdb_id: Option<i64>,
file_uuid: Option<String>,
trace_id: Option<i64>,
start_time: f64,
end_time: f64,
text_content: Option<String>,
}
```