ClickUp Integration¶
Usage is based on idk/services/connector_clickup.py.
Quick start¶
from idk.services.connector_clickup import ClickUpConnector
connector = ClickUpConnector() # uses settings.CLICKUP_API_KEY by default
me = connector.get_info_user()
Required settings:
- CLICKUP_API_URL (e.g., https://api.clickup.com/api/v2/)
- CLICKUP_TEAM_ID
- CLICKUP_API_KEY
Core methods¶
- get_info_user() -> dict | None: returns authenticated user info
- get_members() -> list[dict]: ClickUp team members (normalized)
- get_tasks(clickup_project, first_date, second_date) -> dict: tasks filtered by update date
- get_tasks_by_member(member_id: str | None) -> list[dict]: tasks for member (paginated)
- create_task_in_list(list_id: str, payload: dict) -> dict | None: create task in a list
- update_task_status(task_id: str, status: str) -> bool: set task status
- find_task_by_custom_field(list_id: str, custom_field_id: str, field_value: str) -> str | None: returns first task id
Parameters notes:
- dates: use timezone-aware datetimes; method filters by task_updated date
- payload: follow ClickUp API task schema (name, status, assignees, etc.)
Examples¶
Create a task and then mark it closed:
payload = {"name": "My task", "status": "to do"}
new_task = connector.create_task_in_list(list_id="123", payload=payload)
if new_task:
connector.update_task_status(new_task["id"], status="closed")
Time entries¶
- create_time_entry(task: TaskInstance, data: dict) -> bool: creates time entry via
team/{team_id}/time_entriesand mirrors it locally - get_clickup_time_entries(start_date: int|str|None, end_date: int|str|None, assignee: str|None, space_id: int|None, folder_id: int|None, list_id: int|None, task_id: str|None, custom_task_ids=False, include_task_tags=True, include_location_names=True) -> list[TimeEntry]
- get_clickup_running_time_entry(assignee_id: int) -> dict | None
- get_last_time_entry_of_day(assignee_id: int, date: datetime.date) -> dict | None
- update_time_entry_billable(id: str, billable: bool) -> bool
Notes:
- start_date/end_date accept ms timestamps or "YYYY-MM-DD" strings.
- Returns use internal TimeEntry wrapper where noted.
Structure helpers¶
- build_clickup_map(level: int=1..4, force_refresh=True) -> dict: hierarchical map of spaces → folders → lists → tasks
- get_clickup_spaces(force_refresh=False) -> list[str]: non-private space IDs (cached)
- get_clickup_spaces_v2() -> list[Space]: typed wrapper objects
- get_clickup_folders_v2(space_id) -> list[Folder]
- get_clickup_lists_v2(folder_id) -> list[List]
- get_task_subtasks(task_id: str) -> list[dict]
List/folder/space management¶
- find_or_create_space(space_name: str) -> dict | None
- find_or_create_folder(space_id: str, folder_name: str, folder_id_from_list_data: str | None=None) -> dict | None
- find_or_create_list(folder_id: str, list_name: str) -> dict | None
- update_space(space_id, name=None) -> bool
- update_folder(folder_id, name=None) -> bool
- update_list(list_id, name=None, archived: bool | None=None) -> bool
- delete_list_from_clickup(list_id: str) -> bool (local cleanup when confirmed deleted in API)
Task utilities¶
- update_task(task_id: str, payload: dict) -> bool
- update_comment(comment_id: str, text: str) -> bool
- add_tag_to_task(task_id: str, tag_name: str) -> bool
- move_task_to_list(task_id: str, new_list_id: str) -> bool
- update_task_parent_and_list(task_id: str, new_list_id: str, new_parent_id: str) -> bool
- refresh_task_from_clickup(task_instance) -> TaskInstance | None
- get_task(task_id: str, update_task=False) -> TaskInstance | None
Data access (DB-backed)¶
- get_clickup_projects(force_refresh=False) -> list[dict]: projects derived from stored folders/spaces
- get_project_times(project, first_date, second_date) -> list[dict]
- get_tracked_time_by_id(task, time_entry_id) -> dict | None
Errors and retries¶
- Many calls raise or return None/False on failure. Wrap in try/except for network errors.
- Selected methods implement basic retry/backoff for 429 rate limits.
Refer to the source for full method set and advanced flows: idk/services/connector_clickup.py.