Community生產力與協作github.com

bluesmarties876/skills

Motion REST API 的完整客戶端 — 涵蓋所有 27 個已記錄端點(任務、專案、週期性任務、評論、自訂欄位、使用者、工作區、狀態與排程),並提供原始逃生艙口(含游標分頁)以處理未記錄的內容。處理 X-API-Key 驗證、游標分頁、速率限制回退,並在每次刪除前透過明確確認標誌進行保護。

skills 是什麼?

此技能提供 Motion (usemotion.com) REST API 的完整客戶端,涵蓋 27 個已記錄的端點,包含任務、專案、週期性任務、評論、自訂欄位、使用者、工作區、狀態和排程。它使用 `X-API-Key` 標頭處理認證,並在列表端點上實現游標分頁,支援 `--all` 旗標自動遍歷頁面。該技能包含速率限制回退機制,遵守 429 回應中的 `Retry-After` 標頭,並提供一個原始逃生艙口(`raw` 命令),用於任何未由指定命令覆蓋的端點。它支援 Agent 平台(如 Claude Code、Cursor 和 Codex),並透過環境變數 `MOTION_API_KEY` 注入憑證。此外,該技能為所有刪除操作強制實施明確的安全確認(`--yes` 旗標),防止意外資料遺失。

相容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/bluesmarties876/skills/tree/HEAD/api/motion-api

Installed? Explore more 生產力與協作 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Motion API

Motion (usemotion.com) REST API 的完整客戶端 — 涵蓋所有 27 個已記錄端點,包括 任務、專案、週期性任務、評論、自訂欄位、使用者、工作區、狀態和 排程,並提供一個 raw 逃生艙口以處理任何尚未記錄的內容。

何時使用此技能

當工作涉及 Motion 時使用:讀取或建立任務、列出專案、 在任務上張貼評論、管理週期性任務,或讀取工作區狀態、使用者 和排程。

憑證

一個憑證:MOTION_API_KEY。平台在腳本透過 RunWithCredentials 執行時, 會將其作為環境變數注入 — 切勿在命令列上傳遞金鑰,也切勿 列印或輸出它。

在 Motion 中的 Settings → API 下獲取金鑰。Motion 只顯示一次, 因此請立即複製。如果呼叫開始回傳 401,表示金鑰已被撤銷或重新產生,需要 更換。

注意:在使用代理模式傳遞憑證時,環境變數會包含一個非秘密的佔位符, 而實際值會被注入到對 api.usemotion.com 的請求中。新儲存的憑證 可能需要幾分鐘才能生效;立即的 401 錯誤後續成功是傳播問題, 而不是金鑰錯誤。

API 遵循的慣例

這些是決定呼叫成功或失敗的關鍵事實。

事項值
基礎 URLhttps://api.usemotion.com
認證標頭X-API-Key: <key>
健康檢查GET /v1/users/me — 返回金鑰的擁有者
路徑前綴/v1/ 適用於所有內容,除了自訂欄位是 /beta/
速率限制12 次請求/分鐘(個人),最多 120 次(團隊),企業更高
描述Github Flavored Markdown
優先級值ASAP、HIGH、MEDIUM、LOW(週期性任務:僅 HIGH/MEDIUM)
截止日期類型HARD、SOFT、NONE(週期性任務:僅 HARD/SOFT)

分頁。 列表端點接受一個 cursor 並返回一個信封:

{ "meta": { "nextCursor": "…", "pageSize": 25 }, "tasks": [ … ] }

信封鍵是 meta,下一頁欄位是 nextCursor。在任何列表命令上傳遞 --all, 腳本會自動跟隨游標,返回一個扁平陣列。

--all 在達到 100 頁 後停止並失敗,因此失控的查詢不會導致執行暫停 — 如果看到這種情況,請縮小查詢範圍。而且,如果某一頁既不是 JSON 物件也不是陣列 (已截斷,或為閘道器錯誤頁面),遍歷會 拒絕 而不是返回已取得的內容: 看起來完整但實際上是部分的列表,比錯誤更糟糕。

