CONFIGURE YOUR WORKFLOW

多步流程:網站的 UI,OpenDashboard 的規則

新報名網站請先使用流程接入與自訂 UI:在流程內啟用專屬 API,不需要應用管理金鑰。本頁保留既有應用 API 的詳細合約與進階用法。

你可以在「流程管理 → 報名流程」建立步驟及發佈版本。自己的網站讀取 JSON 後,按 current_actions 顯示操作;新增步驟、增加提交次數或調整條件,不必在網站寫死階段名稱。

此功能需先部署對應版本及完成流程資料庫遷移。舊競賽及普通表單 API 保持原有合約,不會自動轉成自訂流程。

外站 UI 和 OpenDashboard 私人流程頁可以共用同一 run、版本和規則,符合三種填表/查看組合的中央保存接法。免登入新報名可以使用 /start/{slug} 公開入口,系統建立 run 並提供 /w/<token> 私人連結。已有申請仍須經可信身份核對發連結;私人連結不等於公開新建入口。

1. 身份、資料和登入怎樣分工

工作負責方
網站登入、確認使用者可管理哪宗申請你的網站
表單、答案、目前步驟及審核歷史OpenDashboard
角色、提交數量、期限及分支驗證OpenDashboard 伺服器
自己設計的 UI你的網站,根據流程 JSON 動態顯示
沒有登入系統的私人入口指定參與人的 /w/<token> 連結

API 金鑰只保留在網站伺服器。瀏覽器不能直接持有應用金鑰。網站先驗證已登入使用者與申請的歸屬,再把該使用者的 actor 匿名代碼傳給 OpenDashboard。不能接受瀏覽器自行指定別人的 actor。

一宗申請可代表個人、隊伍或一般申請。同一聯絡人可以有多宗申請,共同管理的人各有代碼及角色;這些人不需要註冊 OpenDashboard 帳號。

2. 步驟設定及版本

type功能主要設定
information須知或參考資料,不產生回覆blocks、placement、consent、next;見資訊頁
form填寫及提交questions、roles、window、submission、next
review人工審核、退回補件source、roles、approve、reject、return_to
condition按已提交答案分流rule、yes、no
notification私人頁內通知,然後繼續role、message、next
complete結束流程outcome: completed、accepted 或 rejected

表單可使用短答、長答、數值、日期、選擇題、私人附件及重複群組。角色為 participant、leader、teacher、reviewer 或 operator;角色名稱不會自動授權,建立申請時須明確分配。主辦方操作另外檢查工作區權限。

window 可省略;省略代表不限時間。填寫時使用有時區的 ISO 時間,例如 2026-12-01T09:00:00+08:00。開始時間包含該時刻,截止時刻已不接受寫入。

submission: {"mode":"multiple","min":1,"max":3} 代表同一步可獨立提交 1–3 項;single 的 max 必須為 1。所有草稿須完成提交,才可 continue。min:0 允許不提交便繼續。

審核的 source 必須是每條進入路徑都已完成的表單;return_to 只可回到同一來源表單。條件目前比較單次表單的頂層欄位,支援 eq、neq、gt、gte、lt、lte、contains 及 not_empty。不執行任意程式、遠端 URL 或 JavaScript。

草稿可以暫時不連接全部步驟。發佈時會檢查起點、所有連接、終點、條件資料來源及循環;補件回路以外的循環會被拒絕。每份流程最多 50 步。

已發佈版本固定不變。直接用管理 API 建 run 時,省略 version 會選最新版本;公開入口與流程填表金鑰固定其入口版本。已有申請固定使用開始時的版本。修改不會把新要求偷偷加到已有申請;目前不提供執行中申請的版本遷移。

3. 完整例子:建立、發佈、開始申請

以下為合成例子。下載完整流程 JSON。所有請求都從你自己的伺服器發出,沿用連接應用的測試/正式金鑰。

