diff --git a/docs_v1.0/API_V1.0.0/TRACE/TRACE_HEATMAP_SPEC_V1.0.0.md b/docs_v1.0/API_V1.0.0/TRACE/TRACE_HEATMAP_SPEC_V1.0.0.md
new file mode 100644
index 0000000..593f496
--- /dev/null
+++ b/docs_v1.0/API_V1.0.0/TRACE/TRACE_HEATMAP_SPEC_V1.0.0.md
@@ -0,0 +1,183 @@
+# Trace Heatmap Specification v1.0.0
+
+## Concept
+
+將臉部追蹤資料標準化為熱力圖格式,包含空間(畫面位置)和時間(影片進度)兩個維度。
+
+## Data Model
+
+### 1. Spatial Heatmap — 臉在哪裡?
+
+將畫面划分為 grid,計算每個 cell 的 face 活動量:
+
+```
+frame (1920×1080)
+┌──────────────────────┐
+│ ░░ ░░ ░░░░ │ y
+│ ░░░░░░░░░░░░░░ │
+│ ░░░░░░░░░░░░ │
+│ ░░░░░░░░ │ ← 活動集中在畫面中央
+│ ░░ │
+└──────────────────────┘
+ x →
+```
+
+### 2. Temporal Heatmap — 什麼時候有臉?
+
+```
+face_density
+ │ ██ ████ ██
+ │ ██ ██ ████ ██ ██
+ │ ██ ██ ██████ ██ ██
+ └──────────────────────────→ time
+ 0s 3000s 6000s
+```
+
+## API Design
+
+### GET /api/v1/file/:file_uuid/face_trace/heatmap
+
+回傳標準化熱力圖資料。
+
+#### Query Parameters
+
+| Param | Type | Default | Description |
+|-------|------|---------|-------------|
+| `type` | enum | `spatial` | `spatial` \| `temporal` \| `combined` |
+| `grid_x` | int | 20 | Spatial: X axis grid cells |
+| `grid_y` | int | 12 | Spatial: Y axis grid cells |
+| `bin_sec` | int | 60 | Temporal: time bucket in seconds |
+| `time_start` | float | 0 | Time range start (seconds) |
+| `time_end` | float | — | Time range end (default: video duration) |
+| `min_confidence` | float | 0.5 | Minimum detection confidence |
+| `trace_ids` | string | — | Comma-separated trace_id filter (optional) |
+
+#### Response: Spatial
+
+```json
+{
+ "type": "spatial",
+ "frame_width": 1920,
+ "frame_height": 1080,
+ "grid_x": 20,
+ "grid_y": 12,
+ "cell_w": 96,
+ "cell_h": 90,
+ "data": [
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 1, 3, 5, 8, 12, 14, 10, 6, 3, 1, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 1, 4, 8, 15, 25, 35, 40, 32, 20, 10, 4, 1, 0, 0, 0, 0, 0],
+ ...
+ ],
+ "max_value": 40,
+ "total_detections": 108204,
+ "total_traces": 6892
+}
+```
+
+#### Response: Temporal
+
+```json
+{
+ "type": "temporal",
+ "bin_sec": 60,
+ "duration": 5954,
+ "bins": [
+ {"t_start": 0, "t_end": 60, "face_count": 45, "trace_count": 12, "avg_confidence": 0.82},
+ {"t_start": 60, "t_end": 120, "face_count": 120, "trace_count": 28, "avg_confidence": 0.79},
+ ...
+ ]
+}
+```
+
+#### Response: Combined
+
+```json
+{
+ "type": "combined",
+ "bin_sec": 60,
+ "grid_x": 20,
+ "grid_y": 12,
+ "duration": 5954,
+ "data": [
+ {
+ "t_start": 0,
+ "t_end": 60,
+ "heatmap": [[...], [...]],
+ "max_cell": 8,
+ "face_count": 45
+ },
+ ...
+ ]
+}
+```
+
+## Standardization Rules
+
+1. **Normalization**: All values normalized to 0.0–1.0 range with `max_value` for rendering
+2. **Resolution independence**: Grid size configurable, always returns `cell_w`/`cell_h`
+3. **Temporal bucketing**: Default 60s bins, adjustable
+4. **Filterable**: By time range, confidence, specific traces
+5. **Cachable**: Response includes `file_uuid` + query hash for CDN/Redis cache
+
+## Frontend Rendering
+
+### Spatial Heatmap (Canvas)
+
+```javascript
+function renderHeatmap(canvas, data) {
+ const cellW = canvas.width / data.grid_x;
+ const cellH = canvas.height / data.grid_y;
+ for (let y = 0; y < data.grid_y; y++) {
+ for (let x = 0; x < data.grid_x; x++) {
+ const intensity = data.data[y][x] / data.max_value;
+ ctx.fillStyle = `rgba(255, 0, 0, ${intensity})`;
+ ctx.fillRect(x * cellW, y * cellH, cellW, cellH);
+ }
+ }
+}
+```
+
+### Temporal Heatmap (SVG)
+
+```svg
+
+
+```
+
+## Implementation
+
+### Backend (src/api/trace_agent_api.rs)
+
+Add new route:
+```rust
+.route("/api/v1/file/:file_uuid/face_trace/heatmap", get(list_trace_heatmap))
+```
+
+### SQL (spatial)
+
+```sql
+SELECT
+ FLOOR(x / $grid_w) AS cell_x,
+ FLOOR(y / $grid_h) AS cell_y,
+ COUNT(*) AS intensity
+FROM dev.face_detections
+WHERE file_uuid = $1 AND confidence >= $2
+GROUP BY cell_x, cell_y
+ORDER BY cell_x, cell_y;
+```
+
+### SQL (temporal)
+
+```sql
+SELECT
+ FLOOR(frame_number / ($fps * $bin_sec)) AS bin,
+ COUNT(*) AS face_count,
+ COUNT(DISTINCT trace_id) AS trace_count,
+ AVG(confidence) AS avg_confidence
+FROM dev.face_detections
+WHERE file_uuid = $1 AND confidence >= $2
+GROUP BY bin
+ORDER BY bin;
+```