From f4a0502523375a1501d1cfa24c133855b5af9cc4 Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Thu, 23 Jul 2026 13:06:54 -0700 Subject: [PATCH 1/6] Add My folders API documentation Documents the per-user folders API under /my/stacks: listing a person's folders in home-screen order, reading a folder with its grouped projects, and creating, renaming, and deleting folders. --- README.md | 1 + sections/my_folders.md | 212 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 sections/my_folders.md diff --git a/README.md b/README.md index 1c9d54b..07b14da 100644 --- a/README.md +++ b/README.md @@ -314,6 +314,7 @@ API endpoints - [Message Types](sections/message_types.md#message-types) - [Messages](sections/messages.md#messages) - [My assignments](sections/my_assignments.md#my-assignments) +- [My folders](sections/my_folders.md#my-folders) - [My notes](sections/my_notes.md#my-notes) - [My notifications](sections/my_notifications.md#my-notifications) - [Out of office](sections/out_of_office.md#out-of-office) diff --git a/sections/my_folders.md b/sections/my_folders.md new file mode 100644 index 0000000..9700b8b --- /dev/null +++ b/sections/my_folders.md @@ -0,0 +1,212 @@ +My folders +========== + +Available since Basecamp 5: **folders** group [projects][projects] together on a +person's home screen. Folders are per-user — each person arranges their own home +into folders, and filing a project into a folder for yourself doesn't change how +anyone else sees it. Membership, ordering, and appearance all belong to the +authenticated user. + +For historical reasons the path and the wire type say `stack(s)` rather than +`folder(s)`; they are the same thing. + +Endpoints: + +- [Get my folders](#get-my-folders) +- [Get a folder](#get-a-folder) +- [Create a folder](#create-a-folder) +- [Update a folder](#update-a-folder) +- [Delete a folder](#delete-a-folder) + +[projects]: projects.md + +Get my folders +-------------- + +* `GET /my/stacks.json` returns the authenticated user's folders, in the order + they appear on the home screen. + +###### Example JSON Response + +```json +[ + { + "id": 2085958508, + "name": "Client work", + "type": "Stack", + "created_at": "2026-07-22T22:43:02.439Z", + "updated_at": "2026-07-22T22:43:02.572Z", + "bucket_ids": [], + "is_emoji_only_name": false, + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "gauges_url": null, + "color": null, + "image_url": null, + "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json" + } +] +``` + + +###### Copy as cURL + +```shell +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://3.basecampapi.com/$ACCOUNT_ID/my/stacks.json +``` + +Get a folder +------------ + +* `GET /my/stacks/2.json` returns the folder with an ID of `2`, including the + [projects][projects] grouped inside it under `projects`. + +###### Example JSON Response + +```json +{ + "id": 2085958508, + "name": "Client work", + "type": "Stack", + "created_at": "2026-07-22T22:43:02.439Z", + "updated_at": "2026-07-22T22:43:02.572Z", + "bucket_ids": [], + "is_emoji_only_name": false, + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "gauges_url": null, + "color": null, + "image_url": null, + "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json", + "projects": [] +} +``` + + +###### Copy as cURL + +```shell +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://3.basecampapi.com/$ACCOUNT_ID/my/stacks/2.json +``` + +Create a folder +--------------- + +* `POST /my/stacks.json` creates a new folder for the authenticated user and + files the given [projects][projects] into it. The folder is placed at the top + of the home screen. + +###### Optional parameters + +| Param | Type | Description | +| ------------- | --------------- | ----------- | +| `name` | String | The folder's name. Defaults to `New folder` when blank or omitted. | +| `project_ids` | Array | IDs of the projects to file into the folder. Each must be a project the user can access, or an all-access project they're eligible to join — filing an all-access project the user isn't yet a member of also grants them access to it. Archived, trashed, or invitation-only projects the user isn't on are rejected: the whole request returns `404 Not Found` and nothing is created. Omit for an empty folder. | + +###### Example JSON Request + +```json +{ + "name": "Client work", + "project_ids": [] +} +``` + + +A successful create returns `201 Created` with the new folder's JSON shape, +including its grouped `projects`: + +###### Example JSON Response + +```json +{ + "id": 2085958508, + "name": "Client work", + "type": "Stack", + "created_at": "2026-07-22T22:43:02.439Z", + "updated_at": "2026-07-22T22:43:02.572Z", + "bucket_ids": [], + "is_emoji_only_name": false, + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "gauges_url": null, + "color": null, + "image_url": null, + "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json", + "projects": [] +} +``` + + +###### Copy as cURL + +```shell +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ + -d '{"name":"Client work","project_ids":[]}' \ + https://3.basecampapi.com/$ACCOUNT_ID/my/stacks.json +``` + +Update a folder +--------------- + +* `PUT /my/stacks/2.json` renames the folder with an ID of `2`. Only `name` can + be changed; a folder's projects, ordering, and image are managed elsewhere. + +###### Permitted parameters + +| Param | Type | Description | +| ------ | ------ | ----------- | +| `name` | String | The folder's new name. | + +###### Example JSON Request + +```json +{ + "name": "Active client work" +} +``` + + +Returns `200 OK` with the updated folder's JSON shape: + +###### Example JSON Response + +```json +{ + "id": 2085958508, + "name": "Active client work", + "type": "Stack", + "created_at": "2026-07-22T22:43:02.439Z", + "updated_at": "2026-07-22T22:43:02.572Z", + "bucket_ids": [], + "is_emoji_only_name": false, + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "gauges_url": null, + "color": null, + "image_url": null, + "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json", + "projects": [] +} +``` + + +###### Copy as cURL + +```shell +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ + -d '{"name":"Active client work"}' -X PUT \ + https://3.basecampapi.com/$ACCOUNT_ID/my/stacks/2.json +``` + +Delete a folder +--------------- + +* `DELETE /my/stacks/2.json` deletes the folder with an ID of `2` and returns + `204 No Content`. Deleting a folder **unpins its projects** from the person's + home screen — the projects themselves are not deleted, and they are not moved + back out onto the home screen; they simply stop appearing there until pinned + again. + +###### Copy as cURL + +```shell +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -X DELETE \ + https://3.basecampapi.com/$ACCOUNT_ID/my/stacks/2.json +``` From ad0637293755f350cdf4affa790e54a06d1d51f7 Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Thu, 23 Jul 2026 14:01:40 -0700 Subject: [PATCH 2/6] Note the empty-folder forms for project_ids --- sections/my_folders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sections/my_folders.md b/sections/my_folders.md index 9700b8b..e165710 100644 --- a/sections/my_folders.md +++ b/sections/my_folders.md @@ -99,7 +99,7 @@ Create a folder | Param | Type | Description | | ------------- | --------------- | ----------- | | `name` | String | The folder's name. Defaults to `New folder` when blank or omitted. | -| `project_ids` | Array | IDs of the projects to file into the folder. Each must be a project the user can access, or an all-access project they're eligible to join — filing an all-access project the user isn't yet a member of also grants them access to it. Archived, trashed, or invitation-only projects the user isn't on are rejected: the whole request returns `404 Not Found` and nothing is created. Omit for an empty folder. | +| `project_ids` | Array | IDs of the projects to file into the folder. Each must be a project the user can access, or an all-access project they're eligible to join — filing an all-access project the user isn't yet a member of also grants them access to it. Archived, trashed, or invitation-only projects the user isn't on are rejected: the whole request returns `404 Not Found` and nothing is created. Omit it, or send `null` or an empty array, for an empty folder. | ###### Example JSON Request From 191e9f43503a321cd7815836879e0a502b31e1bd Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Mon, 27 Jul 2026 03:21:42 -0700 Subject: [PATCH 3/6] Sync API docs from bc3 --- README.md | 1 + sections/{my_folders.md => folders.md} | 88 +++++++++++++------------- 2 files changed, 45 insertions(+), 44 deletions(-) rename sections/{my_folders.md => folders.md} (69%) diff --git a/README.md b/README.md index bd8e7bc..ab04b9e 100644 --- a/README.md +++ b/README.md @@ -304,6 +304,7 @@ API endpoints - [Events](sections/events.md#events) - [Everything](sections/everything.md#everything) - [External links](sections/external_links.md#external-links) +- [Folders](sections/folders.md#folders) - [Forwards](sections/forwards.md#forwards) - [Gauges](sections/gauges.md#gauges) - [Google documents](sections/google_documents.md#google-documents) diff --git a/sections/my_folders.md b/sections/folders.md similarity index 69% rename from sections/my_folders.md rename to sections/folders.md index e165710..0fe9ee5 100644 --- a/sections/my_folders.md +++ b/sections/folders.md @@ -1,5 +1,5 @@ -My folders -========== +Folders +======= Available since Basecamp 5: **folders** group [projects][projects] together on a person's home screen. Folders are per-user — each person arranges their own home @@ -23,74 +23,74 @@ Endpoints: Get my folders -------------- -* `GET /my/stacks.json` returns the authenticated user's folders, in the order +* `GET /stacks.json` returns the authenticated user's folders, in the order they appear on the home screen. ###### Example JSON Response - + ```json [ { - "id": 2085958508, + "id": 2085958513, "name": "Client work", "type": "Stack", - "created_at": "2026-07-22T22:43:02.439Z", - "updated_at": "2026-07-22T22:43:02.572Z", + "created_at": "2026-07-27T10:16:49.312Z", + "updated_at": "2026-07-27T10:16:49.325Z", "bucket_ids": [], "is_emoji_only_name": false, - "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958513/stars.json", "gauges_url": null, "color": null, "image_url": null, - "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json" + "url": "https://3.basecampapi.com/195539477/stacks/2085958513.json" } ] ``` - + ###### Copy as cURL ```shell -curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://3.basecampapi.com/$ACCOUNT_ID/my/stacks.json +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://3.basecampapi.com/$ACCOUNT_ID/stacks.json ``` Get a folder ------------ -* `GET /my/stacks/2.json` returns the folder with an ID of `2`, including the +* `GET /stacks/2.json` returns the folder with an ID of `2`, including the [projects][projects] grouped inside it under `projects`. ###### Example JSON Response - + ```json { - "id": 2085958508, + "id": 2085958513, "name": "Client work", "type": "Stack", - "created_at": "2026-07-22T22:43:02.439Z", - "updated_at": "2026-07-22T22:43:02.572Z", + "created_at": "2026-07-27T10:16:49.312Z", + "updated_at": "2026-07-27T10:16:49.325Z", "bucket_ids": [], "is_emoji_only_name": false, - "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958513/stars.json", "gauges_url": null, "color": null, "image_url": null, - "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json", + "url": "https://3.basecampapi.com/195539477/stacks/2085958513.json", "projects": [] } ``` - + ###### Copy as cURL ```shell -curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://3.basecampapi.com/$ACCOUNT_ID/my/stacks/2.json +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://3.basecampapi.com/$ACCOUNT_ID/stacks/2.json ``` Create a folder --------------- -* `POST /my/stacks.json` creates a new folder for the authenticated user and +* `POST /stacks.json` creates a new folder for the authenticated user and files the given [projects][projects] into it. The folder is placed at the top of the home screen. @@ -102,51 +102,51 @@ Create a folder | `project_ids` | Array | IDs of the projects to file into the folder. Each must be a project the user can access, or an all-access project they're eligible to join — filing an all-access project the user isn't yet a member of also grants them access to it. Archived, trashed, or invitation-only projects the user isn't on are rejected: the whole request returns `404 Not Found` and nothing is created. Omit it, or send `null` or an empty array, for an empty folder. | ###### Example JSON Request - + ```json { "name": "Client work", "project_ids": [] } ``` - + A successful create returns `201 Created` with the new folder's JSON shape, including its grouped `projects`: ###### Example JSON Response - + ```json { - "id": 2085958508, + "id": 2085958513, "name": "Client work", "type": "Stack", - "created_at": "2026-07-22T22:43:02.439Z", - "updated_at": "2026-07-22T22:43:02.572Z", + "created_at": "2026-07-27T10:16:49.312Z", + "updated_at": "2026-07-27T10:16:49.325Z", "bucket_ids": [], "is_emoji_only_name": false, - "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958513/stars.json", "gauges_url": null, "color": null, "image_url": null, - "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json", + "url": "https://3.basecampapi.com/195539477/stacks/2085958513.json", "projects": [] } ``` - + ###### Copy as cURL ```shell curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{"name":"Client work","project_ids":[]}' \ - https://3.basecampapi.com/$ACCOUNT_ID/my/stacks.json + https://3.basecampapi.com/$ACCOUNT_ID/stacks.json ``` Update a folder --------------- -* `PUT /my/stacks/2.json` renames the folder with an ID of `2`. Only `name` can +* `PUT /stacks/2.json` renames the folder with an ID of `2`. Only `name` can be changed; a folder's projects, ordering, and image are managed elsewhere. ###### Permitted parameters @@ -156,49 +156,49 @@ Update a folder | `name` | String | The folder's new name. | ###### Example JSON Request - + ```json { "name": "Active client work" } ``` - + Returns `200 OK` with the updated folder's JSON shape: ###### Example JSON Response - + ```json { - "id": 2085958508, + "id": 2085958513, "name": "Active client work", "type": "Stack", - "created_at": "2026-07-22T22:43:02.439Z", - "updated_at": "2026-07-22T22:43:02.572Z", + "created_at": "2026-07-27T10:16:49.312Z", + "updated_at": "2026-07-27T10:16:50.464Z", "bucket_ids": [], "is_emoji_only_name": false, - "star_url": "https://3.basecampapi.com/195539477/buckets/2085958508/stars.json", + "star_url": "https://3.basecampapi.com/195539477/buckets/2085958513/stars.json", "gauges_url": null, "color": null, "image_url": null, - "url": "https://3.basecampapi.com/195539477/my/stacks/2085958508.json", + "url": "https://3.basecampapi.com/195539477/stacks/2085958513.json", "projects": [] } ``` - + ###### Copy as cURL ```shell curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ -d '{"name":"Active client work"}' -X PUT \ - https://3.basecampapi.com/$ACCOUNT_ID/my/stacks/2.json + https://3.basecampapi.com/$ACCOUNT_ID/stacks/2.json ``` Delete a folder --------------- -* `DELETE /my/stacks/2.json` deletes the folder with an ID of `2` and returns +* `DELETE /stacks/2.json` deletes the folder with an ID of `2` and returns `204 No Content`. Deleting a folder **unpins its projects** from the person's home screen — the projects themselves are not deleted, and they are not moved back out onto the home screen; they simply stop appearing there until pinned @@ -208,5 +208,5 @@ Delete a folder ```shell curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -X DELETE \ - https://3.basecampapi.com/$ACCOUNT_ID/my/stacks/2.json + https://3.basecampapi.com/$ACCOUNT_ID/stacks/2.json ``` From 3b6d0e4038fdb96d949e8cbee417e0c29b67ff4e Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Mon, 27 Jul 2026 09:29:39 -0700 Subject: [PATCH 4/6] Sync API docs from bc3 --- sections/folders.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sections/folders.md b/sections/folders.md index 0fe9ee5..9d1e60e 100644 --- a/sections/folders.md +++ b/sections/folders.md @@ -18,8 +18,6 @@ Endpoints: - [Update a folder](#update-a-folder) - [Delete a folder](#delete-a-folder) -[projects]: projects.md - Get my folders -------------- @@ -210,3 +208,5 @@ Delete a folder curl -s -H "Authorization: Bearer $ACCESS_TOKEN" -X DELETE \ https://3.basecampapi.com/$ACCOUNT_ID/stacks/2.json ``` + +[projects]: projects.md From df2b865906db98b874c67a2f00aa17357fff4320 Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Mon, 27 Jul 2026 09:48:14 -0700 Subject: [PATCH 5/6] Sync API docs from bc3 --- sections/folders.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sections/folders.md b/sections/folders.md index 9d1e60e..4f72b6a 100644 --- a/sections/folders.md +++ b/sections/folders.md @@ -12,14 +12,14 @@ For historical reasons the path and the wire type say `stack(s)` rather than Endpoints: -- [Get my folders](#get-my-folders) +- [Get folders](#get-folders) - [Get a folder](#get-a-folder) - [Create a folder](#create-a-folder) - [Update a folder](#update-a-folder) - [Delete a folder](#delete-a-folder) -Get my folders --------------- +Get folders +----------- * `GET /stacks.json` returns the authenticated user's folders, in the order they appear on the home screen. From c5efd00729722ee45c0107ec139a12dc62a682f8 Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Mon, 27 Jul 2026 10:04:24 -0700 Subject: [PATCH 6/6] Sync API docs from bc3 --- sections/folders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sections/folders.md b/sections/folders.md index 4f72b6a..e93fab6 100644 --- a/sections/folders.md +++ b/sections/folders.md @@ -97,7 +97,7 @@ Create a folder | Param | Type | Description | | ------------- | --------------- | ----------- | | `name` | String | The folder's name. Defaults to `New folder` when blank or omitted. | -| `project_ids` | Array | IDs of the projects to file into the folder. Each must be a project the user can access, or an all-access project they're eligible to join — filing an all-access project the user isn't yet a member of also grants them access to it. Archived, trashed, or invitation-only projects the user isn't on are rejected: the whole request returns `404 Not Found` and nothing is created. Omit it, or send `null` or an empty array, for an empty folder. | +| `project_ids` | Array | IDs of the projects to file into the folder — the same ids the folder reports back as `bucket_ids`. Each must be a project the user can access, or an all-access project they're eligible to join — filing an all-access project the user isn't yet a member of also grants them access to it. Archived, trashed, or invitation-only projects the user isn't on are rejected: the whole request returns `404 Not Found` and nothing is created. Omit it, or send `null` or an empty array, for an empty folder. | ###### Example JSON Request