---
document_type: "implementation_guide"
service: "MOMENTRY_CORE"
title: "Momentry Core API 使用範例總覽"
date: "2026-03-26"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
tags:
  - "使用範例總覽"
  - "momentry"
  - "core"
ai_query_hints:
  - "查詢 Momentry Core API 使用範例總覽 的內容"
  - "Momentry Core API 使用範例總覽 的主要目的是什麼？"
  - "如何操作或實施 Momentry Core API 使用範例總覽？"
---

# Momentry Core API 使用範例總覽

| 項目 | 內容 |
|------|------|
| 版本 | V2.1 |
| 日期 | 2026-03-26 |
| Base URL (本地) | `http://localhost:3002` |
| Base URL (外部) | `https://api.momentry.ddns.net` |

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 |
|------|------|------|--------|
| V2.0 | 2026-03-25 | 創建完整範例總覽 | OpenCode |
| V2.1 | 2026-03-26 | 更新API回應格式 (media_url→file_path) 與認證標頭 | OpenCode |

---

## 快速參考

### 環境 URL 選擇

| 環境 | URL | 用途 |
|------|-----|------|
| **本地開發** | `http://localhost:3002` | 開發/測試，直接訪問 API |
| **外部訪問** | `https://api.momentry.ddns.net` | n8n、WordPress、curl 生產環境 |

### 所有可用端點

| 方法 | 端點 | 說明 |
|------|------|------|
| GET | `/health` | 健康檢查 |
| GET | `/health/detailed` | 詳細健康檢查 |
| POST | `/api/v1/search` | 語意搜尋（標準格式） |
| POST | `/api/v1/n8n/search` | 語意搜尋（n8n 格式） |
| POST | `/api/v1/search/hybrid` | 混合搜尋 |
| POST | `/api/v1/register` | 註冊影片 |
| POST | `/api/v1/probe` | 探測影片資訊 |
| GET | `/api/v1/videos` | 列出所有影片 |
| GET | `/api/v1/lookup` | 查詢影片 |
| GET | `/api/v1/progress/:uuid` | 處理進度 |
| GET | `/api/v1/jobs` | 任務列表 |
| GET | `/api/v1/jobs/:uuid` | 任務詳情 |

---

## 認證

### API Key

所有 `/api/v1/*` 端點需要 API Key 認證。

```bash
# 添加 API Key Header
curl -H "X-API-Key: your-api-key" http://localhost:3002/api/v1/videos

# 範例
curl -H "X-API-Key: muser_f08e13ba967e4d8ea8fc542ad9f99ac8_1774416728_90472a35" \
  http://localhost:3002/api/v1/videos
```

### 響應狀態

| 狀態碼 | 說明 |
|--------|------|
| 200 | 成功 |
| 401 | 未授權（缺少或無效 API Key） |
| 500 | 伺服器錯誤 |

### 建立 API Key

```bash
./target/release/momentry api-key create "My Key" --key-type user
```

---

## 1. curl 範例

### 基本語法

```bash
# 格式
curl [OPTIONS] URL

# 常用選項
-X METHOD    # HTTP 方法 (GET, POST, etc.)
-H HEADER    # 添加 HTTP 標頭
-d DATA      # POST 請求體
-s           # 靜默模式
-w FORMAT    # 輸出額外信息
```

### 1.1 健康檢查

```bash
# 基本健康檢查
curl http://localhost:3002/health

# 詳細健康檢查
curl http://localhost:3002/health/detailed
```

**回應**:
```json
{"status":"ok","version":"0.1.0","uptime_ms":123456}
```

### 1.2 語意搜尋

```bash
# 標準格式搜尋
curl -X POST http://localhost:3002/api/v1/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"query": "charade", "limit": 5}'

# n8n 格式搜尋（推薦）
curl -X POST http://localhost:3002/api/v1/n8n/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"query": "charade", "limit": 5}'

# 混合搜尋
curl -X POST http://localhost:3002/api/v1/search/hybrid \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"query": "charade", "limit": 5}'
```