js
const base = 'https://registration.konnec.ai/api/apps/v1';
async function call(path, method = 'GET', body) {
  const response = await fetch(base + path, {
    method,
    headers: {
      Authorization: `Bearer ${process.env.OPENDASHBOARD_API_KEY}`,
      'Content-Type': 'application/json'
    },
    ...(body ? { body: JSON.stringify(body) } : {})
  });
  const data = await response.json();
  if (!response.ok) throw Object.assign(new Error(data.message), { data });
  return data;
}
const definition = {
  title: '項目申請', participant_kind: 'team', start: 'registration',
  nodes: [
    {
      id: 'registration', type: 'form', title: '申請資料',
      roles: ['leader', 'teacher'],
      questions: [{ key: 'project_title', type: 'short_text', title: '項目名稱', required: true, personal: false }],
      submission: { mode: 'single', min: 1, max: 1 }, next: 'review'
    },
    { id: 'review', type: 'review', title: '審核', roles: ['operator'], source: 'registration', return_to: 'registration', approve: 'accepted', reject: 'rejected' },
    { id: 'accepted', type: 'complete', title: '通過', outcome: 'accepted' },
    { id: 'rejected', type: 'complete', title: '未通過', outcome: 'rejected' }
  ]
};
const workflow = await call('/workflows', 'POST', definition);
// 保存此 operation_id;網路失敗時使用相同 id 及相同請求重試。
const publication = await call(`/workflows/${workflow.id}/publish`, 'POST', {
  draft_revision: workflow.draft_revision, operation_id: crypto.randomUUID()
});
// external_id 是你的穩定申請代碼;重試時保持全部內容相同。
const run = await call(`/workflows/${workflow.id}/runs`, 'POST', {
  version: publication.version,
  external_id: 'application_0001', respondent: 'contact_0001',
  participants: [
    { ref: 'contact_0001', roles: ['leader'] },
    { ref: 'teacher_0001', roles: ['teacher'] },
    { ref: 'reviewer_0001', roles: ['operator'] }
  ]
});

如在管理介面建立及發佈,網站只需保存 workflow.id,不用透過 API 再建立一份。此管理 API 的 start 不會代替參加者確認須知;有前置資訊頁時,run 先停在資訊頁,顯示內容後以正常 continue 操作記錄確認。流程填表 API 則在 start 前完成須知確認,見資訊頁。

external_id、respondent、ref 和 operation_id 用 4–64 個英文字母、數字、底線或連字號,不可使用姓名或電郵。

4. 自己的網站怎樣顯示及提交

js
// 你的後端先驗證 contact_0001 可管理此 run。
let current = await call(`/workflow-runs/${run.id}?actor=contact_0001`);
const step = current.definition.nodes.find(n => n.id === current.state.current);
// step.questions 是欄位 JSON;使用與普通表單相同的欄位型別及 key。
// 用 current.current_actions 決定是否顯示儲存、提交、繼續等操作。
const submit = {
  actor: 'contact_0001', node: step.id, action: 'submit',
  revision: current.revision, operation_id: crypto.randomUUID(),
  answers: { project_title: '示範項目' }
};
const result = await call(`/workflow-runs/${run.id}/actions`, 'POST', submit);
// result.item 是此項目的 id;儲存草稿、編輯及重新提交時傳 item。
current = await call(`/workflow-runs/${run.id}?actor=contact_0001`);
await call(`/workflow-runs/${run.id}/actions`, 'POST', {
  actor: 'contact_0001', node: current.state.current, action: 'continue',
  revision: current.revision, operation_id: crypto.randomUUID()
});

每個成功操作都增加 revision。如兩人同時修改,只有符合目前版本的操作會成功;收到 run_changed 時,重新讀取,再讓使用者比較/重送,不能自動把舊答案覆蓋上去。

action傳入欄位用途
saveanswers,已有項目另帶 item保存未完成草稿
submitanswers,已有項目另帶 item驗證並提交項目
reopenitem在目前表單步驟把已提交項目改回草稿
removeitem移除草稿;歷史仍保留
continue表單不需額外欄位;資訊頁可帶 accepted全部項目提交且達到最少數量後,進入下一步
approve / rejectmessage 可選審核角色決定下一步
returnmessage 必填退回來源表單補件,保留答案及歷史

每個操作必須帶 actor、node、revision 及 operation_id。私人連結的 API 由連結決定身份,不接受 actor。

網路失敗時用原 operation_id、原 revision、原內容重試。相同請求取得原結果;相同操作編號卻改了內容會收到 operation_id_reused。請保留尚未確認成功的請求,勿每次重試產生新編號。

需要多次提交時,第一次不傳 item 就建立新項目;保存回傳的 item,之後編輯同一項目必須傳入。達到 max 不可再新增。

5. 審核、補件及私人連結

