Access the ClickUp API with managed OAuth authentication. Manage tasks, lists, folders, spaces, workspaces, users, and webhooks for work management.
# List workspaces (teams)
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/team')
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/clickup/{native-api-path}
Maton proxies requests to api.clickup.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 ClickUp OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=clickup&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': 'clickup'}).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": "clickup",
"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 ClickUp 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/clickup/api/v2/team')
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.
ClickUp organizes data in a hierarchy:
Note: In the API, Workspaces are referred to as "teams".
GET /clickup/api/v2/team
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/team')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"teams": [
{
"id": "1234567",
"name": "Acme Corp",
"color": "#7B68EE",
"avatar": null,
"members": [
{
"user": {
"id": 123,
"username": "Alice Johnson",
"email": "alice@acme.com"
}
}
]
}
]
}
GET /clickup/api/v2/team/{team_id}/space
Query parameters:
archived - Include archived spaces (true/false)Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/team/1234567/space')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"spaces": [
{
"id": "90120001",
"name": "Engineering",
"private": false,
"statuses": [
{"status": "to do", "type": "open"},
{"status": "in progress", "type": "custom"},
{"status": "done", "type": "closed"}
]
}
]
}
GET /clickup/api/v2/space/{space_id}
POST /clickup/api/v2/team/{team_id}/space
Example:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'name': 'New Space', 'multiple_assignees': True, 'features': {'due_dates': {'enabled': True}, 'time_tracking': {'enabled': True}}}).encode()
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/team/1234567/space', 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
PUT /clickup/api/v2/space/{space_id}
DELETE /clickup/api/v2/space/{space_id}
GET /clickup/api/v2/space/{space_id}/folder
Query parameters:
archived - Include archived folders (true/false)Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/space/90120001/folder')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"folders": [
{
"id": "456789",
"name": "Sprint 1",
"orderindex": 0,
"hidden": false,
"space": {"id": "90120001", "name": "Engineering"},
"task_count": "12",
"lists": []
}
]
}
GET /clickup/api/v2/folder/{folder_id}
POST /clickup/api/v2/space/{space_id}/folder
Example:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'name': 'New Folder'}).encode()
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/space/90120001/folder', 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
PUT /clickup/api/v2/folder/{folder_id}
DELETE /clickup/api/v2/folder/{folder_id}
GET /clickup/api/v2/folder/{folder_id}/list
Query parameters:
archived - Include archived lists (true/false)Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/folder/456789/list')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"lists": [
{
"id": "901234",
"name": "Backlog",
"orderindex": 0,
"status": {"status": "active", "color": "#87909e"},
"task_count": 25,
"folder": {"id": "456789", "name": "Sprint 1"}
}
]
}
GET /clickup/api/v2/space/{space_id}/list
GET /clickup/api/v2/list/{list_id}
POST /clickup/api/v2/folder/{folder_id}/list
Example:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'name': 'New List'}).encode()
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/folder/456789/list', 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
POST /clickup/api/v2/space/{space_id}/list
PUT /clickup/api/v2/list/{list_id}
DELETE /clickup/api/v2/list/{list_id}
GET /clickup/api/v2/list/{list_id}/task
Query parameters:
archived - Include archived tasks (true/false)page - Page number (0-indexed)order_by - Sort by field (created, updated, due_date)reverse - Reverse sort order (true/false)subtasks - Include subtasks (true/false)statuses[] - Filter by statusinclude_closed - Include closed tasks (true/false)assignees[] - Filter by assignee IDsdue_date_gt - Due date greater than (Unix ms)due_date_lt - Due date less than (Unix ms)Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/list/901234/task?include_closed=true')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"tasks": [
{
"id": "abc123",
"name": "Implement login feature",
"status": {"status": "in progress", "type": "custom", "color": "#4194f6"},
"priority": {"id": "2", "priority": "high", "color": "#f9d900"},
"due_date": "1709251200000",
"assignees": [{"id": 123, "username": "Alice Johnson", "email": "alice@acme.com"}],
"description": "Add OAuth login flow",
"date_created": "1707436800000",
"date_updated": "1708646400000"
}
]
}
GET /clickup/api/v2/task/{task_id}
Query parameters:
custom_task_ids - Use custom task IDs (true/false)team_id - Required when using custom_task_idsinclude_subtasks - Include subtasks (true/false)Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/task/abc123')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
POST /clickup/api/v2/list/{list_id}/task
Content-Type: application/json
{
"name": "Task name",
"description": "Task description",
"assignees": [123],
"status": "to do",
"priority": 2,
"due_date": 1709251200000,
"tags": ["api", "backend"],
"parent": null
}
Fields:
name (required) - Task titledescription - Task description (supports markdown)assignees - Array of user IDsstatus - Status name (must match a status in the list)priority - Priority level (1=urgent, 2=high, 3=normal, 4=low, null=none)due_date - Unix timestamp in millisecondsdue_date_time - Include time in due date (true/false)start_date - Unix timestamp in millisecondstime_estimate - Time estimate in millisecondstags - Array of tag namesparent - Parent task ID (for subtasks)custom_fields - Array of custom field objectsExample:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'name': 'Complete API integration', 'description': 'Integrate with the new external API', 'priority': 2, 'due_date': 1709251200000, 'assignees': [123]}).encode()
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/list/901234/task', 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
PUT /clickup/api/v2/task/{task_id}
Example:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'status': 'complete', 'priority': None}).encode()
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/task/abc123', data=data, method='PUT')
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
DELETE /clickup/api/v2/task/{task_id}
GET /clickup/api/v2/team/{team_id}/task
Query parameters:
page - Page number (0-indexed)order_by - Sort fieldstatuses[] - Filter by statusesassignees[] - Filter by assigneeslist_ids[] - Filter by list IDsspace_ids[] - Filter by space IDsfolder_ids[] - Filter by folder IDsGET /clickup/api/v2/user
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/user')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"user": {
"id": 123,
"username": "Alice Johnson",
"email": "alice@acme.com",
"color": "#7B68EE",
"profilePicture": "https://...",
"initials": "AJ",
"week_start_day": 0,
"timezone": "America/New_York"
}
}
GET /clickup/api/v2/team/{team_id}/webhook
Example:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/team/1234567/webhook')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
POST /clickup/api/v2/team/{team_id}/webhook
Content-Type: application/json
{
"endpoint": "https://example.com/webhook",
"events": ["taskCreated", "taskUpdated", "taskDeleted"],
"space_id": "90120001",
"folder_id": "456789",
"list_id": "901234",
"task_id": "abc123"
}
Events:
taskCreated, taskUpdated, taskDeletedtaskPriorityUpdated, taskStatusUpdatedtaskAssigneeUpdated, taskDueDateUpdatedtaskTagUpdated, taskMovedtaskCommentPosted, taskCommentUpdatedtaskTimeEstimateUpdated, taskTimeTrackedUpdatedlistCreated, listUpdated, listDeletedfolderCreated, folderUpdated, folderDeletedspaceCreated, spaceUpdated, spaceDeletedgoalCreated, goalUpdated, goalDeletedkeyResultCreated, keyResultUpdated, keyResultDeletedExample:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'endpoint': 'https://example.com/webhook', 'events': ['taskCreated', 'taskUpdated']}).encode()
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/team/1234567/webhook', 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
Response:
{
"id": "webhook123",
"webhook": {
"id": "webhook123",
"userid": 123,
"team_id": "1234567",
"endpoint": "https://example.com/webhook",
"client_id": "...",
"events": ["taskCreated", "taskUpdated"],
"health": {"status": "active", "fail_count": 0},
"secret": "..."
}
}
PUT /clickup/api/v2/webhook/{webhook_id}
DELETE /clickup/api/v2/webhook/{webhook_id}
ClickUp uses page-based pagination. Use the page parameter (0-indexed):
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clickup/api/v2/list/901234/task?page=0')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Responses are limited to 100 tasks per page. The response includes a last_page boolean field. Continue incrementing the page number until last_page is true.
const response = await fetch(
'https://api.maton.ai/clickup/api/v2/list/901234/task',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/clickup/api/v2/list/901234/task',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
curl -g when URLs contain brackets (statuses[], assignees[], list_ids[]) to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Bad request or missing ClickUp connection |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden - insufficient permissions |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from ClickUp API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
clickup. For example:https://api.maton.ai/clickup/api/v2/teamhttps://api.maton.ai/api/v2/team共 2 个版本