兩個列表端點返回裸陣列,沒有分頁 — GET /v1/statuses 和 GET /beta/workspaces/{id}/custom-fields。其他所有端點都是信封格式。

錯誤。 非 2xx 回應攜帶 {"message", "error", "statusCode"}。腳本會將該 JSON 輸出到 stderr 並以非零狀態碼退出。429 會根據 Retry-After 進行重試並回退; 400、401、403 和 404 會立即顯示且永不重試。 驗證失敗會攜帶每個欄位的 errors[] 陣列;客戶端會附加這些訊息, 以便實際原因可見。

User-Agent 是強制性的。 Motion 的邊緣會以 Cloudflare 403 (browser_signature_banned)封鎖預設的 Python-urllib/x.y 簽名, 導致請求無法到達 API。客戶端始終發送 motion-api-skill/1.0; 如果您針對此 API 編寫自己的請求,請明確設定 User-Agent, 否則您將收到令人困惑的 403 而不是真實的回應。

布林查詢參數必須是小寫。 Motion 將查詢字串解析為文字,因此 布林過濾器必須是字面量 true,而不是 Python 的 True。弄錯這個 不會被靜默忽略:API 會回應一個令人困惑的 400,該錯誤會談論相反的值 (請參閱下面的實際差異部分)。客戶端始終發送小寫字面量。

命令參考

每個命令都將 JSON 列印到 stdout。python3 motion.py <group> --help 會列出旗標。

任務

命令端點
tasks listGET /v1/tasks
tasks get <task_id>GET /v1/tasks/{id}
tasks createPOST /v1/tasks
tasks update <task_id>PATCH /v1/tasks/{id}
tasks move <task_id> --workspace-id …PATCH /v1/tasks/{id}/move
tasks delete <task_id> --yesDELETE /v1/tasks/{id}
tasks unassign <task_id> --yesDELETE /v1/tasks/{id}/assignee

tasks list 過濾器:--assignee-id、--project-id、--workspace-id、--name (不區分大小寫的子字串)、--label(單數,一個標籤名稱)、--status(可重複)、 --include-all-statuses。--status 和 --include-all-statuses 互斥 — 同時發送兩者會被 API 拒絕,CLI 會提前拒絕並顯示該訊息,而不是浪費一次請求去發送 保證的 400 錯誤。

--include-all-statuses 是查看已移出其工作區預設狀態的任務的方法 (例如,所有位於 Backlog 或 In Review 中的任務);沒有它,GET /v1/tasks 僅返回 預設狀態,列表看起來是空的。將其與 --all 結合使用,可以返回分配給某人的 每個狀態下的所有任務。

tasks create / tasks update 接受相同的欄位:--name、--workspace-id、 --due-date(ISO 8601;排程任務必需)、--duration、--status、 --project-id、--description、--priority、--label(可重複)、--assignee-id。

--duration 接受表示分鐘的整數,或字串 NONE / REMINDER (輸入時不區分大小寫,標準化為大寫)。

自動排程是三態的,區別很重要:

  • 省略兩個旗標 → 該欄位完全從請求中省略(保持不變)
  • --auto-scheduled '{"deadlineType":"HARD"}' → 將其 開啟;嵌套欄位是 startDate、deadlineType (HARD/SOFT/NONE) 和 schedule(預設 Work Hours)
  • --auto-scheduled-off → 發送明確的 null,將其 關閉

任務的狀態必須啟用自動排程,否則 API 會拒絕。

任務回應看起來像這樣 — 精簡為下方日曆工作流程所依賴的欄位:

