clickup

Use when managing ClickUp tasks, lists, spaces, time tracking, comments, or any project management operation via the ClickUp REST API. Triggers on "clickup", "task", "project management", "time entry", "workspace"

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "clickup" with this command: npx skills add brightprogrammer7/clickup-skills/brightprogrammer7-clickup-skills-clickup

ClickUp API Skill (No MCP)

Overview

Interact with ClickUp workspaces using direct REST API calls (curl). No MCP server required — just a personal API token stored in CLICKUP_TOKEN.

Setup

1. Get Your API Token

Go to ClickUp > Settings > Apps > API Token and generate a personal token.

2. Store Token

export CLICKUP_TOKEN="pk_YOUR_TOKEN_HERE"

Store in .env or export before running commands.

3. Persist Token (Recommended)

Add to ~/.zshrc or ~/.zprofile so it survives shell restarts:

export CLICKUP_TOKEN="pk_YOUR_TOKEN_HERE"

Note: Tokens set only in the terminal session won't be inherited by Claude Code's Bash subshells. Persisting in your shell profile ensures it's always available.

4. Verify Connection

curl -s --header "Authorization: $CLICKUP_TOKEN" \
  https://api.clickup.com/api/v2/user | python3 -m json.tool

zsh tip: Always use --header instead of -H in Claude Code's Bash tool — -H can be misinterpreted as a shell flag in zsh subshells.

ClickUp Hierarchy

Workspace (Team) → Space → Folder (optional) → List → Task → Subtask

Key terminology: In API v2, "Team" = Workspace, "Project" = Folder.

Quick Reference

ActionMethodEndpoint
Get userGET/api/v2/user
Get workspacesGET/api/v2/team
Get spacesGET/api/v2/team/{team_id}/space
Get foldersGET/api/v2/space/{space_id}/folder
Get lists (folder)GET/api/v2/folder/{folder_id}/list
Get lists (folderless)GET/api/v2/space/{space_id}/list
Get tasksGET/api/v2/list/{list_id}/task
Get single taskGET/api/v2/task/{task_id}
Create taskPOST/api/v2/list/{list_id}/task
Update taskPUT/api/v2/task/{task_id}
Delete taskDELETE/api/v2/task/{task_id}
Get commentsGET/api/v2/task/{task_id}/comment
Add commentPOST/api/v2/task/{task_id}/comment
Get custom fieldsGET/api/v2/list/{list_id}/field
Set custom fieldPOST/api/v2/task/{task_id}/field/{field_id}
Get time entriesGET/api/v2/team/{team_id}/time_entries
Create time entryPOST/api/v2/team/{team_id}/time_entries
Start timerPOST/api/v2/team/{team_id}/time_entries/start
Stop timerPOST/api/v2/team/{team_id}/time_entries/stop
Get members (task)GET/api/v2/task/{task_id}/member
Get members (list)GET/api/v2/list/{list_id}/member
Get tagsGET/api/v2/space/{space_id}/tag
Get goalsGET/api/v2/team/{team_id}/goal
Create webhookPOST/api/v2/team/{team_id}/webhook

Base URL: https://api.clickup.com

Common Workflows

Discovery: Find Your Workspace → Space → List IDs

# Step 1: Get workspace (team) ID
curl -s --header "Authorization: $CLICKUP_TOKEN" \
  https://api.clickup.com/api/v2/team | python3 -c "