**標準格式回應**:
```json
{
  "results": [
    {
      "uuid": "a1b10138a6bbb0cd",
      "chunk_id": "sentence_0001",
      "chunk_type": "sentence",
      "start_time": 48.8,
      "end_time": 55.44,
      "text": "fun plot twists...",
      "score": 0.92
    }
  ],
  "query": "charade"
}
```

**n8n 格式回應**:
```json
{
  "query": "charade",
  "count": 1,
  "hits": [
    {
      "id": "sentence_0001",
      "vid": "a1b10138a6bbb0cd",
      "start": 48.8,
      "end": 55.44,
      "title": "Chunk sentence_0001",
      "text": "fun plot twists...",
      "score": 0.92,
      "file_path": "/Users/accusys/momentry/var/sftpgo/data/demo/video.mp4"
    }
  ]
}
```

### 1.3 影片管理

```bash
# 列出所有影片
curl -H "X-API-Key: YOUR_API_KEY" http://localhost:3002/api/v1/videos

# 查詢特定影片（依 UUID）
curl -H "X-API-Key: YOUR_API_KEY" "http://localhost:3002/api/v1/lookup?uuid=a1b10138a6bbb0cd"

# 查詢特定影片（依路徑）
curl -H "X-API-Key: YOUR_API_KEY" "http://localhost:3002/api/v1/lookup?path=/path/to/video.mp4"

# 取得處理進度
curl -H "X-API-Key: YOUR_API_KEY" http://localhost:3002/api/v1/progress/a1b10138a6bbb0cd

# 探測影片（不註冊）
curl -X POST http://localhost:3002/api/v1/probe \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"path": "/path/to/video.mp4"}'

# 註冊影片
curl -X POST http://localhost:3002/api/v1/register \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"path": "/path/to/video.mp4"}'
```

### 1.4 批次測試腳本

```bash
#!/bin/bash
# api_test.sh - API 測試腳本

API_URL="http://localhost:3002"

echo "=== 健康檢查 ==="
curl -s "$API_URL/health" | jq .

echo -e "\n=== 語意搜尋 ==="
curl -s -X POST "$API_URL/api/v1/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"query": "charade", "limit": 3}' | jq .

echo -e "\n=== 影片列表 ==="
curl -s -H "X-API-Key: YOUR_API_KEY" "$API_URL/api/v1/videos" | jq '.videos | length'
```

### 1.5 外部 URL 範例

```bash
# 使用外部 URL（需網路可達）
curl https://api.momentry.ddns.net/health

# 外部搜尋
curl -X POST https://api.momentry.ddns.net/api/v1/n8n/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"query": "charade", "limit": 5}'
```

---

## 2. n8n 範例

### 2.1 HTTP Request Node 設定

```
Node: HTTP Request
├── URL: https://api.momentry.ddns.net/api/v1/n8n/search
├── Method: POST
├── Authentication: None
├── Send Body: ✓ (checked)
├── Content Type: JSON
├── Body:
│   {
│     "query": "={{ $json.query }}",
│     "limit": "={{ $json.limit || 10 }}"
│   }
├── Send Headers: ✓ (checked)
└── Header Parameters:
    └── X-API-Key: {{ $env.MOMENTRY_API_KEY }}
```

### 2.2 基本搜尋 Workflow

```json
{
  "name": "Momentry Video Search",
  "nodes": [
    {
      "parameters": {},
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [250, 300]
    },
    {
      "parameters": {
        "url": "https://api.momentry.ddns.net/api/v1/n8n/search",
        "method": "POST",
        "sendBody": true,
        "contentType": "json",
        "body": {
          "query": "charade",
          "limit": 3
        }
      },
      "name": "Search Video API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [450, 300]
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [[{"node": "Search Video API"}]]
    }
  }
}
```

### 2.3 Webhook 動態搜尋

