'Manage ClickUp tasks via API v2: create, read, update, delete tasks
Scanned 9/2/2026
Install to Claude Code
npx -y skills add jeremylongshore/tons-of-skills-marketplace --skill clickup-core-workflow-a --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Clickup Core Workflow A?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeremylongshore-clickup-core-workflow-a-tons-of-skills-marketplace)More formats (shields.io, HTML) on the badges page.
---
name: clickup-core-workflow-a
description: 'Manage ClickUp tasks via API v2: create, read, update, delete tasks
with
assignees, priorities, due dates, subtasks, and statuses.
Trigger: "clickup task", "create clickup task", "update task status",
"manage clickup tasks", "clickup CRUD", "clickup task management".
'
allowed-tools: Read, Write, Edit, Bash(curl:*), Grep
version: 1.6.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
tags:
- saas
- productivity
- clickup
compatibility: Designed for Claude Code
---
# ClickUp Core Workflow A — Task Management
## Overview
CRUD operations on ClickUp tasks via API v2. Tasks live in Lists and support assignees, priorities (1-4), statuses, due dates, tags, checklists, and custom fields.
## Prerequisites
- A scoped ClickUp API/OAuth token and verified workspace/list permission
- Approved target list, task schema, assignee policy, and data classification
- Idempotency/reconciliation approach for any create or bulk update operation
- A non-production or limited pilot path for automation changes
## Instructions
Resolve workspace, list, task, and custom-field IDs before mutation; validate
the intended state and actor authorization, then make one bounded create/update
or batch. Record the returned task ID and re-read its material fields to
confirm the desired result. Fail closed on unknown status, list, assignee, or
permission rather than falling back to a broader workspace action.
## Endpoints
| Operation | Method | Endpoint |
|-----------|--------|----------|
| Create task | POST | `/api/v2/list/{list_id}/task` |
| Get task | GET | `/api/v2/task/{task_id}` |
| Update task | PUT | `/api/v2/task/{task_id}` |
| Delete task | DELETE | `/api/v2/task/{task_id}` |
| Get tasks in list | GET | `/api/v2/list/{list_id}/task` |
| Add task to list | POST | `/api/v2/list/{list_id}/task/{task_id}` |
| Create subtask | POST | `/api/v2/list/{list_id}/task` (with `parent` field) |
## Create Task
```typescript
interface CreateTaskBody {
name: string; // Required
description?: string; // Plain text
markdown_description?: string; // Markdown (use instead of description)
assignees?: number[]; // Array of user IDs
tags?: string[]; // Tag names
status?: string; // Status name (e.g., "to do", "in progress")
priority?: 1 | 2 | 3 | 4 | null; // 1=Urgent, 2=High, 3=Normal, 4=Low
due_date?: number; // Unix timestamp in milliseconds
due_date_time?: boolean; // true = show time, false = date only
start_date?: number; // Unix ms
start_date_time?: boolean;
time_estimate?: number; // Time estimate in milliseconds
notify_all?: boolean; // Notify assignees
parent?: string; // Parent task ID (creates subtask)
links_to?: string; // Task ID to link to
custom_fields?: Array<{
id: string; // Custom field UUID
value: any; // Type-dependent value
}>;
}
async function createTask(listId: string, task: CreateTaskBody) {
return clickupRequest(`/list/${listId}/task`, {
method: 'POST',
body: JSON.stringify(task),
});
}
// Example: Create an urgent task with assignee
await createTask('900100200300', {
name: 'Fix production bug in auth module',
markdown_description: '## Bug\nLogin fails for SSO users\n\n## Steps\n1. Go to /login\n2. Click SSO',
assignees: [183],
priority: 1,
status: 'in progress',
due_date: Date.now() + 3600000,
due_date_time: true,
tags: ['bug', 'production'],
});
```
## Get Tasks (with Filtering)
```typescript
async function getTasks(listId: string, params: Record<string, string> = {}) {
const query = new URLSearchParams({
archived: 'false',
include_closed: 'false',
subtasks: 'true',
...params,
});
return clickupRequest(`/list/${listId}/task?${query}`);
}
// Filter by assignee and status
const tasks = await getTasks('900100200300', {
'assignees[]': '183',
'statuses[]': 'in progress',
order_by: 'due_date',
reverse: 'true',
page: '0', // Pagination: 100 tasks per page
});
// Response: { tasks: [...] }
```
## Update Task
```typescript
// Only include fields you want to change
async function updateTask(taskId: string, updates: Partial<CreateTaskBody>) {
return clickupRequest(`/task/${taskId}`, {
method: 'PUT',
body: JSON.stringify(updates),
});
}
// Change status and add assignee
await updateTask('abc123', {
status: 'complete',
assignees: { add: [456], rem: [] }, // Add/remove pattern for assignees on update
});
```
## Create Subtask
```typescript
await createTask('900100200300', {
name: 'Write unit tests for auth fix',
parent: 'abc123', // Parent task ID makes this a subtask
assignees: [183],
priority: 3,
});
```
## Bulk Operations
```typescript
// Get all tasks across workspace with team-level endpoint
async function searchTasks(teamId: string, query: string) {
return clickupRequest(`/team/${teamId}/task?${new URLSearchParams({
page: '0',
order_by: 'updated',
reverse: 'true',
include_closed: 'true',
subtasks: 'true',
})}`);
}
```
## Error Handling
| Status | Cause | Solution |
|--------|-------|----------|
| 400 | Missing `name` field | Task name is required |
| 401 | Invalid token | Re-authenticate |
| 404 | Invalid list_id or task_id | Verify IDs via GET endpoints |
| 403 | No permission on this list | Check workspace membership |
## Output
Return a redacted task-operation record with target IDs, requested and observed
state, idempotency key, actor scope, validation result, and rollback/recovery
decision. Do not include task descriptions, tokens, private comments, or full
member data in general logs or automation receipts.
## Examples
Create one staging task with a deterministic external key, re-read the task to
verify status and assignee, then repeat the request to prove it does not create
a duplicate. If the list or assignee is unauthorized, return a classified
failure and ask the owner to correct scope instead of switching to an admin key.
## Resources
- [Create Task API](https://developer.clickup.com/reference/createtask)
- [Update Task API](https://developer.clickup.com/reference/updatetask)
- [Get Tasks API](https://developer.clickup.com/reference/gettasks)
## Next Steps
For spaces, folders, and lists management see `clickup-core-workflow-b`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!