{"id":14066076,"url":"https://github.com/psolymos/clickrup","last_synced_at":"2025-07-21T17:32:48.315Z","repository":{"id":42193222,"uuid":"271406394","full_name":"psolymos/clickrup","owner":"psolymos","description":"Interacting with the ClickUp v2 API from R","archived":false,"fork":false,"pushed_at":"2024-08-07T13:56:40.000Z","size":9099,"stargazers_count":18,"open_issues_count":5,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-19T16:46:42.188Z","etag":null,"topics":["api","clickup","clickup-api","project-management","r","rstats"],"latest_commit_sha":null,"homepage":"https://peter.solymos.org/clickrup/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/psolymos.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-10T23:28:29.000Z","updated_at":"2024-07-12T19:14:02.000Z","dependencies_parsed_at":"2024-08-13T07:10:27.959Z","dependency_job_id":"6606c6fc-b4d4-4e02-823f-1276b418dff5","html_url":"https://github.com/psolymos/clickrup","commit_stats":{"total_commits":86,"total_committers":4,"mean_commits":21.5,"dds":"0.13953488372093026","last_synced_commit":"15f888195d8851258211102f2d232990944a271b"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/psolymos/clickrup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fclickrup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fclickrup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fclickrup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fclickrup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/psolymos","download_url":"https://codeload.github.com/psolymos/clickrup/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fclickrup/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266342809,"owners_count":23914262,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","clickup","clickup-api","project-management","r","rstats"],"created_at":"2024-08-13T07:04:55.609Z","updated_at":"2025-07-21T17:32:48.270Z","avatar_url":"https://github.com/psolymos.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"---\noutput:\n  md_document:\n    variant: gfm\n---\n\n```{r, echo=FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"README-\"\n)\n```\n\n# clickrup \u003cimg src=\"https://raw.githubusercontent.com/psolymos/clickrup/master/inst/images/clickrup.jpg\" align=\"right\" style=\"padding-left:10px;background-color:white;\" width=\"200px\" /\u003e\n\n[![clickrup status badge](https://psolymos.r-universe.dev/badges/clickrup)](https://psolymos.r-universe.dev)\n\n\u003e Interacting with the ClickUp v2 API from R\n\n[ClickUp](https://clickup.com/?noRedirect=true) is a cloud-based collaboration and project management tool. \nFeatures include tasks, docs, chat, goals, and [more](https://clickup.com/features).\n\nThe {clickrup} R package wraps the ClickUp [API v2](https://clickup.com/api). \nSee the [roadmap](https://github.com/psolymos/clickrup/issues/1) for what is currently included in the package.\n\n## Setup\n\nInstall the {clickrup} package:\n\n```{r eval=FALSE}\n## using remotes\nremotes::install_github(\"psolymos/clickrup\")\n\n## with r-universe\noptions(repos = c(\n    psolymos = \"https://psolymos.r-universe.dev\",\n    CRAN = \"https://cloud.r-project.org\"))\ninstall.packages('clickrup')\n```\n\nFollow this [tutorial](https://docs.clickup.com/en/articles/1367130-getting-started-with-the-clickup-api):\n\n- sign up for ClickUp (you can use this referral [link](https://clickup.com?fp_ref=peter51) to do so, it's free),\n- navigate to your personal *Settings*,\n- click *Apps* in the left sidebar,\n- click *Generate* to create your API token,\n- click *Copy* to copy the token to your clipboard.\n\nNow add your ClickUp token as an environment variable:\n\n- open the file `.Renviron`: `file.edit(\"~/.Renviron\")`,\n- add a line with `CU_PAT=\"your_token\"` to the `.Renviron` file and save it,\n- check with `Sys.getenv(\"CU_PAT\")`, it should return the token.\n\nThe ClickUp token will look something like \n`pk_4753994_EXP7MPOJ7XQM5UJDV2M45MPF0YHH5YHO`.\n\nThe `cu_set_pat` function uses `Sys.setenv` to set\nthe `CU_PAT` environment variable for other processes called from within R or future calls to `Sys.getenv` from the same R process.\n\n## API endpoints\n\nThe first step you want to do is to get the IDs for your workspaces (teams is the legacy term for this in the API).\n\nIf your setup was successful, `cu_get_teams()` should return a list with the workspace IDs and names.\n\nThe easiest way to get going with the various endpoints is to browse the [API v2 documentation](https://clickup.com/api).\nOnce you found what you are after, just look at the API heading. For example, for **Get Teams**, the R function\nis prepended with `cu_` (to facilitate RStudio code completion), \nthen comes the heading in lower case and spaces replaced by underscores.\nSimilarly, **Get Filtered Team Tasks** will be `cu_get_filtered_team_tasks()`.\nArticles (a, an, the) are dropped (e.g. **Create a Time Entry**)\nwill be `cu_create_time_entry()`.\n\nFunction arguments are the *Parameters* listed on the API page, `...` passes optional parameters, query parameters, \nor elements for the body.\n\n## Examples\n\nLoad the package and set the access token if it is not already set.\n`cu_get_pat()` returns the token invisibly, so it doesn't\nend up in logs.\n\n```{r}\nlibrary(clickrup)\ncu_get_pat() # returns PAT invisibly\n```\n\n### ClickUp hierarchy\n\nThe [ClickUp hierarchy](https://docs.clickup.com/en/articles/1045623-how-does-the-hierarchy-structure-work-in-clickup) includes the following levels:\n\n- Workspaces (teams is the legacy term for this in the API)\n- Spaces\n- Folders\n- Lists\n- Tasks\n- Subtasks\n- Checklists\n\nWe can list Workspaces that we have access to using the `cu_get_teams()`\nfunction. It takes no arguments, it only passes the access token\nbehind the scenes, so it is a good way to test if things are\nworking as expected\n\n```{r}\nTeams \u003c- cu_get_teams()\nstr(Teams, 3)\n```\n\nSpaces within a specific Workspace defined by its `team_id`\n\n```{r}\nteam_id \u003c- Teams$teams[[2]]$id\nSpaces \u003c- cu_get_spaces(team_id)\nstr(Spaces, 3)\n```\n\nFolders within a specific Space defined by its `space_id`\n\n```{r}\nspace_id \u003c- Spaces$spaces[[2]]$id\nFolders \u003c- cu_get_folders(space_id)\nstr(Folders, 3)\n```\n\nLists within a specific Folder defined by its `folder_id`\n(or Folderless Lists based on `space_id`)\n\n```{r}\nfolder_id \u003c- Folders$folders[[1]]$id\nLists \u003c- cu_get_lists(folder_id)\nstr(Lists, 3)\n\ncu_get_lists_folderless(space_id)\n```\n\nThe functions `cu_get_spaces`, `cu_get_folders`, and `cu_get_lists`\naccept the argument `archived` to return archived spaces/folders/lists\n\n```{r}\nstr(cu_get_lists(folder_id, archived=TRUE), 3)\n```\n\n### Tasks\n\nWe can list Tasks within a specific List defined by its `list_id`\n\n```{r}\nlist_id \u003c- Lists$lists[[1]]$id\nTasks \u003c- cu_get_tasks(list_id)\nstr(Tasks, 2)\n```\n\nNotice that we have `r length(Tasks$tasks)` tasks in the list.\nWe can include Subtasks too\n\n```{r}\nsubTasks \u003c- cu_get_tasks(list_id, subtasks=TRUE)\nlength(subTasks$tasks)\n```\n\nGetting all the tasks (possibly filtered) in a Workspace\nis done via the `cu_get_filtered_team_tasks` function.\nThis function returns tasks in batches of 100.\nIf you don't want to deal with paging, use the\nwrapper function `cu_get_all_team_tasks`\nThe list of tasks returned does not include closed tasks,\nto get those as well we need to pass the `include_closed`\nquery parameter\n\n```{r}\n## without closed tasks\nlength(cu_get_all_team_tasks(team_id, subtasks=TRUE)$tasks)\n\n## with closed tasks\nallSubTasks \u003c- cu_get_all_team_tasks(team_id, subtasks=TRUE,\n                                include_closed=TRUE)\nlength(allSubTasks$tasks)\n\nStatus \u003c- sapply(allSubTasks$tasks, function(z) z$status$status)\ndata.frame(table(Status))\n```\n\nLet's inspect the first few elements of a Task object\n\n```{r}\nstr(Tasks$tasks[[1]][1:10])\n```\n\nDates are given as Unix time (in milliseconds),\n`cu_date_from` and `cu_date_to` is there to convert back and forth\n\n```{r}\nTasks$tasks[[1]]$date_created\ncu_date_from(Tasks$tasks[[1]]$date_created)\ncu_date_to(cu_date_from(Tasks$tasks[[1]]$date_created))\n```\n\nA single task can be accessed through the task ID\n(note: copying the task ID from the ClickUp GUI will prepend\nthe task ID by a hash, `\"#8ckjp5\"`, but the API expects\nID without the hash `\"8ckjp5\"`). Use the `cu_task_id` function to get\nrid of the leading hash (all API call use this function to\nnormalize task IDs).\n\nThe `$parent` property is `NULL` for Tasks, and \nit contains the parent Task ID for Subtasks\n\n```{r}\nx1 \u003c- cu_get_task(cu_task_id(\"#8ckjp5\")) # task\nx1$parent\n\nx2 \u003c- cu_get_task(\"8ckjru\") # subtask\nx2$parent\n```\n\nDependencies are stored in the `$dependencies` property\n\n```{r}\nstr(x1$dependencies)\n```\n\n### Helper functions\n\n`cu_options` stores the API settings\n\n```{r}\nstr(cu_options())\n```\n\n`cu_response` allows inspecting the response object\n\n```{r}\ncu_response(Teams)\n```\n\nCheck rate limits and remaining requests (rate is limited by the minute)\n\n```{r}\ncu_ratelimit(subTasks)\n```\n\n### Formatting the request body\n\n`PUSH` and `PUT` requests often require to send data as part of the\nrequest body. Check the API examples and use `I()` when the API expects an\narray as part of the body. For example when passing data to\n`cu_create_task`, `assignees` is an array of the assignees' \nuserids to be added. Adding a single userid without `I()` will\ndrop the brackets, but\n`list(name = \"New Task Name\", assignees = I(183))` will result in\nthe expected JSON object:\n`{ \"name\": \"New Task Name\", \"assignees\": [183] }`.\n\n### Attachments\n\nWe can upload files as attachments to tasks:\n\n```{r eval=FALSE}\nf \u003c- file.path(tempdir(), \"example.png\")\n\npng(f)\nhist(rnorm(10^6), col=2, main=\"Example\")\ndev.off()\n\ncu_post_task_attachment(\"8ach57\", f)\n\nunlink(f) # delete file\n```\n\n## Issues\n\nhttps://github.com/psolymos/clickrup/issues\n\n## License\n\n[MIT](LICENSE) \u0026copy; 2020 Peter Solymos\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsolymos%2Fclickrup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpsolymos%2Fclickrup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsolymos%2Fclickrup/lists"}