```json
{
  "name": "Momentry Dynamic Search",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "search",
        "responseMode": "lastNode"
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [250, 300]
    },
    {
      "parameters": {
        "url": "https://api.momentry.ddns.net/api/v1/n8n/search",
        "method": "POST",
        "sendBody": true,
        "contentType": "json",
        "body": {
          "query": "={{ JSON.stringify($json.body.query) }}",
          "limit": "={{ $json.body.limit || 5 }}"
        }
      },
      "name": "Search API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [450, 300]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [[{"node": "Search API"}]]
    }
  }
}
```

### 2.4 測試 Webhook

```bash
# 測試模式（需先在 n8n UI 點擊 Execute）
curl -X POST http://localhost:5678/webhook-test/video-rag-mcp \
  -H "Content-Type: application/json" \
  -d '{"query":"charade","limit":3}'

# 生產環境（需 workflow 為 Active 狀態）
curl -X POST http://localhost:5678/webhook/video-rag-mcp \
  -H "Content-Type: application/json" \
  -d '{"query":"charade","limit":3}'
```

### 2.5 健康檢查 Workflow

```json
{
  "name": "Momentry Health Check",
  "nodes": [
    {
      "parameters": {},
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [250, 300]
    },
    {
      "parameters": {
        "url": "https://api.momentry.ddns.net/health",
        "method": "GET"
      },
      "name": "Health Check",
      "type": "n8n-nodes-base.httpRequest",
      "position": [450, 300]
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [[{"node": "Health Check"}]]
    }
  }
}
```

### 2.6 錯誤處理

| 錯誤 | 原因 | 解決 |
|------|------|------|
| 502 Bad Gateway | API 服務未啟動 | `sudo launchctl load /Library/LaunchDaemons/com.momentry.api.plist` |
| "Your request is invalid" | Body 格式設定錯誤 | 確認 Content Type: JSON，Body 為有效 JSON |
| 404 on webhook-test | 未執行 workflow | 在 n8n UI 點擊 "Execute workflow" |

---

## 3. WordPress 範例

### 3.1 PHP 基本用法

```php
<?php
// 搜尋影片
$api_url = 'https://api.momentry.ddns.net/api/v1/n8n/search';

$data = [
    'query' => 'charade',
    'limit' => 10
];

$response = wp_remote_post($api_url, [
    'headers' => ['Content-Type' => 'application/json'],
    'body'    => json_encode($data),
    'timeout' => 30
]);

if (is_wp_error($response)) {
    echo '錯誤: ' . $response->get_error_message();
} else {
    $body = json_decode(wp_remote_retrieve_body($response), true);
    print_r($body['hits']);
}
?>
```

### 3.2 列出影片

```php
<?php
$api_url = 'https://api.momentry.ddns.net/api/v1/videos';

$response = wp_remote_get($api_url, ['timeout' => 30]);

if (!is_wp_error($response)) {
    $body = json_decode(wp_remote_retrieve_body($response), true);
    foreach ($body['videos'] as $video) {
        echo $video['file_name'] . "\n";
    }
}
?>
```

### 3.3 查詢特定影片

```php
<?php
$uuid = 'a1b10138a6bbb0cd';
$api_url = 'https://api.momentry.ddns.net/api/v1/lookup?uuid=' . $uuid;

$response = wp_remote_get($api_url, ['timeout' => 30]);

if (!is_wp_error($response)) {
    $video = json_decode(wp_remote_retrieve_body($response), true);
    echo '檔案: ' . $video['file_name'] . "\n";
    echo '時長: ' . $video['duration'] . ' 秒';
}
?>
```

### 3.4 JavaScript fetch

```javascript
// 搜尋影片
async function searchVideos(query, limit = 10) {
    const response = await fetch('https://api.momentry.ddns.net/api/v1/n8n/search', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ query, limit })
    });
    
    if (!response.ok) {
        throw new Error('API 請求失敗');
    }
    
    return await response.json();
}

// 使用範例
searchVideos('charade', 5)
    .then(data => {
        data.hits.forEach(hit => {
            console.log(`${hit.text} (score: ${hit.score})`);
        });
    });
```

