11 KiB
11 KiB
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 <DIRECTUS_ACCESS_TOKEN> - Runtime API 目前不要求 Bearer token(公開給 snippet / SDK)
常見錯誤碼
401:缺少或無效 token403:token 有效但缺少對應 permission404:資源不存在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 |
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: stringname: string
- Body 可選:
module_type(預設visual)status(預設draft)start_atend_attargeting_config
- 注意:
experiment_key由後端系統生成(EX+timestamp)- 建立成功後會自動建立一筆「原始版本」Variant
PATCH /api/admin/experiments/{experiment_id}
- Path 必填:
experiment_id - Body 全部可選:
namemodule_typestatusstart_atend_attargeting_config
- 注意:
- JSON body 本身是必填(即使欄位都可選,仍需送
{}或至少一個欄位)
- 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: stringname: 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 可選:
nametraffic_weightcontent_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 其他
publishedrelease 會先降為draft - 目標 release 再升為
published
- 同 experiment 其他
POST /api/admin/releases/{release_id}/rollback
- Path 必填:
release_id - 業務行為:
- 只允許 rollback 目前
published的 release(否則409) - 會找同 experiment 中「版本號較小且非 archived」的最新 release 升為
published - rollback 完成後,會強制同 experiment 僅保留一個
published
- 只允許 rollback 目前
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: stringbase_url: string
- Body 可選:
mode(預設edit)
GET /api/editor/sessions/{session_id}
- Path 必填:
session_id
PATCH /api/editor/sessions/{session_id}
- Path 必填:
session_id - Body 可選:
statusdraft_changes
- 注意:
- JSON body 本身是必填(即使欄位都可選,仍需送
{}或至少一個欄位)
- 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_typeselector_value
EditorChangeWrite每筆可選:idselector_type(預設css)sort_order(預設0)payload
- 注意:
- 目前是「完整覆蓋」語意:request 沒帶到的舊 change 會被刪除
enabled欄位已移除
Preview
POST /api/editor/previews/build
- Body 必填:
variant_id: stringitems: EditorChangeWrite[]
- 注意:
- 欄位名稱是
items,不是changes
- 欄位名稱是
6. Runtime API
Bootstrap
POST /api/runtime/bootstrap
- Body 必填:
url: stringvisitor_id: string
- Body 可選:
site_idsite_keyuser_agent
- 注意:
site_id/site_key至少建議帶一個,否則通常拿不到 candidate experiments
Assign
POST /api/runtime/assign
- Body 必填:
visitor_idexperiment
experiment必填:experiment_idexperiment_keystatusvariants(陣列,可空但可能回422)
variants[]每筆必填:idvariant_keytraffic_weight
- 注意:
- 若
variants為空,或全部traffic_weight <= 0,會回422 No assignable variants were provided.
- 若
Payload
POST /api/runtime/payload
- Body 結構與
/assign相同(visitor_id + experiment) - 回傳包含:
assigned_variant_idassigned_variant_keypayload
Events
POST /api/runtime/events/impression
POST /api/runtime/events/conversion
- Body 必填:
visitor_idevent_name
- Body 可選:
site_idsite_keyexperiment_idexperiment_keyvariant_idvariant_keypayload
7. 資料取得時,如何判斷「是缺參數還是被規則擋」
bootstrap 回傳 candidate_experiments = [] 常見原因
site_id/site_key無法解析成站點。- 該 site 沒有
status=running的實驗。 - URL 規則不匹配(
contains/equals/starts_with/regex)。 - 裝置不匹配(
device_targets與 user-agent 判斷不一致)。 - 實驗下沒有 variants。
assign 回 422 常見原因
experiment.variants空陣列。experiment.variants全部權重為0或負值。
variants 建立/更新回 400 常見原因
- 同一 experiment 下,所有 variant 的
traffic_weight加總不等於100。
rollback 回 409 常見原因
- 你指定的 release 目前不是
published。 - 該 release 沒有更早的非 archived 版本可回退。
editor PUT changes 看起來「少資料」的常見原因
- 你沒有把舊 change id 一起送回去,會被 full-replace 刪掉。
- 你送的是
changes欄位而不是items。
8. 你在 Swagger(/docs)建議先看哪裡
- 先看
auth -> GET /api/auth/me,確認 token 與 permission 正常。 - 再看
admin/experiments與admin/variants的 request body schema。 - 看
editor -> PUT changes/POST previews/build,確認你送的是items。 - 看
runtime -> bootstrap/assign/payload的 nested schema,特別是experiment.variants[]。
9. 已知注意事項(目前版本)
API_CONTRACT_MASTER.md已同步目前路由;這份文件偏重「必填參數 + 業務限制」。- 自動化測試(P2)尚未補齊,建議以 staging smoke + 這份欄位表當暫時驗證基準。