流程設計 API 與設計原則
說明怎麼用 API 建流程,以及怎麼設計。任務流轉請看任務相關主題。
名詞#
| 名詞 | 是什麼 |
|---|---|
| process(流程) | 藍圖:有哪些工作站、站與站怎麼連 |
| station(工作站) | 一個階段:進來什麼、要做到什麼、做完往哪走 |
| transition(出口) | 從某站往下一站的一條線 |
| routine(例行事務) | 把一個流程拿來實際跑的一份套用;誰處理哪一站綁在這層 |
| task(任務) | 一張票,在 routine 的各站之間流動 |
不同團隊跑同一條流程時開新的 routine,不要複製 process。
權限與共通寫法#
- 讀取(GET):組織內已認證的成員都可以。
- 新增、修改、刪除:只有組織 admin,其他人回 403
權限不足。 - 找不到資源回 404,驗證失敗回 422(
errors物件標出哪個欄位)。
export SF_KEY='<你的 API key>'
H=(-H "Authorization: Bearer $SF_KEY" -H "Accept: application/json" -H "Content-Type: application/json")
流程(process)#
| 端點 | 用途 |
|---|---|
GET https://station-flow.staging.quanhox.com.tw/api/v1/processes |
列出流程 |
POST https://station-flow.staging.quanhox.com.tw/api/v1/processes |
建立流程(admin) |
GET https://station-flow.staging.quanhox.com.tw/api/v1/processes/{id} |
流程詳情,含各站與全部出口 |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/processes/{id} |
修改(admin) |
DELETE https://station-flow.staging.quanhox.com.tw/api/v1/processes/{id} |
刪除(admin) |
GET https://station-flow.staging.quanhox.com.tw/api/v1/processes/{id}/diagram |
取得 Mermaid 流程圖 |
欄位:name(必填,組織內不可重複,≤128 字)、standard_days(標準天數)、sort_order、common_instructions(共通說明,見下)。
建立流程時,系統會自動產生四個系統站與兩條預設出口:
- 系統站:
開始(start)、結束(end)、存查(archive)、異常(exception)。系統站不能刪除。 - 預設出口:開始 → 結束、結束 → 存查。
curl -s -X POST "https://station-flow.staging.quanhox.com.tw/api/v1/processes" "${H[@]}" \
-d '{"name":"請假申請","standard_days":3}'
流程詳情的 data.transitions 攤平列出全部出口,查串線看這份。
共通說明(common_instructions)#
每一站都適用的規則,改了直接生效。站的詳情會並列回傳站自己的 execution_instructions 與流程的 process_common_instructions。
curl -s -X PUT "https://station-flow.staging.quanhox.com.tw/api/v1/processes/12" "${H[@]}" \
-d '{"common_instructions":"動手前先讀票上最新留言。"}'
工作站(station)#
| 端點 | 用途 |
|---|---|
GET https://station-flow.staging.quanhox.com.tw/api/v1/processes/{processId}/stations |
列出某流程的站 |
POST https://station-flow.staging.quanhox.com.tw/api/v1/processes/{processId}/stations |
新增站(admin) |
GET https://station-flow.staging.quanhox.com.tw/api/v1/stations/{id} |
站的詳情,含出口與共通說明 |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/stations/{id} |
修改站、串線(admin) |
DELETE https://station-flow.staging.quanhox.com.tw/api/v1/stations/{id} |
刪除站(admin;系統站回 422) |
主要欄位:
| 欄位 | 說明 |
|---|---|
name |
站名,建立時必填 |
type |
新增時只能是 normal(可省略) |
description |
這站是什麼、為什麼存在(≤2000 字) |
execution_instructions |
執行者照著做的步驟 |
standard_days、sort_order、entry_criteria、entry_data、exit_data、checklist、notes |
標準天數、排序與其他文字欄位 |
next_action_template |
選填 JSON 物件,給自動化執行者的出口提示 |
next_station_ids |
下一站 id 陣列,用來建立或刪除出口 |
next_station_names |
出口命名,key = 目標站 id,value = 出口名稱 |
previous_station_ids |
上一站 id 陣列,從反方向接線 |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/stations/{id} 是部分更新:沒帶的欄位保留原值,串線時不必把整站資料帶回去。
# 新增一站,同時接在「開始」(id 40) 後面、往「結束」(id 42) 走
curl -s -X POST "https://station-flow.staging.quanhox.com.tw/api/v1/processes/12/stations" "${H[@]}" \
-d '{"name":"主管審核","sort_order":10,"previous_station_ids":[40],
"next_station_ids":[42],
"execution_instructions":"確認假別與天數,核可選「核可」,不核可選「退回補件」。"}'
出口(transition)#
出口類別#
| 類別 | 怎麼設 | 用途 |
|---|---|---|
| 正常 | normal 出口,tone: positive(預設) |
往前推進;一站可有多條 |
| 退回 | normal 出口,tone: negative,回傳 is_return: true |
依原因退到指定站(任意站) |
| 系統動作 | 不用設定 | 每站都有:rollback(退回流轉歷史的前一站)、exception(送異常站)、jumpback(從異常站跳回指定站)。執行時呼叫任務端點,不會出現在出口清單 |
設定的出口都是 transition_type: normal;找退回類出口看 is_return。「放棄/不做」不算退回,設成正常。
建立、刪除、命名:透過工作站#
出口沒有獨立的新增端點,用 PUT https://station-flow.staging.quanhox.com.tw/api/v1/stations/{id} 處理:
| 帶的欄位 | 效果 |
|---|---|
next_station_ids(可加 next_station_names) |
ids 是這站完整的出口清單:多的新增、少的刪除,再依 names 命名 |
只帶 next_station_names |
只改既有出口的名稱,不動連線。指向沒有出口的站回 422 |
只帶 next_station_ids |
增刪連線,既有的自訂名稱保留 |
未命名的出口叫「完成」。
curl -s -X PUT "https://station-flow.staging.quanhox.com.tw/api/v1/stations/43" "${H[@]}" \
-d '{"next_station_ids":[42,44],
"next_station_names":{"42":"核可","44":"退回補件"}}'
限制:
- 不能指向自己、別的流程的站、「存查」或「異常」(422)。「結束 → 存查」是系統線,不能改名,刪掉就補不回來。
- 存查、異常不能當來源;開始、存查、異常不能用
previous_station_ids指派上一站。
讀取、設定細節、刪除單條#
| 端點 | 用途 |
|---|---|
GET https://station-flow.staging.quanhox.com.tw/api/v1/stations/{stationId}/transitions |
某站的全部出口 |
GET https://station-flow.staging.quanhox.com.tw/api/v1/transitions/{id} |
單條出口 |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/transitions/{id}(PATCH 也可以) |
設定名稱、類別、必填意見、必附資料、排序(admin) |
DELETE https://station-flow.staging.quanhox.com.tw/api/v1/transitions/{id} |
刪除單條 normal 出口(admin) |
PUT/PATCH 欄位,name、tone、comment_required、required_data 至少帶一個:
name(≤128 字)、sort_order;tone:positive/negative;comment_required:true時走這個出口必須留言。required_data:走這個出口前票上必須有的資料,最多 10 項,帶null清空。只在正常流轉時檢查,rollback、exception、jumpback 不檢查。缺資料時流轉回 422,錯誤在errors.required_data。
required_data 每項的格式:
| type | 欄位 |
|---|---|
attribute |
label(≤64 字)、key(票屬性 key,^[a-z0-9_.-]{1,64}$)、optional、選填 format(date)、pattern(正規表示式) |
attachment |
label、patterns(1–5 個檔名樣式,可用 {屬性key} 代入票屬性)、min(1–10,預設 1)、scope、optional |
project |
label;票必須綁專案,不能設成選填 |
附件的 scope:task(預設,票上任何時候附過都算)、transition(只算這次流轉附的)、station_visit(只算這次進站後附的)。退件後要交新版的出口用 station_visit。
curl -s -X PATCH "https://station-flow.staging.quanhox.com.tw/api/v1/transitions/88" "${H[@]}" \
-d '{"tone":"negative","comment_required":true,
"required_data":[{"type":"attribute","label":"假別","key":"leave_type"}]}'
刪除單條:只能刪 normal,開始站最後一個出口不能刪(422)。
Mermaid 流程圖#
GET https://station-flow.staging.quanhox.com.tw/api/v1/processes/{id}/diagram 回 {"mermaid":"graph TD ..."}。節點 id 是 S<站 id>;正常出口畫實線,退回出口畫虛線並標名稱。執行時的 rollback、exception、jumpback 不畫。
curl -s "https://station-flow.staging.quanhox.com.tw/api/v1/processes/12/diagram" "${H[@]}"
例行事務(routine)#
| 端點 | 用途 |
|---|---|
GET https://station-flow.staging.quanhox.com.tw/api/v1/routines |
列表;admin 可加 ?for_user=me 或 ?for_user=<user id> 只看某人有角色的;非 admin 一律只看到自己有角色的 |
POST https://station-flow.staging.quanhox.com.tw/api/v1/routines |
建立(admin):name(必填,組織內不可重複)、process_id(必填)、description、sort_order、owner_user_id(事務負責人,省略=建立者) |
GET https://station-flow.staging.quanhox.com.tw/api/v1/routines/{id} |
詳情,含角色清單 |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/routines/{id} |
修改 name、description、sort_order、owner_user_id(admin) |
DELETE https://station-flow.staging.quanhox.com.tw/api/v1/routines/{id} |
刪除(admin) |
事務負責人(owner_user_id)是需求方的窗口(一位、須為組織成員),自動是開始、結束、異常站的處理者,並負責存查;換人時四站換掉舊的、其他人不動。詳情回 owner({id, name} 或 null),任務詳情回 routine_owner。
curl -s -X POST "https://station-flow.staging.quanhox.com.tw/api/v1/routines" "${H[@]}" \
-d '{"name":"2026 請假","process_id":12}'
每站指派處理者#
任務只有該站綁定角色的成員能推進,admin 也一樣。開始站的角色決定誰能開票(POST https://station-flow.staging.quanhox.com.tw/api/v1/tasks 不在開始站角色裡回 403)。有兩種做法,可以混用。
做法一:每站直接指派(建議)#
| 端點 | 用途 |
|---|---|
GET https://station-flow.staging.quanhox.com.tw/api/v1/routines/{routineId}/station-assignees |
流程現行版本的每一站一列:station_id、station_name、station_type、role(id、name、is_auto,沒綁是 null)、users |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/routines/{routineId}/stations/{stationId}/assignees |
指派(admin);body {"user_ids":[...]},空陣列 = 取消指派 |
系統自動建角色(「<站名> 處理者」),成員相同就共用,沒綁站就自動刪。user_ids 必須是組織成員,否則 422。
curl -s -X PUT "https://station-flow.staging.quanhox.com.tw/api/v1/routines/7/stations/43/assignees" "${H[@]}" \
-d '{"user_ids":[5,9]}'
做法二:手動角色(同一組人管多站時)#
| 端點 | 用途 |
|---|---|
GET https://station-flow.staging.quanhox.com.tw/api/v1/routines/{routineId}/roles / POST https://station-flow.staging.quanhox.com.tw/api/v1/routines/{routineId}/roles |
列出/建立角色(name、sort_order) |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/roles/{id} / DELETE https://station-flow.staging.quanhox.com.tw/api/v1/roles/{id} |
改名/刪除角色 |
GET https://station-flow.staging.quanhox.com.tw/api/v1/roles/{id}/users |
角色成員 |
POST https://station-flow.staging.quanhox.com.tw/api/v1/roles/{id}/users |
加成員:{"user_id":5}(已在角色或不屬於組織回 422) |
DELETE https://station-flow.staging.quanhox.com.tw/api/v1/roles/{id}/users/{userId} |
移除成員 |
GET https://station-flow.staging.quanhox.com.tw/api/v1/routines/{routineId}/station-roles / POST https://station-flow.staging.quanhox.com.tw/api/v1/routines/{routineId}/station-roles |
列出/建立站與角色的綁定:{"station_id":43,"role_id":3};一站只綁一個角色,重複回 422 |
PUT https://station-flow.staging.quanhox.com.tw/api/v1/station-roles/{id} / DELETE https://station-flow.staging.quanhox.com.tw/api/v1/station-roles/{id} |
換綁的角色(role_id)/解除綁定 |
寫入都要 admin。讓系統站少了事務負責人的寫入(含成員、角色、綁定)一律 422 且不生效。手動角色和舊資料的「流程負責人」角色不會被自動刪除;換人只改角色成員,綁這個角色的站一起生效。
設計原則#
切站:換手才開站#
一個站至少要符合下面一條才值得存在,都不符合就併進前一站:
- 責任換手:下一段的執行者可能跟這段不同(看「可能」,不是看現在誰在做)。
- 要有人拍板才能繼續。
- 要等外部回覆或排程,票停在這裡是合理的。
- 這一段的耗時需要單獨看得出來。
站名寫「在做什麼」(審核),不寫「誰」,因為人會換。
人站與 agent 站#
- 判斷偏好、承擔後果的給人(定方向、驗收、對外承諾、花錢、不可逆動作);照既定標準執行的給 agent(拆規格、實作、測試、彙整、歸檔)。
- 先假設 agent 做得到,答不出「agent 憑什麼替他決定」才改成人站。人站要少而集中,例如前面拍板一次、後面驗收一次。
- 會自動撿票的 agent 不要跟人共用角色,否則 agent 會撿到該角色所有站的票。
出口#
- 有兩個以上出口的站一定要命名。名稱寫「選這條會發生什麼」,不寫「去哪一站」。
- 打回上一站重做用系統的 rollback,不要另拉一條反向線。要依原因退到不同站時才建退回出口(
tone: negative),並開comment_required。 - 送異常是給事務負責人決定票回哪一站;要跳好幾站回去或要特別處理時才用。
- 「選 X 之前一定要有 Y」用
required_data擋。只設「選這條時一定有值」的資料,可能合法空白的設下去,票會永遠送不出去。設之前先查停在這站的票缺不缺。 - 給 agent 撿的站,出口名只用文字、數字、
-、_,不放標點和空白,比對才不會出錯。
說明怎麼寫#
execution_instructions只寫「選『核可』」「選退回」,不寫「推進到 X 站」。線會改,寫死的站名漏改不會報錯,執行者只會照錯的做。- 執行者通常只看當前站的說明。每站都要遵守的規則寫進
common_instructions,或在每站重寫一次。 - 決策站寫明「撿到票就要選一個出口;拿不準就退回並寫明要改什麼」。要交檔案的站寫「流轉時附上 X」。
需求不清楚時先訪談#
除非開票時規格就完整,開始站後第一站做成「需求訪談」:問清楚目標、現有資料、限制,整理成文件附在票上,審核站要有退回訪談站的出口。先畫草圖讓需求方回「對/不對/哪裡改」,不要丟大問卷。
建置順序#
POST https://station-flow.staging.quanhox.com.tw/api/v1/processes:自動產生四個系統站與預設出口。POST https://station-flow.staging.quanhox.com.tw/api/v1/processes/{processId}/stations:逐站建立。sort_order留間隔(10、20、30),之後插站不用重編。PUT https://station-flow.staging.quanhox.com.tw/api/v1/stations/{id}:用next_station_ids串線,多出口時一起帶next_station_names。PUT https://station-flow.staging.quanhox.com.tw/api/v1/transitions/{id}:設定退回類別、必填意見、必附資料。POST https://station-flow.staging.quanhox.com.tw/api/v1/routines:建例行事務,owner_user_id帶真正的需求方窗口(四個系統站會自動有他)。- 指派每一個會停票的站;四個系統站需要別人一起處理時再加協作者。
GET https://station-flow.staging.quanhox.com.tw/api/v1/processes/{id}/diagram看整條線,GET https://station-flow.staging.quanhox.com.tw/api/v1/routines/{routineId}/station-assignees確認沒有role: null的站。
常見地雷#
owner為null的舊 routine 系統站可能沒人:漏綁「結束」無法歸檔,漏綁「存查」撤不回來。- 負責人預設是建立者,通常不是真正的窗口;建立時就帶
owner_user_id。 - 票一律從開始站建立。開始站綁會開票的委託方(或代表委託方的窗口),不是處理方。
- 上線前用一張真實的票走完全程,並實際走一次 rollback 或 exception → jumpback。「票開得出來」不等於能上線。
- 交給 agent 的站,先確認那個 agent 真的會定期查自己的待辦,否則票會停著沒人撿。