js
const review = await call(`/workflow-runs/${run.id}?actor=reviewer_0001`);
await call(`/workflow-runs/${run.id}/actions`, 'POST', {
  actor: 'reviewer_0001', node: review.state.current, action: 'return',
  message: '請補充項目的實作內容。',
  revision: review.revision, operation_id: crypto.randomUUID()
});
const link = await call(`/workflow-runs/${run.id}/links`, 'POST', {
  actor: 'contact_0001', expires_at: '2027-01-01T00:00:00+08:00'
});
// link.url 可由網站顯示或由主辦方自行轉交;此 API 不發送電郵。
// 網站伺服器撤銷:
await call(`/workflow-links/${link.id}`, 'DELETE');

私人連結只允許該人對該宗申請的角色操作。資料庫只保存 token 雜湊,網址只在建立時回傳;預設 30 日到期,可另指定未來到期時間。失效、撤銷或應用停用後不能讀寫。連結持有人即獲授權,不能把它當作公開報名網址。沒有自己登入系統時,主辦方或網站後端仍須先建立申請並分配參與人。

審核補件會把來源表單項目改回草稿,attempt 增加。舊答案及操作紀錄保留。參與人修改及重新提交後,仍需 continue 才再進入審核。尚待補件的草稿不會計入已提交資料表。

6. 附件、重複群組與儀表板

長答 paragraph 可設定 max_length,整數 1–100,000;省略時維持 5,000。 流程編輯器的長答問題及重複群組長答欄位都有「最多字元數」。此設定隨版本保存, 既有申請不會自動改用新限制。自訂 UI 應讀取該值並顯示字數;後端仍會拒絕超長內容, 不會自動截斷。計數與 JavaScript string.length/HTML maxlength 一致(UTF-16 碼元;部分 emoji 佔兩個或更多字元),空格與換行也計算。這不是整宗申請的容量限制; 整宗申請仍受原有大小上限約束。

流程的私人附件型別為 file,答案是已完成的 apu_… 上傳代碼,不能傳外部網址或競賽的 upl_… 代碼。需要應用已開啟實名模式。先沿用私人上傳 API建立上傳、傳送位元組並完成驗證,再把代碼放到答案。儲存容量最大 50 MiB,始終屬個人資料。流程欄位採已發佈的 upload.max_bytes;未設定此限制的舊欄位仍為 20 MiB。提升容量不會改寫既有流程版本。

重複群組使用 repeating_group 及 fields,格式見自己的填表介面。同一組內可以有 file 欄位;所有附件都檢查應用及測試環境歸屬、大小及 digest。私人頁的附件下載網址短期有效,不應存入公開儀表板。

實名應用的原生流程可以用普通文字問題收集證件資料,包括重複群組中的隊員問題;請用 short_text/text 保留前置零及字母,並設定 personal: true。在流程表單編輯器中,對應操作是新增文字問題並勾選「個人資料」。這不會建立登入身份或授予申請存取權,網站後端仍須驗證使用者與申請的歸屬;個人資料不會進入公開報表。未實名的應用不能收集這些欄位,既有競賽 API 的欄位限制也不因此改變。

發佈回傳 collection_id;每個表單步驟有自己的 form_id。提交項目進入該合集,可在既有「連接應用」報告工作區匯入,或呼叫 /collections/<collection_id>/tables。繼續使用既有表中表分析,明確分開申請/提交項目及群組成員的計數。個人欄位和附件排除於報告資料表之外。

同一表單有多次提交時,合集 submissions 是每個已提交項目,不是申請數。申請數及各步狀態應讀取 /workflows/<id>/runs 的操作資料,在你的受保護 UI 分頁顯示;不要以提交項目數冒充申請數。

流程的表單不能透過普通 /forms/<id>/responses 提交,會收到 workflow_form_use_run_api。必須使用 run actions,才能檢查流程、身份、期限和提交數量。

7. 端點及常見問題

所有路徑以下列前綴開始:/api/apps/v1。