### 3.5 WordPress Shortcode

在 `functions.php` 中註冊短碼：

```php
<?php
// 將文件路徑轉換為可訪問的 URL
function convert_file_path_to_url($file_path) {
    // 範例: 將 SFTPGo 文件路徑轉換為 web URL
    // /Users/accusys/momentry/var/sftpgo/data/demo/video.mp4
    // → https://sftpgo.example.com/demo/video.mp4
    
    // 移除基本路徑
    $base_path = '/Users/accusys/momentry/var/sftpgo/data/';
    if (strpos($file_path, $base_path) === 0) {
        $relative_path = substr($file_path, strlen($base_path));
        // 替換為實際的 SFTPGo web URL
        return 'https://sftpgo.example.com/' . $relative_path;
    }
    
    // 如果無法轉換，返回原始路徑
    return $file_path;
}

// 註冊短碼
add_shortcode('momentry_search', function($atts) {
    $atts = shortcode_atts([
        'query' => '',
        'limit' => '10'
    ], $atts);
    
    if (empty($atts['query'])) {
        return '<p>請提供搜尋關鍵字</p>';
    }
    
    $response = wp_remote_post('https://api.momentry.ddns.net/api/v1/n8n/search', [
        'headers' => [
            'Content-Type' => 'application/json',
            'X-API-Key' => 'YOUR_API_KEY'  // 替換為實際的 API Key
        ],
        'body'    => json_encode([
            'query' => $atts['query'],
            'limit' => (int)$atts['limit']
        ]),
        'timeout' => 30
    ]);
    
    if (is_wp_error($response)) {
        return '<p>搜尋服務暫時無法使用</p>';
    }
    
    $data = json_decode(wp_remote_retrieve_body($response), true);
    
    if (empty($data['hits'])) {
        return '<p>找不到相關結果</p>';
    }
    
    $output = '<ul class="momentry-results">';
    foreach ($data['hits'] as $hit) {
        // 注意: API 現在返回 file_path 而非 media_url
        // 需要將文件路徑轉換為可訪問的 URL
        $file_path = $hit['file_path'];
        $video_url = convert_file_path_to_url($file_path); // 需要實作此函數
        
        $output .= sprintf(
            '<li>%s <a href="%s?start=%s">播放</a></li>',
            esc_html($hit['text']),
            $video_url,
            $hit['start']
        );
    }
    $output .= '</ul>';
    
    return $output;
});
?>
```

**使用方式**:
```
[momentry_search query="charade" limit="5"]
```

### 3.6 WordPress REST API Endpoint

在 WordPress REST API 中註冊自定義端點：

```php
<?php
// 註冊 REST API 端點
add_action('rest_api_init', function() {
    register_rest_route('momentry/v1', '/search', [
        'methods'  => 'POST',
        'callback' => function($request) {
            $response = wp_remote_post(
                'https://api.momentry.ddns.net/api/v1/n8n/search',
                [
                    'headers' => ['Content-Type' => 'application/json'],
                    'body'    => json_encode([
                        'query' => $request->get_param('query'),
                        'limit' => $request->get_param('limit', 10)
                    ])
                ]
            );
            
            if (is_wp_error($response)) {
                return new WP_Error('api_error', 'API 請求失敗');
            }
            
            return json_decode(wp_remote_retrieve_body($response));
        }
    ]);
});
?>
```

**呼叫方式**:
```
POST /wp-json/momentry/v1/search
Body: {"query": "charade", "limit": 5}
```

---

## 4. 回應格式說明

### 4.1 n8n 格式 (`/api/v1/n8n/search`)

```json
{
  "query": "charade",
  "count": 10,
  "hits": [
    {
      "id": "sentence_0001",
      "vid": "a1b10138a6bbb0cd",
      "start": 48.8,
      "end": 55.44,
      "title": "Chunk sentence_0001",
      "text": "fun plot twists...",
      "score": 0.92,
      "file_path": "/Users/accusys/momentry/var/sftpgo/data/demo/video.mp4"
    }
  ]
}
```

