Motion API
Motion(usemotion.com) REST API의 전체 클라이언트로, 다음에 걸친 27개의 문서화된 엔드포인트를 제공합니다:
작업, 프로젝트, 반복 작업, 댓글, 사용자 정의 필드, 사용자, 워크스페이스, 상태 및 일정,
그리고 아직 문서화되지 않은 모든 기능을 위한 raw 탈출구도 포함합니다.
이 스킬을 사용해야 하는 경우
작업에 Motion이 관련될 때마다 사용합니다: 작업 읽기 또는 생성, 프로젝트 목록 조회, 작업에 댓글 게시, 반복 작업 관리, 또는 워크스페이스 상태, 사용자 및 일정 읽기.
자격 증명
하나의 자격 증명, MOTION_API_KEY. 플랫폼은 RunWithCredentials를 통해 스크립트가 실행될 때
이를 환경 변수로 주입합니다 — 절대 명령줄에 키를 전달하지 말고, 절대 출력하거나 에코하지 마십시오.
Motion에서 설정 → API 아래에서 키를 얻으십시오. Motion은 한 번만 표시하므로, 즉시 복사하십시오. 호출이 401을 반환하기 시작하면 키가 취소되었거나 재생성된 것이므로 교체해야 합니다.
참고: 프록시 모드 자격 증명 전달의 경우, 환경 변수는 비밀 자리 표시자를 보유하고
실제 값은 api.usemotion.com에 대한 요청에 주입됩니다. 새로 저장된 자격 증명은
전파되는 데 몇 분이 걸릴 수 있습니다. 즉시 401이 발생했다가 나중에 성공하는 것은
잘못된 키가 아니라 전파 문제입니다.
API가 따르는 규칙
이것은 호출이 작동하는 것과 작동하지 않는 것을 구분하는 사실입니다.
| 항목 | 값 |
|---|---|
| 기본 URL | https://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"}를 전달합니다. 스크립트는
이를 stderr에 JSON으로 출력하고 0이 아닌 종료 코드로 종료합니다. 429는 Retry-After를
준수하여 백오프와 함께 재시도됩니다; 400, 401, 403 및 404는 즉시 표시되고 절대 재시도되지 않습니다.
유효성 검사 실패는 필드별 errors[] 배열을 전달합니다; 클라이언트는 실제 이유가 표시되도록
해당 메시지를 추가합니다.
User-Agent는 필수입니다. Motion의 에지는 기본 Python-urllib/x.y 서명을 차단합니다
Cloudflare 403(browser_signature_banned)으로 인해 요청이 API에 도달하기 전에.
클라이언트는 항상 motion-api-skill/1.0을 보냅니다; 이 API에 대해 자신의 요청을 작성하는 경우,
명시적으로 User-Agent를 설정하십시오. 그렇지 않으면 실제 응답 대신 혼란스러운 403을 받게 됩니다.
부울 쿼리 매개변수는 소문자여야 합니다. Motion은 쿼리 문자열을 텍스트로 구문 분석하므로,
부울 필터는 리터럴 true여야 하며 Python의 True가 아닙니다. 이것을 잘못하면
자동으로 실패하지 않습니다: API는 반대 값에 대해 이야기하는 혼란스러운 400으로 응답합니다
(아래 실시간 차이점 섹션 참조). 클라이언트는 항상 소문자 리터럴을 보냅니다.
명령 참조
모든 명령은 stdout에 JSON을 출력합니다. python3 motion.py <그룹> --help는 플래그를 나열합니다.
작업
| 명령 | 엔드포인트 |
|---|---|
tasks list | GET /v1/tasks |
tasks get <task_id> | GET /v1/tasks/{id} |
tasks create | POST /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> --yes | DELETE /v1/tasks/{id} |
tasks unassign <task_id> --yes | DELETE /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": "Q4 계획 초안",
"description": "세 가지 시나리오를 개략적으로 설명합니다.",
"status": { "name": "진행 중", "isResolvedStatus": false },
"priority": "HIGH",
"labels": ["q4"],
"assignees": [{ "id": "usr_1", "name": "Sam Patel" }],
"project": { "id": "prj_1", "name": "계획" },
"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 작업을 필터링하여 이미 완료되거나
취소된 항목을 제외하십시오.
프로젝트
| 명령 | 엔드포인트 |
|---|---|
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 create | POST /v1/recurring-tasks |
recurring-tasks delete <id> --yes | DELETE /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 "주간 검토" --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 … --yes | DELETE /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> --yes | DELETE /beta/custom-field-values/task/{taskId}/custom-fields/{valueId} |
custom-field-values delete-from-project <project_id> <value_id> --yes | DELETE /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는 --metadata를 JSON으로 사용합니다 — format (plain/formatted/percent,
숫자만), 체크박스의 경우 toggle, 선택 필드의 경우 options:
--metadata '{"options":[{"id":"a","value":"Alpha","color":"#ff0000"}]}'
사용자, 워크스페이스, 상태, 일정
| 명령 | 엔드포인트 |
|---|---|
me | GET /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 list | GET /v1/schedules |
workspaces list --ids는 반복 가능하며, --all은 커서를 따라갑니다.
users list는 범위를 지정해야 합니다. --workspace-id 또는 --team-id를 전달하십시오;
스크립트는 API가 반환하는 400에 요청을 낭비하지 않고 이 메시지와 함께 범위가 지정되지 않은
호출을 조기에 거부합니다. 모든 사람을 나열하려면 워크스페이스를 반복하십시오.
schedules list는 근무 시간 창을 반환하며 이벤트가 아닙니다. 각 일정에는 자체
timezone과 요일별 {start, end} 블록 배열이 있습니다 — 그리고 하루는 여러 개의
블록을 가질 수 있습니다 (예: 아침과 저녁이 있는 학교 운영 일정). 이것을 "사용자에게 하루에
하나의 작업 블록이 있다"로 읽지 말고 캘린더로 취급하지 마십시오. 실제로 예약된 항목은
작업 scheduledStart 값을 읽으십시오.
raw 탈출구
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는
반복 가능하며 반복은
…
(잘렸음)