# Python API 參數速查(FastAPI) 這份文件對齊目前程式實作(`backend/app/api/*` + `backend/app/schemas/*`),給你在看 `http://127.0.0.1:8000/docs` 時快速判斷: - 哪些欄位是必填 - 哪些欄位可選 - 有哪些業務限制會造成 4xx > Base URL(local):`http://127.0.0.1:8000` > API Prefix:`/api` --- ## 1. 驗證與權限 ### Authorization Header - Admin / Editor API 幾乎都需要:`Authorization: Bearer ` - 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 ` | | `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 + 這份欄位表當暫時驗證基準。