Files
mkt.ose.tw/docs/backend/PYTHON_API_PARAMETER_GUIDE.md

408 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Python API 參數速查FastAPI
這份文件對齊目前程式實作(`backend/app/api/*` + `backend/app/schemas/*`),給你在看 `http://127.0.0.1:8000/docs` 時快速判斷:
- 哪些欄位是必填
- 哪些欄位可選
- 有哪些業務限制會造成 4xx
> Base URLlocal`http://127.0.0.1:8000`
> API Prefix`/api`
---
## 1. 驗證與權限
### Authorization Header
- Admin / Editor API 幾乎都需要:`Authorization: Bearer <DIRECTUS_ACCESS_TOKEN>`
- Runtime API 目前不要求 Bearer token公開給 snippet / SDK
### 常見錯誤碼
- `401`:缺少或無效 token
- `403`token 有效但缺少對應 permission
- `404`:資源不存在
- `422`:請求 body 結構不符 schema
### Permission 對照(路由層)
| 模組 | 權限旗標 |
|---|---|
| Sites | `can_manage_sites` |
| Experiments | `can_manage_experiments` |
| Variants | `can_manage_variants` |
| Releases | `can_manage_releases` |
| Goals | `can_manage_goals` |
| SDK Configs | `can_manage_sdk_configs` |
| Editor | `can_use_editor` |
---
## 2. 必要參數總表Swagger 快速對照)
> 這張表是「你在 `/docs` 要先看哪個欄位必填」的最短路徑。
| 端點 | 必要 Path / Query | 必要 Body | 主要限制 |
|---|---|---|---|
| `GET /api/auth/me` | 無 | 無 | 必須帶 `Authorization: Bearer <token>` |
| `POST /api/admin/experiments` | 無 | `site_id`, `name` | `experiment_key` 系統生成,不可自填 |
| `PATCH /api/admin/experiments/{experiment_id}` | `experiment_id` | JSON body欄位可全選填 | body 本身必帶(可傳 `{}` |
| `POST /api/admin/variants` | 無 | `experiment_id`, `name` | 權重總和必須 = 100 |
| `PATCH /api/admin/variants/{variant_id}` | `variant_id` | JSON body欄位可全選填 | body 本身必帶(可傳 `{}`);若改 `traffic_weight` 需滿足總和 = 100 |
| `POST /api/admin/releases/build` | 無 | `experiment_id` | 會產生新 `draft` release`version_no` 遞增 |
| `POST /api/editor/sessions` | 無 | `variant_id`, `base_url` | 需 editor 權限 |
| `PATCH /api/editor/sessions/{session_id}` | `session_id` | JSON body`status`/`draft_changes` 皆可不帶) | body 本身必帶(可傳 `{}` |
| `PUT /api/editor/variants/{variant_id}/changes` | `variant_id` | `items[]` | `items[].change_type``items[].selector_value` 必填;整包 full-replace |
| `POST /api/editor/previews/build` | 無 | `variant_id`, `items[]` | 欄位名稱必須是 `items`(不是 `changes` |
| `POST /api/runtime/bootstrap` | 無 | `url`, `visitor_id` | 實務上建議必帶 `site_id``site_key`,否則常拿不到候選實驗 |
| `POST /api/runtime/assign` | 無 | `visitor_id`, `experiment` | `experiment``experiment_id/experiment_key/status/variants[]` 必填;無可分流 variant 會 `422` |
| `POST /api/runtime/payload` | 無 | 同 `/assign` | 同 `/assign`;回傳 assigned variant + payload |
| `POST /api/runtime/events/impression|conversion` | 無 | `visitor_id`, `event_name` | 其餘欄位可選(建議盡量帶 site/experiment/variant |
---
## 3. Health / Auth
### `GET /health`
- 必填:無
- 用途:服務存活檢查
### `GET /health/ready`
- 必填:無
- 用途環境就緒檢查DB URL / Directus URL / Token
### `GET /api/auth/me`
- 必填 Header`Authorization`
- 回傳:目前使用者與 permission context
---
## 4. Admin API實際已掛載
## Sites
### `GET /api/admin/sites`
- 必填:無(需 Authorization
### `GET /api/admin/sites/{site_id}`
- Path 必填:`site_id`
## Experiments
### `GET /api/admin/experiments`
- 必填:無
### `GET /api/admin/experiments/{experiment_id}`
- Path 必填:`experiment_id`
### `POST /api/admin/experiments`
- Body 必填:
- `site_id: string`
- `name: string`
- Body 可選:
- `module_type`(預設 `visual`
- `status`(預設 `draft`
- `start_at`
- `end_at`
- `targeting_config`
- 注意:
- `experiment_key` 由後端系統生成(`EX+timestamp`
- 建立成功後會自動建立一筆「原始版本」Variant
### `PATCH /api/admin/experiments/{experiment_id}`
- Path 必填:`experiment_id`
- Body 全部可選:
- `name`
- `module_type`
- `status`
- `start_at`
- `end_at`
- `targeting_config`
- 注意:
- JSON body 本身是必填(即使欄位都可選,仍需送 `{}` 或至少一個欄位)
### `GET /api/admin/experiments/{experiment_id}/activity`
- Path 必填:`experiment_id`
- 用途:讀 Directus activity log操作紀錄
## Variants
### `GET /api/admin/variants`
- Query 可選:
- `experiment_id`
### `GET /api/admin/variants/{variant_id}`
- Path 必填:`variant_id`
### `POST /api/admin/variants`
- Body 必填:
- `experiment_id: string`
- `name: string`
- Body 可選:
- `traffic_weight`(預設 0
- `content_config`
- 注意:
- `variant_key` 由後端系統生成(`VA+timestamp`
- 業務限制:同一 experiment 全部 variants 權重總和必須等於 100不符會 `400`
### `PATCH /api/admin/variants/{variant_id}`
- Path 必填:`variant_id`
- Body 可選:
- `name`
- `traffic_weight`
- `content_config`
- 注意:
- 若更新 `traffic_weight`,同樣會觸發總和=100 驗證
- JSON body 本身是必填(即使欄位都可選,仍需送 `{}` 或至少一個欄位)
## Releases
### `GET /api/admin/releases`
- Query 可選:
- `experiment_id`
### `GET /api/admin/releases/{release_id}`
- Path 必填:`release_id`
### `POST /api/admin/releases/build`
- Body 必填:
- `experiment_id: string`
- 用途:
- 讀取該 experiment 下所有 variant changes
- 產出 `runtime_payload`
- 建立新 release`status=draft``version_no` 遞增)
### `POST /api/admin/releases/{release_id}/publish`
- Path 必填:`release_id`
- 業務行為:
- 同 experiment 其他 `published` release 會先降為 `draft`
- 目標 release 再升為 `published`
### `POST /api/admin/releases/{release_id}/rollback`
- Path 必填:`release_id`
- 業務行為:
- 只允許 rollback 目前 `published` 的 release否則 `409`
- 會找同 experiment 中「版本號較小且非 archived」的最新 release 升為 `published`
- rollback 完成後,會強制同 experiment 僅保留一個 `published`
### `POST /api/admin/releases/{release_id}/archive`
- Path 必填:`release_id`
- 業務行為:把 release 狀態改成 `archived`
## Goals
### `GET /api/admin/goals`
- Query 可選:
- `site_id`
### `GET /api/admin/goals/{goal_id}`
- Path 必填:`goal_id`
## SDK Configs
### `GET /api/admin/sdk-configs`
- 必填:無
### `GET /api/admin/sdk-configs/{sdk_config_id}`
- Path 必填:`sdk_config_id`
---
## 5. Editor API
## Session
### `POST /api/editor/sessions`
- Body 必填:
- `variant_id: string`
- `base_url: string`
- Body 可選:
- `mode`(預設 `edit`
### `GET /api/editor/sessions/{session_id}`
- Path 必填:`session_id`
### `PATCH /api/editor/sessions/{session_id}`
- Path 必填:`session_id`
- Body 可選:
- `status`
- `draft_changes`
- 注意:
- JSON body 本身是必填(即使欄位都可選,仍需送 `{}` 或至少一個欄位)
### `DELETE /api/editor/sessions/{session_id}`
- Path 必填:`session_id`
## Variant Changes
### `GET /api/editor/variants/{variant_id}/changes`
- Path 必填:`variant_id`
### `PUT /api/editor/variants/{variant_id}/changes`
- Path 必填:`variant_id`
- Body 必填:
- `items: EditorChangeWrite[]`
- `EditorChangeWrite` 每筆必填:
- `change_type`
- `selector_value`
- `EditorChangeWrite` 每筆可選:
- `id`
- `selector_type`(預設 `css`
- `sort_order`(預設 `0`
- `payload`
- 注意:
- 目前是「完整覆蓋」語意request 沒帶到的舊 change 會被刪除
- `enabled` 欄位已移除
## Preview
### `POST /api/editor/previews/build`
- Body 必填:
- `variant_id: string`
- `items: EditorChangeWrite[]`
- 注意:
- 欄位名稱是 `items`,不是 `changes`
---
## 6. Runtime API
## Bootstrap
### `POST /api/runtime/bootstrap`
- Body 必填:
- `url: string`
- `visitor_id: string`
- Body 可選:
- `site_id`
- `site_key`
- `user_agent`
- 注意:
- `site_id` / `site_key` 至少建議帶一個,否則通常拿不到 candidate experiments
## Assign
### `POST /api/runtime/assign`
- Body 必填:
- `visitor_id`
- `experiment`
- `experiment` 必填:
- `experiment_id`
- `experiment_key`
- `status`
- `variants`(陣列,可空但可能回 `422`
- `variants[]` 每筆必填:
- `id`
- `variant_key`
- `traffic_weight`
- 注意:
-`variants` 為空,或全部 `traffic_weight <= 0`,會回 `422 No assignable variants were provided.`
## Payload
### `POST /api/runtime/payload`
- Body 結構與 `/assign` 相同(`visitor_id + experiment`
- 回傳包含:
- `assigned_variant_id`
- `assigned_variant_key`
- `payload`
## Events
### `POST /api/runtime/events/impression`
### `POST /api/runtime/events/conversion`
- Body 必填:
- `visitor_id`
- `event_name`
- Body 可選:
- `site_id`
- `site_key`
- `experiment_id`
- `experiment_key`
- `variant_id`
- `variant_key`
- `payload`
---
## 7. 資料取得時,如何判斷「是缺參數還是被規則擋」
### `bootstrap` 回傳 `candidate_experiments = []` 常見原因
1. `site_id/site_key` 無法解析成站點。
2. 該 site 沒有 `status=running` 的實驗。
3. URL 規則不匹配(`contains/equals/starts_with/regex`)。
4. 裝置不匹配(`device_targets` 與 user-agent 判斷不一致)。
5. 實驗下沒有 variants。
### `assign` 回 `422` 常見原因
1. `experiment.variants` 空陣列。
2. `experiment.variants` 全部權重為 `0` 或負值。
### `variants` 建立/更新回 `400` 常見原因
1. 同一 experiment 下,所有 variant 的 `traffic_weight` 加總不等於 `100`
### `rollback` 回 `409` 常見原因
1. 你指定的 release 目前不是 `published`
2. 該 release 沒有更早的非 archived 版本可回退。
### `editor PUT changes` 看起來「少資料」的常見原因
1. 你沒有把舊 change id 一起送回去,會被 full-replace 刪掉。
2. 你送的是 `changes` 欄位而不是 `items`
---
## 8. 你在 Swagger/docs建議先看哪裡
1. 先看 `auth -> GET /api/auth/me`,確認 token 與 permission 正常。
2. 再看 `admin/experiments``admin/variants` 的 request body schema。
3.`editor -> PUT changes` / `POST previews/build`,確認你送的是 `items`
4.`runtime -> bootstrap/assign/payload` 的 nested schema特別是 `experiment.variants[]`
---
## 9. 已知注意事項(目前版本)
- `API_CONTRACT_MASTER.md` 已同步目前路由;這份文件偏重「必填參數 + 業務限制」。
- 自動化測試P2尚未補齊建議以 staging smoke + 這份欄位表當暫時驗證基準。