Access the Motion API with managed OAuth authentication. Manage tasks, projects, workspaces, comments, and recurring tasks with full CRUD operations.
# List tasks
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/motion/v1/tasks')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/motion/{native-api-path}
Maton proxies requests to api.usemotion.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Motion OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=motion&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'motion'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "motion",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple Motion connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/motion/v1/tasks')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
GET /motion/v1/tasks
Query Parameters:
workspaceId (string) - Filter by workspaceprojectId (string) - Filter by projectassigneeId (string) - Filter by assigneestatus (array) - Filter by status (cannot combine with includeAllStatuses)includeAllStatuses (boolean) - Return tasks across all statuseslabel (string) - Filter by labelname (string) - Search task names (case-insensitive)cursor (string) - Pagination cursorExample:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/motion/v1/tasks?workspaceId=WORKSPACE_ID')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
GET /motion/v1/tasks/{taskId}
POST /motion/v1/tasks
Content-Type: application/json
{
"name": "Task name",
"workspaceId": "WORKSPACE_ID",
"dueDate": "2024-03-15T10:00:00Z",
"duration": 60,
"priority": "HIGH",
"description": "Task description in markdown",
"projectId": "PROJECT_ID",
"assigneeId": "USER_ID",
"labels": ["label1", "label2"],
"autoScheduled": {
"startDate": "2024-03-14T09:00:00Z",
"deadlineType": "SOFT",
"schedule": "Work Hours"
}
}
Required Fields:
name (string) - Task titleworkspaceId (string) - Workspace IDOptional Fields:
dueDate (datetime, ISO 8601) - Task deadline (required for scheduled tasks)duration (string | number) - "NONE", "REMINDER", or minutes (integer > 0)status (string) - Defaults to workspace default statusprojectId (string) - Associated projectdescription (string) - GitHub Flavored Markdown supportedpriority (string) - ASAP, HIGH, MEDIUM, or LOWlabels (array) - Label names to addassigneeId (string) - User ID for task assignmentautoScheduled (object) - Auto-scheduling settings with startDate, deadlineType (HARD, SOFT, NONE), and scheduleExample:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
'name': 'New task',
'workspaceId': 'WORKSPACE_ID',
'priority': 'HIGH',
'duration': 30
}).encode()
req = urllib.request.Request('https://api.maton.ai/motion/v1/tasks', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
PATCH /motion/v1/tasks/{taskId}
Content-Type: application/json
{
"name": "Updated task name",
"status": "Completed",
"priority": "LOW"
}
DELETE /motion/v1/tasks/{taskId}
POST /motion/v1/tasks/{taskId}/move
Content-Type: application/json
{
"workspaceId": "NEW_WORKSPACE_ID"
}
POST /motion/v1/tasks/{taskId}/unassign
GET /motion/v1/projects?workspaceId={workspaceId}
Query Parameters:
workspaceId (string, required) - Workspace IDcursor (string) - Pagination cursorGET /motion/v1/projects/{projectId}
POST /motion/v1/projects
Content-Type: application/json
{
"name": "Project name",
"workspaceId": "WORKSPACE_ID",
"description": "Project description",
"dueDate": "2024-06-30T00:00:00Z",
"priority": "HIGH",
"labels": ["label1"]
}
Required Fields:
name (string) - Project nameworkspaceId (string) - Workspace IDOptional Fields:
dueDate (datetime, ISO 8601) - Project deadlinedescription (string) - HTML input acceptedlabels (array) - Label namespriority (string) - ASAP, HIGH, MEDIUM (default), or LOWprojectDefinitionId (string) - Template ID (requires stages array if provided)stages (array) - Stage objects for project templatesGET /motion/v1/workspaces
GET /motion/v1/users?workspaceId={workspaceId}
Query Parameters:
workspaceId (string) - Workspace ID (required if no teamId)teamId (string) - Team ID (required if no workspaceId)Note: You must provide either workspaceId or teamId.
GET /motion/v1/users/me
GET /motion/v1/comments?taskId={taskId}
Query Parameters:
taskId (string, required) - Filter comments by taskcursor (string) - Pagination cursorPOST /motion/v1/comments
Content-Type: application/json
{
"taskId": "TASK_ID",
"content": "Comment in GitHub Flavored Markdown"
}
Required Fields:
taskId (string) - Task to comment onOptional Fields:
content (string) - Comment content in GitHub Flavored MarkdownGET /motion/v1/recurring-tasks?workspaceId={workspaceId}
Query Parameters:
workspaceId (string, required) - Filter by workspacecursor (string) - Pagination cursorPOST /motion/v1/recurring-tasks
Content-Type: application/json
{
"name": "Weekly review",
"workspaceId": "WORKSPACE_ID",
"frequency": "weekly"
}
DELETE /motion/v1/recurring-tasks/{recurringTaskId}
GET /motion/v1/schedules
GET /motion/v1/statuses?workspaceId={workspaceId}
Query Parameters:
workspaceId (string, required) - Filter by workspaceGET /motion/v1/custom-fields
POST /motion/v1/custom-fields
Content-Type: application/json
{
"name": "Field name",
"type": "text"
}
DELETE /motion/v1/custom-fields/{customFieldId}
POST /motion/v1/custom-fields/{customFieldId}/project
Content-Type: application/json
{
"projectId": "PROJECT_ID"
}
POST /motion/v1/custom-fields/{customFieldId}/task
Content-Type: application/json
{
"taskId": "TASK_ID"
}
DELETE /motion/v1/custom-fields/{customFieldId}/project
DELETE /motion/v1/custom-fields/{customFieldId}/task
Motion uses cursor-based pagination:
GET /motion/v1/tasks?cursor=CURSOR_VALUE
Response includes pagination metadata:
{
"tasks": [...],
"meta": {
"nextCursor": "abc123",
"pageSize": 20
}
}
Use the nextCursor value in subsequent requests to retrieve more results.
const response = await fetch(
'https://api.maton.ai/motion/v1/tasks',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/motion/v1/tasks',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
curl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Missing Motion connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Motion API |
共 2 个版本