### 4.2 標準格式 (`/api/v1/search`)

```json
{
  "results": [
    {
      "uuid": "a1b10138a6bbb0cd",
      "chunk_id": "sentence_0001",
      "chunk_type": "sentence",
      "start_time": 48.8,
      "end_time": 55.44,
      "text": "fun plot twists...",
      "score": 0.92
    }
  ],
  "query": "charade"
}
```

### 4.3 健康檢查

```json
{
  "status": "ok",
  "version": "0.1.0",
  "uptime_ms": 123456
}
```

### 4.4 詳細健康檢查

```json
{
  "status": "ok",
  "version": "0.1.0",
  "uptime_ms": 123456,
  "services": {
    "postgres": {"status": "ok", "latency_ms": 42, "error": null},
    "redis": {"status": "ok", "latency_ms": 0, "error": null},
    "qdrant": {"status": "ok", "latency_ms": 15, "error": null},
    "mongodb": {"status": "ok", "latency_ms": 0, "error": null}
  }
}
```

### 4.5 處理進度

```json
{
  "uuid": "a1b10138a6bbb0cd",
  "file_name": "video.mp4",
  "duration": 120.5,
  "overall_progress": 75,
  "processors": [
    {"name": "asr", "status": "complete", "progress": 100},
    {"name": "cut", "status": "complete", "progress": 100},
    {"name": "yolo", "status": "progress", "progress": 35}
  ]
}
```

### 4.6 Probe 回應

```json
{
  "uuid": "a1b10138a6bbb0cd",
  "file_name": "video.mp4",
  "duration": 120.5,
  "width": 1920,
  "height": 1080,
  "fps": 30.0,
  "cached": false,
  "format": {
    "filename": "/path/to/video.mp4",
    "format_name": "mov,mp4,m4a,3gp,3g2,mj2",
    "duration": "120.5",
    "size": "12345678",
    "bit_rate": "819200"
  },
  "streams": [
    {
      "index": 0,
      "codec_name": "h264",
      "codec_type": "video",
      "width": 1920,
      "height": 1080,
      "r_frame_rate": "30/1",
      "duration": "120.5"
    }
  ]
}
```

---

## 5. HTTP 狀態碼

| 狀態 | 說明 | 解決 |
|------|------|------|
| 200 | 成功 | - |
| 400 | 請求格式錯誤 | 檢查 JSON 格式 |
| 404 | 端點或資源不存在 | 確認 URL 正確 |
| 500 | 伺服器內部錯誤 | 檢查 API 服務日誌 |
| 502 | API 服務未啟動 | 見下方說明 |

### 502 Bad Gateway 解決

```bash
# 檢查服務狀態
launchctl list | grep momentry.api

# 啟動服務
sudo launchctl load /Library/LaunchDaemons/com.momentry.api.plist

# 或使用本地測試
curl http://localhost:3002/health
```

---

## 6. 常見問題

### Q: 為什麼有兩個 URL？

| URL | 用途 |
|-----|------|
| `localhost:3002` | 直接訪問，繞過反向代理 |
| `api.momentry.ddns.net` | 通過 Caddy 反向代理 |

### Q: 兩者功能相同嗎？

是的，所有端點和功能完全相同。

### Q: n8n webhook-test 返回 404？

需在 n8n UI 中點擊 "Execute workflow" 按鈕後才能使用測試 Webhook。

### Q: 生產環境 webhook 返回 404？

需將 workflow 切換為 Active 狀態（右上角開關）。

---

## 相關文件

- [API_INDEX.md](./API_INDEX.md) - 文件總覽
- [API_ENDPOINTS.md](./API_ENDPOINTS.md) - 端點完整說明
- [API_N8N_GUIDE.md](./API_N8N_GUIDE.md) - n8n 詳細指南
- [API_WORDPRESS_GUIDE.md](./API_WORDPRESS_GUIDE.md) - WordPress 詳細指南