方法/路徑回傳或用途
GET /workflowsworkflows、next_offset
POST /workflows建立草稿,回傳 id、draft_revision
GET /workflows/:iddraft、draft_revision、published_version
PUT /workflows/:id{definition, draft_revision},版本檢查後儲存
POST /workflows/:id/publish{draft_revision, operation_id} → version、collection_id
GET /workflows/:id/versions發佈紀錄及 next_offset
GET /workflows/:id/versions/:version該版本的 definition、collection_id
POST /workflows/:id/runs{external_id,respondent,participants,version?} → id、revision、version
GET /workflows/:id/runsruns、next_offset
GET /workflows/:id/bindings?version=1發佈版本與步驟/表單對應
GET /workflow-runs/:id/export完整申請副本;須允許 data_sync
POST /workflow-runs/:id/processing-receipts通知處理結果;見同步教學
GET /workflow-runs/:id?actor=:refdefinition、state、revision、current_actions
POST /workflow-runs/:id/actions操作結果含 revision、current、status、item
GET /workflow-runs/:id/events?actor=:ref操作摘要及 next_offset
GET /workflow-runs/:id/links?actor=:ref連結摘要,不含 token
POST /workflow-runs/:id/links{actor,expires_at?} → id、url、expires_at
DELETE /workflow-links/:id撤銷連結
GET /workflow-runs/:id/files/:uploadId?actor=:ref此申請附件的短期下載網址

列表帶 offset=0&limit=25,limit 最大 100。next_offset:null 表示已到最後一頁。私人入口的權限投影及 API 是平台內部使用;外部網站使用上表的應用 API。

為何不能操作? 查看 current_actions 是否有此動作,並確認角色分配、現在步驟及開放時間。只有 server 接受的操作才會改動資料,隱藏按鈕不是權限控制。

修改流程是否影響已報名的人? 不會。只有新申請使用新版本。查看 run 的 version 取得其表單及規則,不能用最新草稿渲染舊申請。

invalid_workflow 怎樣處理? 回傳 fields 以路徑指出問題,例如 nodes.2.source。先修正連接、來源、角色或欄位,再發佈。

workflow_unavailable 是什麼? 伺服器尚未完成流程資料庫遷移,不能開始收取申請。管理員須完成部署及資料庫更新。

通知會發送電郵嗎? 目前 notification 只在授權角色的私人頁顯示。郵件、短信和外部 webhook 不是此步驟的功能。

資料是即時的嗎? 成功操作直接保存到 OpenDashboard。畫面須重新讀取取得新進度;儀表板沿用開啟/重新整理時更新的方式,不是自動推送。

網站一定要改用 OpenDashboard 的 UI 嗎? 不需要。自訂 UI 與私人頁都使用同一套規則。網站也可以保存本地副本,再使用穩定代碼及 operation_id 同步;同步排隊和重試由網站自己的伺服器負責。

公開新報名入口:設定一次,使用同一套流程

管理員可在「流程管理 → 選擇流程 → 網站接入」建立及管理入口。網站後端也可使用以下 API;金鑰不可出現在瀏覽器:

http
POST /api/apps/v1/workflow-entries
Authorization: Bearer YOUR_APP_KEY
Content-Type: application/json

{
  "id": "wen_demo_signup",
  "workflow_id": "wfl_demo",
  "version": 1,
  "slug": "demo-signup",
  "title": "示範活動報名",
  "description": "請先填寫隊伍資料,再提交作品。",
  "participant_role": "leader",
  "link_days": 90,
  "opens_at": null,
  "closes_at": null
}

先發佈 workflow,再填入實際回傳的 workflow_id 和 version。id 由接入方建立並保留;同 id、相同設定重試回傳原入口,變更設定則回傳 entry_exists。slug 全平台唯一,使用 3–80 個英文小寫、數字或連字號。入口初始 enabled=false、revision=1。

http
PATCH /api/apps/v1/workflow-entries/wen_demo_signup
Authorization: Bearer YOUR_APP_KEY
Content-Type: application/json

{"enabled": true, "revision": 1}

回傳新 revision。完全相同的重試不重複變更;過期 revision 回傳 entry_changed。GET /workflow-entries 支援 offset、每頁 25 筆及 next_offset;GET /workflow-entries/{id} 讀取設定。測試金鑰只操作測試入口,正式金鑰只操作正式入口。

入口公開網址為 /start/demo-signup。網站可以直接放這個連結,不必實作匿名申請建立及 token 管理。公開頁有每小時每 IP 10 次新建上限;成功與未知結果的重試使用同一 token,不會重建申請。run 和私人連結在同一資料庫交易建立;連結建立失敗時不留下孤立申請。token 僅以雜湊保存,私人頁按角色限制資料及操作。

匿名入口只適合單一隊長或參加者能完成所有填表步驟的流程。 participant_role 只能是 leader 或 participant;所有表單必須允許該角色,審核必須由 operator 執行,不能讓匿名報名者審核自己。需要多位指定老師或外部評審參與時,由可信後端使用原有 runs/links API 安排身份與角色。