{
  "id": "tsk_123",
  "name": "Draft Q4 plan",
  "description": "Outline the three scenarios.",
  "status": { "name": "In Progress", "isResolvedStatus": false },
  "priority": "HIGH",
  "labels": ["q4"],
  "assignees": [{ "id": "usr_1", "name": "Sam Patel" }],
  "project": { "id": "prj_1", "name": "Planning" },
  "dueDate": "2026-11-01T17:00:00.000Z",
  "duration": 45,
  "scheduledStart": "2026-10-28T09:00:00.000Z",
  "startOn": "2026-10-28",
  "completedTime": null
}

解讀為:status 是一個物件,而不是字串 — 您需要的過濾器是 status.isResolvedStatus,當任務完成或取消時它會變為 true。 assignees 和 labels 是陣列;project 是物件或 null。scheduledStart 和 dueDate 是 UTC;startOn 是純日期。

沒有日曆端點。 任務在日曆上的位置是其 scheduledStart (UTC ISO 8601),duration 以分鐘為單位,startOn 是純日期。要回答「接下來是什麼」, 擷取任務並按 scheduledStart 排序 — 不要尋找返回事件的排程端點,因為 schedules list 僅返回工作時間區間(見下文),而不是已預約的項目。 過濾掉 status.isResolvedStatus 為 true 的任務,以排除任何 已完成或已取消的項目。

專案

命令端點
projects list [--workspace-id …]GET /v1/projects
projects get <project_id>GET /v1/projects/{id}
projects create --name … --workspace-id …POST /v1/projects

projects create 也接受 --due-date、--description(接受 HTML)、--label (可重複)、--priority(伺服器端預設為 MEDIUM),以及模板配對 --project-definition-id + --stages。階段必須與定義的順序和數量 完全匹配,否則 API 會返回 400。對於較長的階段陣列,請使用 --stages @stages.json。 CLI 不強制要求配對;API 會拒絕沒有定義 ID 的階段列表。

週期性任務

命令端點
recurring-tasks list --workspace-id …GET /v1/recurring-tasks
recurring-tasks createPOST /v1/recurring-tasks
recurring-tasks delete <id> --yesDELETE /v1/recurring-tasks/{id}

recurring-tasks create 需要 --frequency、--name、--workspace-id 和 --assignee-id。可選:--deadline-type(僅 HARD/SOFT — NONE 在此處會被拒絕)、 --duration(表示分鐘的整數,或 REMINDER;此端點不接受 NONE)、--starting-on、--ideal-time(HH:mm)、--schedule(預設 Work Hours)、 --description、--priority(僅 HIGH/MEDIUM)。

--starting-on 會完全按照給定的內容發送給 API — 不會進行修剪。

--frequency 是 Motion 自有 DSL 中的字串,而不是物件。 這經常讓人困惑。詞彙表文件在 https://docs.usemotion.com/cookbooks/frequency/:

  • 日期代碼:MO、TU、WE、TH、FR、SA、SU
  • 每日:daily_every_day、daily_every_week_day、daily_specific_days_[MO, TU, FR]
  • 每週:weekly_any_day、weekly_any_week_day、weekly_specific_days_[MO, FR]
  • 隔週:biweekly_first_week_any_day、biweekly_first_week_specific_days_[MO, TU]、 biweekly_second_week_any_week_day
  • 按星期中的幾天的每月:monthly_first_MO、monthly_second_TU、monthly_last_FR
  • 按日期的每月:monthly_1、monthly_15、monthly_31(超出範圍的日期會回退 到該月的最後一天)
  • 按週的每月:monthly_any_day_first_week、monthly_any_week_day_last_week、 monthly_last_day_of_month
  • 每季:quarterly_first_day、quarterly_last_week_day、quarterly_any_day_first_week

日期陣列必須始終與頻率類型配對 — 單獨使用 [MO, FR] 是無效的。

一個完整的呼叫,因為頻率字串是最困難的部分:

python3 motion.py recurring-tasks create \
    --name "Weekly review" --workspace-id ws_1 --assignee-id usr_1 \
    --frequency "weekly_specific_days_[MO,FR]" \
    --deadline-type SOFT --duration 30 --ideal-time 16:00 \
    --schedule "Work Hours" --priority MEDIUM