import sys, json
teams = json.load(sys.stdin)['teams']
for t in teams:
    print(f\"{t['id']}: {t['name']}\")"

# Step 2: Get spaces in workspace
curl -s --header "Authorization: $CLICKUP_TOKEN" \
  "https://api.clickup.com/api/v2/team/{TEAM_ID}/space" | python3 -c "
import sys, json
spaces = json.load(sys.stdin)['spaces']
for s in spaces:
    print(f\"{s['id']}: {s['name']}\")"

# Step 3: Get lists (folderless)
curl -s --header "Authorization: $CLICKUP_TOKEN" \
  "https://api.clickup.com/api/v2/space/{SPACE_ID}/list" | python3 -c "
import sys, json
lists = json.load(sys.stdin)['lists']
for l in lists:
    print(f\"{l['id']}: {l['name']}\")"

Search for a Task by Name

curl -s --header "Authorization: $CLICKUP_TOKEN" \
  "https://api.clickup.com/api/v2/team/{TEAM_ID}/task?search=Task+Name&subtasks=true&include_closed=true" | python3 -c "
import sys, json
for t in json.load(sys.stdin).get('tasks', []):
    print(f\"{t['id']}: [{t['status']['status']}] {t['name']}\")"

Get Available Statuses for a List

curl -s --header "Authorization: $CLICKUP_TOKEN" \
  "https://api.clickup.com/api/v2/list/{LIST_ID}" | python3 -c "
import sys, json
d = json.load(sys.stdin)
for s in d.get('statuses', []):
    print(f\"{s['status']} (type: {s['type']})\")
"

Create a Task

curl -s -X POST \
  --header "Authorization: $CLICKUP_TOKEN" \
  --header "Content-Type: application/json" \
  "https://api.clickup.com/api/v2/list/{LIST_ID}/task" \
  --data '{
    "name": "My New Task",
    "description": "Task description here",
    "status": "to do",
    "priority": 3,
    "assignees": [],
    "tags": [],
    "due_date": null,
    "notify_all": false
  }'

Priority values: 1 = Urgent, 2 = High, 3 = Normal, 4 = Low

Bulk Create Tasks (Python — Recommended for batches)

Use Python subprocess for bulk operations to avoid zsh flag interpretation issues:

import subprocess, json

TOKEN = "pk_YOUR_TOKEN"
LIST_ID = "YOUR_LIST_ID"

tasks = [
    ("Task name", "to do"),
    ("Another task", "in progress"),
    ("Finished task", "done"),
]

for name, status in tasks:
    payload = json.dumps({"name": name, "status": status})
    result = subprocess.run(
        ["curl", "-s", "-X", "POST",
         "--header", f"Authorization: {TOKEN}",
         "--header", "Content-Type: application/json",
         f"https://api.clickup.com/api/v2/list/{LIST_ID}/task",
         "--data", payload],
        capture_output=True, text=True
    )
    d = json.loads(result.stdout)
    print(f"[{d['status']['status']}] {d['name']}" if "id" in d else f"ERROR: {d.get('err')}")

Create a Subtask

Same as creating a task, but add "parent": "{parent_task_id}" to the JSON body.

Update a Task

curl -s -X PUT \
  --header "Authorization: $CLICKUP_TOKEN" \
  --header "Content-Type: application/json" \
  "https://api.clickup.com/api/v2/task/{TASK_ID}" \
  --data '{
    "name": "Updated Name",
    "status": "in progress",
    "priority": 2
  }'

Get Tasks with Pagination

PAGE=0
while true; do
  RESULT=$(curl -s --header "Authorization: $CLICKUP_TOKEN" \
    "https://api.clickup.com/api/v2/list/{LIST_ID}/task?page=$PAGE")
  COUNT=$(echo "$RESULT" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['tasks']))")
  echo "$RESULT" | python3 -c "
import sys, json
for t in json.load(sys.stdin)['tasks']:
    print(f\"{t['id']}: [{t['status']['status']}] {t['name']}\")"
  [ "$COUNT" -lt 100 ] && break
  PAGE=$((PAGE + 1))
done

Add a Comment

curl -s -X POST \
  --header "Authorization: $CLICKUP_TOKEN" \
  --header "Content-Type: application/json" \
  "https://api.clickup.com/api/v2/task/{TASK_ID}/comment" \
  --data '{
    "comment_text": "This is a comment from the API",
    "notify_all": false
  }'

Track Time

# Get time entries (date range in milliseconds)
curl -s --header "Authorization: $CLICKUP_TOKEN" \
  "https://api.clickup.com/api/v2/team/{TEAM_ID}/time_entries?start_date=1700000000000&end_date=1710000000000"

# Create a time entry (duration in milliseconds)
curl -s -X POST \
  --header "Authorization: $CLICKUP_TOKEN" \
  --header "Content-Type: application/json" \
  "https://api.clickup.com/api/v2/team/{TEAM_ID}/time_entries" \
  --data '{
    "tid": "{TASK_ID}",
    "description": "Working on feature",
    "start": 1700000000000,
    "duration": 3600000
  }'

Rate Limits

  • 100 requests/minute per token (all plans)
  • HTTP 429 returned when exceeded
  • Check response headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
  • Use webhooks instead of polling where possible

Pagination

  • Use page query param (0-indexed) with max 100 results per page
  • Loop until returned items < 100 (indicates last page)
  • Applies to: tasks, time entries, comments, and other list endpoints

Common Mistakes

MistakeFix
Using "workspace" in URLUse team — API v2 calls workspaces "teams"
Updating custom fields via PUT taskUse dedicated POST /task/{id}/field/{field_id} endpoint
Forgetting Content-Type header on POST/PUTAlways include Content-Type: application/json
Timestamps in secondsClickUp uses milliseconds (Unix epoch × 1000)
Not paginating task listsMax 100 per page — always implement pagination loop
Polling instead of webhooksSubscribe to webhook events for real-time updates
Using -H flag in zsh subshellsUse --header instead — -H is misinterpreted by zsh in some contexts
Token not available in Claude Code BashPersist token in ~/.zshrc or ~/.zprofile; session-only exports don't survive subshells
Trying to clear notifications via APIClickUp API v2 has no notification endpoint — clear them manually in the UI
Searching tasks without include_closed=trueClosed/done tasks are excluded by default; add include_closed=true to find them

Webhook Events

Subscribe to events: taskCreated, taskUpdated, taskDeleted, listCreated, listUpdated, listDeleted, folderCreated, folderUpdated, folderDeleted, spaceCreated, spaceUpdated, spaceDeleted, goalCreated, goalUpdated, goalDeleted.

See clickup-api-reference.md for the full endpoint reference.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

clickup

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

clickup

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

clickup

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

clickup

No summary provided by upstream source.

Repository SourceNeeds Review