入口固定使用已發佈版本。標題、網址、角色、時間、有效期和版本建立後不修改;需要新配置時建立新入口並停用舊入口。新流程版本不會暗中搬動既有申請。停收或截止只阻止新申請;既有私人連結仍依其有效期及各步驟期限運作。link_days 為 1–365 天,預設 30 天。應用停用、連結過期或被撤銷都會拒絕繼續存取。

兩個填表介面怎樣接同一宗申請?

公開入口只建立新申請,不使用姓名或電郵認領舊資料。外站登入用戶需要兩邊繼續修改時,最簡單的接法是由外站可信後端先建立 run、保存 user → run/actor 對應,再發該 run 的私人連結。外站 UI 用 workflow-runs 操作 API,OpenDashboard 私人頁也更新該 run;雙方都帶目前 revision,衝突時核對並重試。

從匿名公開入口開始的申請,不會自動連到外站帳戶。若後續要綁定,必須另做可信的歸屬核驗;不能僅憑客戶端傳來的 run_id 授權。若外站只是「開始報名」按鈕,直接跳轉公開入口便不需要這項帳戶綁定。

表單數量、資料及查看權限

每個表單步驟在發佈時產生一張版本專用表單。需要兩張表便設定「隊伍報名」「作品」兩個表單步驟;作品一、二放同一張作品表的欄位/分區。多個 UI 不增加表單或申請副本。來源 intake 則保留其原本綁定的表單,不混入 workflow 產生的表單。

管理入口設定需要 edit_boards;讀取申請狀態、答案及附件需要 read_personal。公開頁只回傳報名說明和開放狀態,不回傳隊伍名單。對外展示資料使用安全報表 API/報告連結,不能把管理員答案端點直接公開。

流程資料副本

外站需要接收 OpenDashboard 報名與作品資料時,使用流程資料同步:核對表單與步驟對應、沿用固定申請編號,並在「網站接入」設定資料變更通知。

流程儀表板

在「流程管理 → 選取流程 → 儀表板」按「建立流程儀表板」,可建立初始統計,之後在同一分頁開啟已有儀表板。它沿用既有儀表板編輯器及工作區儲存,不需要外站再傳一份分析資料。建立後等候「已儲存」才離開;若有人同時編輯工作區,請重新載入後再試,系統不會覆蓋對方版本。

  • 申請總覽:每個 workflow run 一行,跨該流程的已發佈版本。尚未提交的申請仍在總數中;「已有表單提交」不代表報名完整。
  • 步驟進度:每宗申請的每個表單步驟一行,分開未填、草稿、部分提交、已提交及待補件。條件分支未經過的步驟不視為已提交。
  • 提交明細:每個正式提交項目一行。可多次提交的步驟可能有多行,不能把行數直接當隊伍數。
  • 重複項目明細:每個頂層重複群組項目一行,例如隊員;不是全流程的去重人數。附件內容不會進入分析。

申請透過不可反查的分析識別碼關聯;版本欄位可供圖表篩選。答案只包含其發佈版本允許分析的數字、日期、布林及簡單文字/選項欄位,姓名、聯絡資料、私人欄位及附件不作分析欄位。預設統計不需解除私人欄位設定。內層巢狀群組及多選展開目前不提供分析明細。

開啟工作區或按「更新流程資料」時,使用當前登入者的權限讀取。來源資料列不寫入儀表板工作區;只保存版面、欄位定義和指標。read_personal 允許查看,建立/編輯另外需要 edit_boards。外站填表金鑰不能讀取管理員的分析端點。既有對外分享仍使用確認後的固定快照,不提供即時流程資料;個人報告連結不能使用這類職員儀表板。

一般使用者毋須操作 API。管理介面使用登入保護的 GET /api/admin-workflow-analytics?app=APP&workflow=WORKFLOW&test=0,回傳 workflow、versions、readAt、tables;view=summary 只列出已關聯的儀表板。此端點不是 /api/apps/v1 的外站合約。每宗申請從一次已保存的狀態讀取;跨申請讀取期間仍可能有新提交。單次分析最多 10,000 明細列,超出時明確拒絕,不能將截斷結果當成全部統計。

這項功能不會建立參加者申請、不發佈流程、不改動公開入口或通知設定,也不遷移原站主導的既有接駁。舊式原站主導的接駁保持原有合集及同步;新建的中央流程使用標準流程儀表板。