請注意此處的較窄的集合:週期性任務僅接受 HIGH/MEDIUM 優先級和僅 HARD/SOFT 截止日期類型,而 API 的其他部分也允許 ASAP/LOW 和 NONE。 CLI 強制實施這兩者。

評論

命令端點
comments list --task-id …GET /v1/comments
comments create --task-id … [--content …]POST /v1/comments

--content 輸入時是 Github Flavored Markdown,返回時是 HTML。它是 可選的 — 如果沒有 --content,請求主體僅攜帶任務 ID。Motion 是否接受空評論尚未驗證;當您打算說些什麼時,請傳遞 --content。

自訂欄位 — 注意 /beta/ 前綴

命令端點
custom-fields list --workspace-id …GET /beta/workspaces/{workspaceId}/custom-fields
custom-fields create --workspace-id … --type … --name …POST /beta/workspaces/{workspaceId}/custom-fields
custom-fields delete <id> --workspace-id … --yesDELETE /beta/workspaces/{workspaceId}/custom-fields/{id}
custom-field-values add-task <task_id> …POST /beta/custom-field-values/task/{taskId}
custom-field-values add-project <project_id> …POST /beta/custom-field-values/project/{projectId}
custom-field-values delete-from-task <task_id> <value_id> --yesDELETE /beta/custom-field-values/task/{taskId}/custom-fields/{valueId}
custom-field-values delete-from-project <project_id> <value_id> --yesDELETE /beta/custom-field-values/project/{projectId}/custom-fields/{valueId}

12 種自訂欄位類型,按原樣拼寫:text、url、date、person、 multiPerson、phone、select、multiSelect、number、email、checkbox、relatedTo。

設定值需要 --custom-field-instance-id(工作區上的欄位)、--type 和 --value。--value 是 JSON,因此請正確引用它:字串用 --value '"hello"', 數字用 --value '42',多選用 --value '["A","B"]', 核取方塊用 --value 'true'。

python3 motion.py custom-field-values add-task tsk_123 \
    --custom-field-instance-id cfi_1 --type select --value '"Alpha"'

custom-fields create 接受 JSON 格式的 --metadata — format(plain/formatted/percent,僅數字)、 核取方塊的 toggle,以及選擇欄位的 options:

--metadata '{"options":[{"id":"a","value":"Alpha","color":"#ff0000"}]}'

使用者、工作區、狀態、排程

命令端點
meGET /v1/users/me
users list [--workspace-id …] [--team-id …]GET /v1/users
workspaces list [--ids …]GET /v1/workspaces
statuses list [--workspace-id …]GET /v1/statuses
schedules listGET /v1/schedules

workspaces list --ids 是可重複的,--all 會跟隨游標。

users list 必須限定範圍。 傳遞 --workspace-id 或 --team-id;腳本會提前拒絕 無範圍的呼叫並顯示該訊息,而不是浪費一次請求去發送 API 返回的 400。要列出所有人, 請遍歷您的工作區。

schedules list 返回工作時間區間,而不是事件。 每個排程都有自己的 timezone 和一個按天劃分的 {start, end} 區塊陣列 — 一天可能包含多個 區塊(例如,包含早上和晚上區塊的通學排程)。不要將其解讀為 「使用者每天有一個工作區塊」,也不要將其視為日曆;要檢視實際預約的內容, 請閱讀任務的 scheduledStart 值。

原始逃生艙口

python3 motion.py raw GET  /v1/tasks --query status=Todo --query status=Doing
python3 motion.py raw GET  /v1/tasks --query assigneeId=u1 --query includeAllStatuses=true --all
python3 motion.py raw POST /v1/comments --body '{"taskId":"t1","content":"hi"}'
python3 motion.py raw DELETE /v1/tasks/t1 --yes

對於命名命令未涵蓋的任何內容,請使用此功能。--query KEY=VALUE 是可重複的,重複 ...(為翻譯而截斷)

相關技能